jQuery tooltip is not displayed anymore after updating table data - javascript

I have a table with a single span element in td.
<table>
<tbody>
<tr>
<td id="td">
<span id="span1">this is span1</span>
</td>
</tr>
</tbody>
</table>
I create a jQuery tooltip for span1.
$('#span1').tooltip({
content: function(){
return "tooltip_span1";
},
items: $('#span1')
});
I update the content of td adding a second span with id 'span2' by concatenating.
var tdHtml = $('#td').html();
tdHtml+="<br> <span id=\"span2\">this is span2</span>"
$('#td').html(tdHtml);
I add a tooltip for span2 which will be displayed correctly.
$('#span2').tooltip({
content: function(){
return "tooltip_span2";
},
items: $('#span2')
});
However, the tooltip of span1 is not displayed anymore after updating the td content. Why?
Please see a jsFiddle example here.
Thanks very much for your answers.

You should use append, right now you are deleting and re-adding span1 (and removing previously added behavior)
$('#td').append("<br> <span id=\"span2\">this is span2</span>");
http://jsfiddle.net/dy7pq/2/

It looks like it's because you are treating the existing code as HTML and that the DOM reference is lost. It will work if instead you append a DOM fragment.
var newSpan = $('<span id="span2">this is span2</span>');
$('#td').append(newSpan);
See this fiddle for complete code: http://jsfiddle.net/harveyramer/b3xGM/1/

Related

Traversing on each span under table > tr > td > div

How to traverse on each span under table > tr > td > div ?
I would like to hide those span elements once click on the anchor tag that beneath the same tr level.
JSFiddle
$(document).ready(function() {
$(".hide").click(function(){
$('#table td div span').each(function(){
var $span = $(this);
$(this).siblings().hide();
var spanattr = $span.attr('class');
alert(spanattr);
});
});
});
HTML:
<table id="table">
<tbody>
<tr>
<td class="tdspan">
<div class="container">
<span class="spanelem">First</span>
</div>
</td>
<td class="tdspan">
<div class="container">
<span class="spanelem">Second</span>
</div>
</td>
<td class="tdspan">
<div class="container">
<span class="spanelem">3rd</span>
</div>
</td>
<td>
Hide
</td>
</tr>
</tbody>
<br>
</table>
<span id="text"></span>
I already searched for other questions and used the provided solution such as below link but I'm not able to figure it out.
jquery to traverse the div and get its span details
You don't need for loops there.
Simply .find() span with class .spanelem in a closest <tr> parent of the clicked element:
$(".hide").click(function(){
$(this).closest('tr').find('.spanelem').hide();
// Or using selector context (.find() equivalent but a bit shorter)
// $('.spanelem', $(this).closest('tr')).hide();
});
JSFiddle JSFiddle
References:
.closest()
.find()
selector context
Are you just trying to hide the spans themselves? You are hiding their siblings, and since they are the only children of their parent div, there is nothing else to hide. If you want to hide the spans themselves, then just change
$(this).siblings().hide();
to
$(this).hide();
If you have multiple rows, then you can just crawl up the tree from the .hide button that was clicked to its ancestor row, then find all the spans within that row. You may want to search on a particular class, or all spans, but I don't know for sure how you identify which elements you want to hide.
Something like
$(this).closest('tr').find('span').each(function() {
Updated JSFiddle here: https://jsfiddle.net/fk9jgrLx/4/
If your table structure is as in provided example, and if you will have multiple rows:
$(document).ready(function() {
$(".hide").click(function(){
$(this).parent().siblings().find('span').hide();
});
});
https://jsfiddle.net/L1j9psz6/1/ - remove all spans from row...

jQuery dynamic insert row for expand/collapse

I have a table structure as follows;
<tr>
<td><div class="icon-chevron-right"></div></td>
<td><div>List 1</div></td>
</tr>
<tr>
<td><div class="icon-chevron-right"></div></td>
<td><div>List 2</div></td>
</tr>
Now on click of the icon image (chevron), I want the details row to be displayed immediately below the clicked row (It should be a tr containing child table). This should be inserted/appended dynamically on click of any of the list row.
How do I do this using jQuery? Any examples for reference would be really helpful..
the following example creates a new tr (if does not exists) containing table element under the tr where the clicked icon exists.
function createChildTable(string)
{
return $('<table>').append(
$('<tr>').append(
$('<td>').append(string)
)
);
}
$('.icon-chevron-right').click(function() {
var details = $(this).closest('tr').next('tr.details');
if (details.length) details.show();
else {
// first time clicked
details = $('<tr>').append( createChildTable('child table details') ).addClass('details');
$(this).closest('tr').after(details);
}
});
Example Link
I'd say there are two main ways to do this, and you'll have to figure out which one is best for you; it depends.
What you're talking about is ADDING a row into the DOM. This is fine in some cases, it depends on what this collapsed row is used for. If you want to be able to remove the collapsed row and add it again, it could make your life difficult if you have to reconstruct all the inner HTML via JavaScript every time.
var collapseHTML = '<tr class="collapse"><td colspan="2">This is my new row</td></tr>';
$('.icon-chevron-right').click(function() {
$('.collapse').remove(); // Deletes all rows that has class "collapse"
collapseHTML.insertAfter( $(this).closest('tr') ); // Inserts what's stored in collapseHTML after "this closest tr"
});
Then, as someone else said, you can solve this by adding those rows from the get go like so:
<tr>
<td><div class="icon-chevron-right"></div></td>
<td><div>List 1</div></td>
</tr>
<tr class="collapse">
<td colspan="2">This is my new row</td>
</tr>
Then, your css should loook something like this:
.collapse {
display: none;
}
.collapse.active {
display: block;
}
This means that when you add the active class to the collapse row, it goes from display: none; to display: block;. This you do via JavaScript/jQuery:
$('.icon-chevron-right').click(function() {
$('.collapse.active').removeClass('active'); // Removes active from all active collapsed rows
$(this).closest('tr').next().addClass('active'); // adds active class to "this closest tr's next element" (which is the collapse row)
});
Hope this helps!

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

complex jquery selector : challenge

I've searched among jquery selectors for some time now, but can't find any solution to my problem.
I've got an html table filed by a foreach. On each line, several links that pop up tooltips. My problem : can't find the right selector.
<table>
<?php foreach($article) :?>
<tr>
<td>
<div class="none" style="display:none;">
<div class="tooltip_1">
"The content of my tooltip_1"
</div>
<div class="tooltip_2">
"The content of my tooltip_2"
</div>
</div>
<div class="cell">
a link
a link
</div>
</td>
<tr>
<?php endforeach; ?>
</table>
To show my tooltip, I use qTip, and it works like this :
$('a[class="link_to_tooltip_1"]').qtip({
content: $('jquery selector'),
(... other options)
});
So basicaly, I would need something like
content: $('self.parentNode.parentNode > div[class="none"] > div[class="tooltip_1"]'),
in other words :
start from link "link_to_tooltip_1"
go back to parent div "cell"
go back to parent td
then go to child div "none"
and finally select child div "tooltip_1"
Thanks a lot.
// this is "complex" version;
// assumes .cell and .none are nested inside same container, whether <td> or <li> or anything
$(".link_to_tooltip_1").each(function () {
console.log($(this).closest(".cell").siblings(".none").find(".tooltip_1"));
// $(this).qtip({ content: /* use above selector */ });
});
// this is the "not-so-complex" version;
// assumes both items are nested arbitrary level deep inside same <td>
$(".link_to_tooltip_1").each(function () {
console.log($(this).closest("td").find(".tooltip_1"));
// $(this).qtip({ content: /* use above selector */ });
});
jsFiddle Link
$('a.link_to_tooltip1').closest('tr').find('.tooltip_1');
is probably what you're seeking for ?
why not place your tooltip like this ? :
<table>
<?php foreach($article) :?>
<tr>
<td>
<div class="cell">
<span class="tooltip_1" style="display:none;" >"The content of my tooltip_1"</span>a link
<span class="tooltip_2" style="display:none;" >"The content of my tooltip_2"</span>a link
</div>
</td>
<tr>
<?php endforeach; ?>
</table>
and
$('a[class="link_to_tooltip_1"]').qtip({
content: $(this).children("span"),
(... other options)
});
Edit
I didn't know you can't use $(this). So in this context, you can do :
$('a[class="link_to_tooltip_1"]').each(function(){
var content = $(this).prev("span");
$(this).qtip({
content: content,
(... other options)
});
Here is the selector you are looking for:
"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"
Explanations:
You can't go backwards (match an element, and then its parent). However you can select an element and verify that it contains elements that match an other selector:
"td:has(.cell .link_to_tooltip_1)"
This selects the parent <td> of .link_to_tooltip_1. So this does exactly the .link_to_tooltip_1.parentNode.parentNode you described.
Then you just have to select .none .tooltip_1 in the selected <td>:
"td:has(.cell .link_to_tooltip_1) .none .tooltip_1"
So your example code becomes:
$('a[class="link_to_tooltip_1"]').qtip({
content: $("td:has(.cell .link_to_tooltip_1) .none .tooltip_1"),
(... other options)
});
And as you were asking for, this is done with just a jquery selector :-)
I'd try something like this:
add a class to the elements with tooltips and rel attribute with the target class of element holding data
link with tooltip yar!
then in JS
$('a.iHaveATooltip').bind('mouseenter', function(){
$(this).addClass('showingTooltip');
}).bind('mouseleave', function(){
$(this).removeClass('showingTooltip');
}).qtip({
content: function(){ return $('.' + $('.showingTooltip').attr('rel')).html() },
(... other options)
});
it's the only idea I can come with to cheat the lack of support for generic data referencing based on DOM structure. Though can't promise it will work as I don't know the plugin and don't know if passing function as an argument won't collide with how it's implemented - you might have to change the plugin to allow it to accept function as content parameter.
good bye and good luck,
Tom

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