jQuery slideUp bug? - javascript

I'm messing around with some jQuery stuff for a mockup and noticed some odd behavior. I'm hoping someone here can shed some light on it.
This is all mockup / test code, so please excuse the sloppyness.
So I have a table that I'm using in conjunction with the jQuery datatable plugin:
http://www.datatables.net/
My table markup is as follows:
<table id="dexterIndex">
<thead>
<tr>
<th>Name</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test 1</td>
<td>Yes</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 2</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 3</td>
<td>Yes</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 4</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 5</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 6</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 7</td>
<td>Yes</td>
<td>2008-2009</td>
<td>Fall 2009</td>
<td>Fall 2009</td>
</tr>
</tbody>
</table>
Now, the functionality I'm going for is:
On hover change the row background color
If hovering for more than 'x' seconds slide down a sub-row for the row being hovered over.
Here is a screenshot of the effect working correctly (generally):
Upon leaving the row with one's mouse the sub-row slides back up.
This all works, but it seems that each time it slides back up it falls short by about a pixel. Here is an image after hovering/un-hovering 10 times. This is the table in the state after the sub-row slides up (meaning it's not just the sub-row showing with no text).
If I change slideUp/slideDown to fadeIn/fadeOut everything works fine and I don't get extra pixels. (I'll probably end up just using the fades, but i'm curious about this behavior).
This is what safari is reporting about the DOM in the bugged state (also, why can't I copy/paste in the Safari Web Inspector?):
And finally, here is some sloppy jQuery that handles the actual moving parts:
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('#dexterIndex').dataTable()
$('#dexterIndex tbody tr')
.hover(function() {
var table_row = this
table_row.hovering = true
window.setTimeout(function() {
if (table_row.hovering) {
$('.school-info').slideUp('fast', function() {
$(this).remove()
})
table_row.hovering = false
var tr = $('<tr />').attr({'class': 'school-info',})
$(table_row).after(tr)
$('<td />')
.attr({
'colspan': 5
})
.css({
'display': 'none'
})
.text("Sub Row")
.appendTo(tr)
.slideDown('fast')
}
}, 2000)
$(this).children().each(function() {
(this.oldColor === undefined)? this.oldColor = $(this).css('background-color'): null;
$(this).css({'background-color': '#f3ffc0'})
})
},
function() {
this.hovering = false
$('.school-info').slideUp('fast', function() {
$(this).remove()
})
$(this).children().each(function() {
$(this).css({'background-color': this.oldColor})
})
})
})
TL;DR: slideUp slides up one pixel less each time, fadeOut doesn't have any issues.
If anyone can shed some light on this issue it'd be greatly appreciated.

Couple of questions/ideas:
It seems this technique is being used for UI/richness, meaning that the sub-rows aren't calculated when the user hovers nor does it get created from an ajax call, etc. But you aren't hiding and unhiding the data, but instead creating it on hover and then removing it afterward. This is potentially very inaccessible and adds extra overhead to the browser-script.
So I'd suggest having the table load with the actual sub-rows and having your jquery hide them during load. You could simply add a class like "sub_row" to those tables.
Second, is this only happening in Safari? Is it happening in Firefox? Either way, I would guess you are losing a pixel from the browser adding a default border. I don't know why this would keep adding that border on each slideup, but I'm sure someone else here can spot that.
Lastly, I'm unfamiliar with your selector syntax. you are selecting your tds and trs as :
$('<tr />)
and
$(')
instead of:
$('tr')
and
$('td')
Any reason why?

Related

Executing code before and after downloading a file with Datatables (JS)

I am using Datatables to create some tables with data. I am using the option they have to include a download CSV button. However, since I am working with large amounts of data, I wanted to put a "Loading, please wait..." gif on the screen so users know it is downloading. However, the gif loading I have requires that I activate it before the downloading starts, and deactivate it after the downloading finishes (really it's just adding a class to the body which makes it a bit transparent and adds a wheel gif). I haven't found a way to run code before and after download. I think I can do before with action, but not after.
Can anyone help me out with this? Is there a way to do code before download and after download? Or, in absence of that, is there maybe a better way I can implement a waiting gif while it prepares the csv for download?
You can extend the csv-button and call the original action inside it. This enables you to show a custom loading-indicator while the export is being processed.
$(document).ready(function() {
let table = $('#example').DataTable({
processing: true,
dom: 'Bfrtip',
buttons: [{
extend: 'csv',
text: 'CSV Export',
action: function(e, dt, button, config) {
console.log('csv button clicked');
this.processing(true); // show indicator on button
console.log('before csv export');
config.filename = 'my-export'; // set filename
$.fn.dataTable.ext.buttons.csvHtml5.action.call(this, e, dt, button, config); // call export-action
console.log('after csv export');
this.processing(false); // hide indicator on button
}
}],
});
});
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/b-1.5.6/b-html5-1.5.6/datatables.min.css" />
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/b-1.5.6/b-html5-1.5.6/datatables.min.js"></script>
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test-1</td>
<td>Test 1234</td>
</tr>
<tr>
<td>Test-3</td>
<td>I dont know!</td>
</tr>
<tr>
<td>Test-2</td>
<td>Another...</td>
</tr>
<tr>
<td>Alpha-1</td>
<td>Apple Test</td>
</tr>
<tr>
<td>Alpha-2</td>
<td>Banana Test</td>
</tr>
<tr>
<td>Alpha-3</td>
<td>Coconut</td>
</tr>
<tr>
<td>Beta-1</td>
<td>Beta</td>
</tr>
<tr>
<td>Beta-2</td>
<td>Not Alpha</td>
</tr>
<tr>
<td>Alpha-1</td>
<td>Apple Test</td>
</tr>
<tr>
<td>Alpha-2</td>
<td>Banana Test</td>
</tr>
<tr>
<td>Alpha-3</td>
<td>Coconut</td>
</tr>
<tr>
<td>Beta-1</td>
<td>Beta</td>
</tr>
<tr>
<td>Beta-2</td>
<td>Not Alpha</td>
</tr>
</tbody>
</table>

jquery tablesorter usage without tbody and th block

I am very much interested to know how to use jquery tablesorter without tbody and th block, the reason behind this is I have many tables and css working which I generated from http://www.csstablegenerator.com/ site, in which only tr and td blocks only used
This is working table with tbody block Working default table style fiddle
But I want to sort table with only tr and td blocks Expected Fiddle
This is my test table which I want to sort
<table border='1' id='test' >
<!-- this is my header -->
<tr>
<td>AlphaNumeric</td>
<td>Numeric</td>
<td>Animals</td>
<td>Sites</td>
</tr>
<tr>
<td>abc 123</td>
<td>10</td>
<td>Koala</td>
<td>http://www.google.com</td>
</tr>
<tr>
<td>abc 1</td>
<td>234</td>
<td>Ox</td>
<td>http://www.yahoo.com</td>
</tr>
<tr>
<td>abc 9</td>
<td>10</td>
<td>Girafee</td>
<td>http://www.facebook.com</td>
</tr>
<tr>
<td>zyx 24</td>
<td>767</td>
<td>Bison</td>
<td>http://www.whitehouse.gov/</td>
</tr>
</table>
Assuming you don't want to manually deal with the HTML of the table, so I would get jquery to do it for you:
var header = $("#test tr:first").html();
$("#test tr:first").remove();
$("#test").prepend('<thead>' + header + '</thead>');
$('#test').tablesorter();

How to avoid duplicate code (toggle when page loaded)?

See the code below, If you click on the sub-title row it then will hide the rows with it. It work well.
On the second sub-title row (<tr class="sub-title default-hide">) - I want this to toggle/hidden by default when the page loaded.. How to do this without writing duplicate code like below?
$(".sub-title").on("click",function() {
tr = $(this).find('span').hasClass("arrow2");
trSpan = $(this).find('span');
$(this).nextUntil(".sub-title").each(function() {
if (!$(this).hasClass('head-order')) {
$(this).toggle();
if (tr) {
trSpan.removeClass('arrow2').addClass('arrow1');
} else {
trSpan.removeClass('arrow1').addClass('arrow2');
}
}
});
});
HTML
<table border="1">
<tbody>
<tr class="head">
<td> title </td>
</tr>
<tr class="sub-title">
<td>Sub Title 1 <span class="arrow2"> </span></td>
</tr>
<tr> <td>Item 1</td> </tr>
<tr> <td>Item 2</td> </tr>
<tr> <td>Item 3</td> </tr>
<tr class="sub-title default-hide">
<td>Sub Title 2 <span class="arrow2"></span></td>
</tr>
<tr> <td>Item 4</td> </tr>
<tr> <td>Item 5</td> </tr>
<tr> <td>Item 6</td> </tr>
</tbody>
</table>
I created a jsFiddle example with the information you provided.
I edited the code a bit, using a default arrow-class and just adding the class close to it, to define the new style, which should make the code a little shorter.
$(".sub-title").on("click",function() {
var trSpan = $(this).find('span');
trSpan.toggleClass('closed');
$(this).nextUntil(".sub-title").each(function() {
if (!$(this).hasClass('head-order')) {
$(this).toggle();
}
});
});
To make the "default-hidden" - element closed on pageload, all I do is to trigger a click-event on it after binding the click-Handler.
$('.default-hide').trigger('click');
See the fiddle for a working example
Create a named function and call it a couple times:
var toggleArrow = function(el) {
tr = $(el).find('span').hasClass("arrow2");
trSpan = $(el).find('span');
$(el).nextUntil(".sub-title").each(function() {
if (!$(el).hasClass('head-order')) {
$(el).toggle();
if (tr) {
trSpan.removeClass('arrow2').addClass('arrow1');
} else {
trSpan.removeClass('arrow1').addClass('arrow2');
}
}
});
};
$(".sub-title").on("click", function(){ toggleArrow(this); });
$(".default-hide").each(function(i, el){ toggleArrow(this); });
You can trigger the click event manually for the default-hide rows.
Like this
$('.default-hide').trigger('click');

jquery .load() and IE

Tested the below code with FF, Safary and Chrome and all works ok. But with IE... not so
When the button "viewEditButID'" is click the div "customerDetailsDivClass" is hidden. When it's click again the div reapers but before it dose so it download the data is going to display.
$(document).ready( function() {
$('#viewEditButID').click( function()
{
if ($('div.customerDetailsDivClass').is(':visible'))
{
$('div.customerDetailsDivClass').toggle("slow");
}
else
{
//Will make the box visible so update the date before this is done
$("div.customerDetailsDivClass").load("/Admin/UpdateCustomerList");
$('div.customerDetailsDivClass').toggle("slow");
}
});
});
html
<div class="customerDetailsDivClass">
<table id="customerTable">
<tr><th>Customer Name</th><th>Customer Code</th><th></th></tr>
<tr class="evenRow">
<td>Customer 1</td>
<td>SADFHS12345</td>
<td class="noRightPad"><input type="submit" name="createBut" value="View/Edit"/></td>
</tr>
<tr>
<td>Customer 2</td>
<td>SADFHS67891</td>
<td class="noRightPad"><input type="submit" name="createBut" value="View/Edit"/></td>
</tr>
</table>
</div>
From there a servlet is called and redirects the request to a .jsp which response with only the following:
<table id="customerTable">
<tr>
<th>Customer Name</th><th>Customer Code</th><th></th>
</tr>
<tr class="evenRow">
<td>Customer 2</td>
<td>SADFHS12345</td>
<td class="noRightPad"><input type="submit" name="createBut" value="View/Edit"/></td>
</tr>
<tr>
<td>Customer 2</td>
<td>SADFHS67891</td>
<td class="noRightPad"><input type="submit" name="createBut" value="View/Edit"/></td>
</tr>
</table>
So like i mention in FF the table is updated with Customer 2 data, but with IE the old data (Customer 1 data) is presented back again.
Any help, hints to toubleshoot would be great!
Thanks
Alexis
manage to resolve this...
after a day of wasted time and swearing at the IE developers..
there was a blank line "\n" in my .jsp file which (only) IE interprets this as end of file rather then looking at the byte count in the http header..
anyway i learn allot about js debugging at least
alexis
You're fighting the browser cache.
Change it to
.load("/Admin/UpdateCustomerList?Timestamp=" + new Date())

Dynamically hiding table rows with jQuery

I am trying to alternate background colors of table rows, each section starting with the same color. I have achieved this with the following code:
$(document).ready(function(){ $("tbody tr.row:nth-child(even)").css("background", "#efefef"); });
I also need to be able to limit the number of rows (5 for example) that are visible inside each tbody section. These need to be able to be toggled with a button with a .click() event. Does anyone know how I could achieve this? The only solutions I have come up with caused the background colors to break. Any help would be greatly appreciated!
Here is an example of the table structure:
<table>
<tbody>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
</tbody>
<tbody>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
<tr>
<td>Cell Contents</td>
<td>Cell Contents</td>
</tr>
</tbody>
</table>
This should do the trick:
$(function() {
$('#showAll').click(function() {
$('table > tbody').each(function() {
$(this).children('tr:gt(4)').toggle();
});
$("tr:visible").filter(':odd').css("background", "#efefef").end()
.filter(':even').css("background", "#ffffff");
}).click();
});
Edited to clean up code (inspired by #karim79's answer).
This does it (tested):
var rowLimit = 5;
$(document).ready(function() {
$('button').click(function() {
//hide everything after the rowLimit row
$('table > tbody > tr:gt(' + (rowLimit - 1) + ')').toggle();
});
});
The key is in the gt selector
To prevent your row styles from vanishing, put them in a CSS class and use addClass and removeClass instead to apply them, bearing in mind that if they're not in a class, then they don't exist :)
Scrolling. Set the height of the table to what 5 rows will fit in, and then use css
overflow: scroll; :D

Categories

Resources