How to update html table without disturbing scroll position? - javascript

HTML:
<div class="html_table"></div> # In html body tag.
Ajax function to get table data.
var $html_table= $('.html_table');
function ajaxCallFunction() { $.ajax({
type: 'POST',
url: url,
contentType: 'application/json',
success: function(res, status, xhr){
$html_table.html(res['html_table']);
},
error:function(xhr, status, error){
}
});
Updating table for every 5 seconds,
window.onload = function() {
ajaxCallFunction();
setInterval(ajaxCallFunction, 1000*5);
}
Issue:
I have 100 rows in a table. Need to update it every 5 seconds without disturbing the position of scroll. When the user looking to the bottom line, the scroll bar goes to its original position after 5 seconds. How to handle the issue?
How to update the cell value of the table, without affecting the scroll position?
Any other suggestions are welcome.
Note:
In my case, its more important that focus on current row should not get affected.

You can save the current scroll position before changing the html and restore it after you changed the html.
var savedScrollPosition = $(window).scrollTop;
in response callback then restore the position:
$(window).scrollTop(savedScrollPosition);
If the requested HTML is different from the previous one this is of course not working. Maybe you could calculate the real new scroll position relative to the height of the old and new HTML and the saved scroll position in such a case.

Related

on ajax success running table.setData but data is not loading

I am trying to run a report with two tabulator tables. One main table, then on click of a row it will populate a modal. All the html part works and the jquery (JS) works. I have a success function on my ajax call to set the data in the modal. But it does not seem to be waiting for the ajax to return the data. See code below. I can see the data in the console.log so the console.log seems to be running its just not pushing to the table. If I run a function to set the data manually from the console it works. So not really sure whats going on.
var CatVolumetable = new Tabulator("#myreport", {
//height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
placeholder:"Select Year-Month to populate Data",
layout:"fitColumns", //fit columns to width of table (optional)
columns:[ //Define Table Columns
{title:"Category Name", field:"Category_name", align:"left"},
{title:"State", field:"State",align:"center"},
{title:"Max Quantity",field:"maxQuantity", align:"left"},
],
rowClick:function(e, row){ //trigger an alert message when the row is clicked
var state = row.getData().State;
//getStoresByState(state);
$('#drilldown').modal('toggle');
let myUrl = 'http://localhost:3000/view_state_category_volume_drilldown/'+state;
$.ajax({
//$.ajax({
url: myUrl,
method: 'get',
dataType: 'json',
success: function(data){
console.log(data);
ddtable.setData(data);
}
});
var ddtable = new Tabulator("#drilldownTable", {
//height:205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
//ajaxURL:""
placeholder:"No Data Available",
layout:"fitColumns", //fit columns to width of table (optional)
columns:[ //Define Table Columns
{title:"Manager_email", field:"Manager_email"},
{title:"Manager_name", field:"Manager_name", align:"left"},
{title:"Store_num", field:"Store_num"},
{title:"Street_address", field:"Street_address", align:"center"},
{title:"City Name", field:"City_name", align:"center"},
],
});
SOLUTION:
I figured out the problem is that the data must be loaded after the modal is toggled (i.e. after it is visible). If I load data on the show event listener it works perfectly. Below is code with bootstrap.
$("#drilldown").on('shown.bs.modal', function (e){
///Ajax call with success handler to load data
})
If the API is too fast for your second tabulator table
Check this post
.Use below code to set Data after drilldownTable is initialized
if ($("#drilldownTable").hasClass("tabulator")){
//element has class of .tabulator
}

Scroll to bottom on page load

I have the following code, it's a chat display that I got using the Firebase API.
The problem is that, when the page loads, I want it to directly have the scrollbar set at the bottom. At the moment it is sort of sliding slowly to the bottom (because of the .animate).
How can I have the scrollbar always stay at the bottom when I reload the page, even if new content is added to the chat?
$(document).ready(function () {
var myDataRef = new Firebase('https://ot7fwnsj7h7.firebaseio-demo.com/');
myDataRef.on('child_added', function (snapshot) {
var message = snapshot.val();
displayChatMessage(message.name, message.text);
});
function displayChatMessage(name, text) {
$('<div/>').text(text).prepend($('<em/>').text(name + ': ')).appendTo($('#displayChat'));
// make text scroll everytime someone posts
$('#displayChat').animate({
scrollTop: $("#displayChat")[0].scrollHeight
}, 'slow');
};
});
And here's my fiddle:
http://jsfiddle.net/qxkr35pj/
I hope I've been clear! Thanks.
This line of code scrolls the element to its bottom.
Call it every time you update the view.
JSFiddle
$("#displayChat")[0].scrollTop = $("#displayChat")[0].scrollHeight
I think what you want is this instead of your animate code:
$('#displayChat').scrollTop($("#displayChat").height());
You'd also want to use that every time a message gets added - it'll take the scrollbar to the bottom of the div.

Javascript Variable Change Conundrum

So I have this little loop which checks the id of the last div on my page and then replaces the div with a rendered updated div using ajax, then loops around and repeats. Now the problem I have is that if it loops and the id of the last div is the same it just adds another updated div so I get two of the same thing. I would only want it to append the data again if the id of the last div has changed (i.e it's a different div), but I don't think Javascript has an onChange method for calling the request only when id has changed. How might I go about this in JS?
Thanks in advance.
$( window ).load(function() {
update_live();
});
function update_live (){
var id = $(".tasktable").last().attr('id');
$.ajax({
type: 'GET',
url: "/ansible_jobs/update_live/",
data: { task_id: id },
dataType: 'html',
success: data_append
});}
function data_append(data){
$('.tasktable').last().empty();
$('.tasktable').last().replaceWith(data);
setTimeout(update_live, 2000);
}
Change update_live() to update_live(previousId), compare it with the current one, and update only if it is different. Pass the id forward.

Tooltipster not working properly in the beginning

I am using the tooltipster plugin tool where I got gantt chart drawn with some td given id.
So, which ever id is defined and the mouse over it will get ajax data and show accordingly.
Below is snippet of my codes. Issue here is that the tool tip only appear after few times I mouse the td. Thereafter, it works fine.
I can see, in my debug window, that ajax page is called and following error:
Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips. jquery.tooltipster.min.js:1
$(document).ready(function () {
$('td[id]').tooltipster({
// content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
// We'll make this function asynchronous and allow the tooltip to go ahead and show the loading notification while fetching our data
continueTooltip();
var idval=0;
// Next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'GET',
url: 'getDetails.php',
data:idval,
success: function(data) {
// Update our tooltip content with our returned data and cache it
//alert("Data is : "+data);
var finalData = 'Total Data : 300 <br> Total Completed : 200';
//alert("DATA");
//origin.tooltipster: $('<span>testst<strong>This text is in bold case !</strong></span>')
origin.tooltipster({
content: finalData,
multiple: true,
contentAsHTML: true
});
//origin.tooltipster({content: data,contentAsHTML: true}).data('ajax', 'cached');
}
});
//}
}
});
});
The Tooltipster plugin really should be initialised before all of this. Using the mouseenter enter to trigger it's initialisation every time a user hover's over a <td> element is not great practice and is the root problem to your issue. Ideally you would want to break it down into the following:
Find your <td> elements with id's defined.
Apply tooltipster to these elements.
Let tooltipster handle everything from there.
1. Finding your <td> elements
With the magic of jQuery you can fetch these with a clever use of selectors rather than querying a larger set with your initial implementation, gathered from the answers within the StackOverflow thread here, jquery get only all html elements with ids, we get:
$('td[id]')
This will fetch you all <td> elements with an id defined, be warned this could be a bit slow if you have an extensive table. Alternatively you can select, then apply a filter to narrow down your set:
$('td').filter(function(){
return $(this).attr('id') !== undefined;
});
Both will essentially do the same!
2. Applying tooltipster to these elements
I've not done much here since you had a lot of commented out code, so I've kept it the same, with some minor tweaks, here is my version of the "working code":
$('td[id]').tooltipster({
// content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
// We'll make this function asynchronous and allow the tooltip to go ahead and show the loading notification while fetching our data
continueTooltip();
// Next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'GET',
url: 'getDetails.php',
data: $(this).attr('id'),
success: function(data) {
// Update our tooltip content with our returned data and cache it
//alert("Data is : "+data);
var finalData = 'Total Data : 300 <br> Total Completed : 200';
//alert("DATA");
//origin.tooltipster: $('<span>testst<strong>This text is in bold case !</strong></span>')
origin.tooltipster({
content: finalData,
multiple: true,
contentAsHTML: true
});
//origin.tooltipster({content: data,contentAsHTML: true}).data('ajax', 'cached');
}
});
//}
}
});
3. Letting tooltipster handle everything from here
Tooltipster (when intialised) is triggered by default when hovering over an element, this means your functionBefore will be run before this "hover" event, causing your AJAX request to be run each time, there is no need to do anything more thereafter :D
I hope this helps! :)
You can use this code :
var tooltipInstance;
$("body").on('mouseover', 'td[id]:not(.tooltipstered)', function(){
tooltipInstance = $(this).tooltipster({
//your code ...
});
tooltipInstance.tooltipster('open');
});

jquery animation does not animate

i have some jquery code that will load the chatbox of my site every second (so if any new posts arrive they become visible)
my code is here
function loadLog(){
$.ajax({
url: "/log.html",
cache: false,
success: function(html){
$("#chatbox").html(html); //Insert chat log into the #chatbox div
if($("#chatbox").attr("scrollHeight") + 20 > $("#chatbox").attr("scrollHeight") - 20){
$("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div
}
},
});
}
everything works fine, except it is meant to autoscroll to the bottom of the chatbox so you see the newest posts, instead it just stays at the top.
I am using the most recent version of jQuery
There is no such attribute scrollHeight (it's property). What if you try something like this instead:
$box.animate({scrollTop: $box[0].scrollHeight}, 'normal');
http://jsfiddle.net/dfsq/zBdas/
Another tip: make sure you cache your DOM queries like $box = $("#chatbox"), don't reselect elements again and again.

Categories