check if div with scrollbar is currently readed by user - javascript

I have a div with a scrollbar which contains a logfile.
I fetch the newest log every 5000ms from the server by running a timer which does an ajax request to the server.
However, each time when I am reading and scrolling down the div, and the ajax request refreshes the div with the new content, then I am at the top of the text again and have to read all again.
So I need to check somehow if the user is reading at the moment, and clear the interval if he does.
I know that I could just create a toggle so the user can clear the interval manually, but I wan't to try a more intelligent approach.
My approach would be to check inside the timer, wheter the div is focused or not and if true, clear the Interval.
getLogs = setInterval
(
function()
{
if ($("div#log").is(":focus"))
{
clearInterval(getLogs);
}
else
{
//ajax request
}
},
5000
);
But $("div#log").is(":focus") always returns false.
I also tried $("div#log").is(":active") but this is not defined.

I suggest you use jQuery's .scrollTop() method to check whether scrollTop !== 0 in which case you can assume the user has scrolled within the element and is currently reading it.
getLogs = setInterval
(
function()
{
if ($("div#log").scrollTop() > 0)
{
clearInterval(getLogs);
}
else
{
//ajax request
}
},
5000
);
You could then introduce some logic to reinstate the timer either after a certain amount of time (assuming at some point the user will move on - quite a quick, but unstable solution) or by checking whether your log-file height is same as .scrollTop() + containing div height in which case the user has read to the end of the document.

Related

Can we remove click event without calling it?

I am having problem in overriding the pagination code given by grid. What I need to do is kind of hack the pagination given by my grid.
We are having a lot of records. So, what we are doing we are loading records to a threshold limit.
So, lets assume the threshold limit is 50 and page size is 10 so there will be 5 pages. So, when user comes to 5th page next button provided by the grid will be disabled.
So, what we need to do we need to make it enable and if user clicks on it I need make ajax call and load another 50 records(threshold limit) in the grid.
After that I need to disable this event so that next time user clicks it should not do the make ajax call and it should work like previously (by going from 1st page to 2nd page and so on)
All the above things mentioned I am able to do. But here problem comes when user goes to 5th page and go back to some other page let say 3 without clicking next button. Now, after going to 3rd page
when user clicks on the next page button it is making ajax call as I have make the button enable when user comes to 5th page and provided a click event to it.
So even if I provide a condition to run only on when grid current page is 5 then also it is running because after going to 5th page I will make button enable and bind and event. So, as I provided the event it will run without even specifying the condition.
How do I make the click event work as default and only when the user is at 5 it will make the ajax call.
This is my code -
///grid Current page will tell us which page we are in the grid.
if(gridCurrentPage==5){
query(".dojoxGridWardButton").forEach(function(element) {
query(".dojoxGridnextPageBtnDisable").replaceClass("dojoxGridnextPageBtn", "dojoxGridnextPageBtnDisable");
query(".dojoxGridlastPageBtnDisable").replaceClass("dojoxGridlastPageBtn", "dojoxGridlastPageBtnDisable");
});
callNextButton(gridCurrentPage)
}
And this is the function.
function callNextButton(gridCurrentPage) {
var target = dojo.query(".dojoxGridnextPageBtn");
var signal = on(target, "click", function(event){ ///Adding click event
if (gridCurrentPage ==5 ) {
var deferred = new dojo.Deferred();
setTimeout(function() {
deferred.callback({
called: true
})
}, 2000);
if (checking some conditions) {
////////doing Ajax call
deferred.then(function() {
//calling a callback
})
},
error: function(e) {}
};
})
signal.remove(); //Removing click event
}
Note : My grid is enhanced grid which is part of dojo toolkit. But probably its a design issue so, any comments/advices are welcome.
I really need an advice here. Please anyone can find the problem where it is it will be reqlly helpful.

How to make scroll event to receive only one request at a time?

I am trying to trigger an action on scroll event when the user reaches a certain point in the web page.
So What I am facing right now is that the Scroll event fires too many times which messes the structure of the web page. I mean too much stuffs are loaded into the site suddenly which is exactly How I do not want it. Instead I have tried Debounce method in jQuery & also Throttle but none of them are working as because let me tell you.
DEBOUNCE can't keep to execute until when the user stops scrolling so if the user keeps scrolling continuously with no delays so the debounce function won't execute.
THROTTLE as it keeps executing after every given amount of time so It can miss the scroll place to fire there. So it's no help too.
What I Want Exactly ?
I want that whenever a user scrolls to the certain area of the web page so even if the page fires too much scroll events so it should only process one event and ignore the rest and then when the user scrolls down and then he reaches the area so then again it should only process one request.
IMP : Also I want to capture fast scrolling too as right now it's not firing any events on fast scrolling only when the user scrolls too much slowly. Something like the when even during fast scrolling the user passes the certain area of the web page so the event should fire.
Here is my Code :
$i = 0;
$(window).scroll(_.throttle(function() {
// console.log($i++);
if ($('.searchResult').length) {
scrollTop = $(this).scrollTop();
lastLiPos = parseInt($('.searchResult li:last-child').offset().top) - parseInt($(window).height());
last12thRowLiPos = parseInt($('.searchResult li:nth-last-child(26)').offset().top) - parseInt($(window).height());
if ((scrollTop > last12thRowLiPos && scrollTop < (last12thRowLiPos) + 150) &&
$('#search_result_cont').attr('data-disable-load-result') === 'false'
) {
var text = $.trim($("div#load_more").text());
if (text !== "No More Results") {
$('div#load_more').trigger('click');
}
if (text !== "No More Results") {
$('div.loading_animate').fadeIn(1000);
} else {
console.log($.trim($("div#load_more").text()));
}
}
}
},100));
I think you need some RXJS filter magic.. I haven't used it, but there is a rxjs-jquery library.

Programmatically change first page jQuery Mobile shows

My goal is to show a different first page depending on whether the user is logged in or not. The login check happens using a synchronous Ajax call, the outcome of which decides whether to show a login dialog or the first user page.
The normal way to do this would be to set $.mobile.autoInitialize = false and then later on initialize programmatically, as described in the answer to this question. For some reason this won't work, instead another page gets loaded every single time.
I decided to give up on this way and try out a different parcour. I now use a placeholder, empty startup page that should be shown for as long as the login check takes. After the login check it should automatically change. This is done by calling a function that performs the ajax call needed for authentication on the pagechange event that introduces this startup page. The function takes care of changing to the outcome page as well.
The trick is that it doesn't quite do that.. Instead it shows the correct page for just a short time, then changes back to the placeholder. Calling preventDefault in pagechange didn't prevent this, as described in the tutorial on dynamic pages. Adding a timer fixed this, leading me to think that the placeholder wasn't quite finished when pageshow got fired (as per this page on page events), or some side-effect of the initial page load still lingered.
I'm really clueless as to how to fix this seemingly trivial, yet burdensome problem. What causes this extra change back to the initial page? Also, if my approach to intercepting the initial page load is wrong, what would be the correct approach instead?
I use jQuery Mobile 1.4.0 and jQuery 1.10.2 (1.8.3 before).
EDIT: Below is the code to my last try before I posted the question here. It does not work: preventDefault does not prevent the transition to the placeholder page.
$(document).on("pagebeforechange", function(e, data) {
if (typeof(data.options.fromPage) === "undefined" && data.toPage[0].id === "startup") {
e.preventDefault();
initLogin();
}
});
function initLogin() {
// ... Login logic
if (!loggedIn) // Pseudo
$('body').pagecontainer("change", "#login", {});
}
If you're using a Multi-page model, you can prevent showing any page on pagebeforechange event. This event fires twice for each page, once for the page which is about to be hidden and once for the page which is about to be shown; however, no changes is commenced in this stage.
It collects data from both pages and pass them to change page function. The collected data is represented as a second argument object, that can be retrieved once the event is triggered.
What you need from this object is two properties, .toPage and .options.fromPage. Based on these properties values, you decide whether to show first page or immediately move to another one.
var logged = false; /* for demo */
$(document).on("pagebeforechange", function (e, data) {
if (!logged && data.toPage[0].id == "homePage" && typeof data.options.fromPage == "undefined") {
/* immediately show login dialig */
$.mobile.pageContainer.pagecontainer("change", "#loginDialog", {
transition: "flip"
});
e.preventDefault(); /* this will stop showing first page */
}
});
data.toPage[0].id value is first page in DOM id.
data.options.fromPage should be undefined as it shouldn't be redirected from another page within the same webapp.
Demo
I'm undergoing the same problem as the one described by #RubenVereecken, that is, a coming back to the initial page once the cange to my second page has completed. In fact, he posed the question "What causes this extra change back to the initial page?" and it hasn't been replied yet.
Unfortunately, I don't know the reason since I haven't found how the page-event order works in JQM-1.4.2 yet, but fortunately, the workaround suggested by #Omar is working for me.
It's not exactly the same code but the general idea works at the time of preventing a coming back to the initial page. My code is as follows:
$(document).on("pagebeforechange", function(event, data) {
if ( typeof (data.toPage) == "string") {
if (data.toPage.indexOf("#") == -1 && typeof (data.options.fromPage[0].id) == string") {
event.preventDefault();
}
}});
The condition data.toPage.indexOf("#") == -1 is because I checked that all the undesired coming-backs to the initial page were happening when the property '.toPage' was set to something like [http://localhost/.../index.html].

div scrolls to top after refresh need to stop auto scroll to the top

I am trying to get a div that refreshes every 2 seconds to stop scrolling back to the top after the 2 second refresh I have PHP code and javascript. The Javascript I am using is:
function at_Ticket_scrollBottom()
{
var objDiv = document.getElementById("cartTicket");
objDiv.scrollTop = objDiv.scrollHeight;
}
function at_Tabs_Update()
{
if(div_WPOSVar_IsVisible())
{
//calling setTimeout without clearing any existing timeout can add multiple calls.
//IE the normal 2 second sequence, then call at_Tabs_Update two more times, and
// now we have 3 timeouts set to call at_Tabs again, etc.
//This wouldn't be an issue except that we call at_Tabs_Update directly to cause
// immediate refresh from many places.
//So clear the handle everytime to get rid of the last one we set.
clearTimeout(at_Tabs_Timer);
at_Tabs_Timer=setTimeout("at_Tabs_Update()", 2*1000); //every 2 seconds
return;
}
}
So after the refresh if I scroll down to the bottom of the ticket it jumps back to the top after the next refresh so I can never get to the bottom and select an item and edit it before the refresh how do I stop the auto scroll back to the top.
from the scars infos I can gather here I think your best bet would be to save your current scroll position before you refresh and after the ajax call scroll to that saved position.
use jQuerys .scrollTop() function for both reading and setting the scroll.
some pseudo code for illustration:
at ajax refresh function
var curPos $(element).scrollTop();
... do ajax call ..
ajax callback: $(element).scrollTop(curPos);

Always up to date content using AJAX

At the moment I am using ajax requests every 10 minutes to update certain content and other time intervals for others.
I do this using jQuery by:
On mouse move, the active page is checked
If the active page has not be updated within the given time interval, the page is updated
I'm doing this because although i want the content to stay up to date, I don't want it to be sending requests in the background (when the user is not using the application). Doing this also means that if the user has not used it for more than the time period, when they start to use it again it will automatically update.
I'm wondering just how efficient this is as whenever the mouse moves the checks are called (and has slowed down performance a bit - especially when trying to click links) - is the a more efficient way to do this?
Thanks!
I would rather activate/reset a timer, on say, 60 seconds, on movement of the mouse, and set your fixed-interval checks to only run if that timer is above zero.
That way, checks aren't made every time the mouse moves, and if the user becomes inactive, update checks stop after 60 seconds.
Another possible solution would be to use the window blur and focus events to determine if the window is active:
var checkForContentUpdates = true;
$(window).focus(function() {
checkForContentUpdates = true;
});
$(window).blur(function() {
checkForContentUpdates = false;
});
Your AJAX routine would then key off of the checkForContentUpdates bool.
I'm sure that there are scenarios where this isn't fool-proof, so you'd likely have to combine this method with other logic.

Categories