I have a script that refreshes a Div on my website every 20 seconds. The problem is, once it refreshes, it scrolls to the to of the Div. I want it to stay at the last position and not scroll to the top after a refresh. Could someone please look at this script and maybe point out what I'm doing wrong? Thanks in advance!
var time = new Date().getTime();
var refreshTime = 20*1000;
$(document).bind("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error hover change", function(e) {
time = new Date().getTime();
});
var lastScrollPos = 0;
$('#feed1').on('scroll', function() {
lastScrollPos = this.scrollTop;
});
function refresh() {
if(new Date().getTime() - time >= refreshTime)
$('#feed1').load(location.href="/dashboard" , function () {
$(this).scrollTop(lastScrollPos);
});
else
setTimeout(refresh, refreshTime);
}
setTimeout(refresh, refreshTime);
Why don't you use feed1 div only for loading your dashboard contents and handle its position using style.
#feed1 {
height: 150px;
overflow: auto;
}
Add other data outside feed1 div because load method will overwrite feed1's content.
See this example if you are looking for something similar otherwise you can modify this example so that other can understand your requirement/scenario.
If you do location.href="/dashboard", the browser will discard all the page's state (including scripting variables) and load "/dashboard" (assigning a value to location.href is identical to calling location.assign("/dashboard")).
The jQuery load function will probably not even require you to reposition the scroll offset, if you gave it chance to execute!
Try:
$('#feed1').load("/dashboard #feed1");
UPDATE:
It seems the HTTP request fired by jQuery's load mechanism is receiving a truncated response in your case (content-length: 0).
You would have to put the scroll position you want to keep into localStorage. Try:
var time = new Date().getTime();
var refreshTime = 20*1000;
$(document).bind("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error hover change", function(e) {
time = new Date().getTime();
});
var previousScrollPos = localStorage.getItem("lastScrollPos");
if(previousScrollPos)
{
$('#feed1').scrollTop(previousScrollPos);
localStorage.removeItem("lastScrollPos");
}
function refresh() {
if(new Date().getTime() - time >= refreshTime)
{
localStorage.setItem("lastScrollPos", $('#feed1').scrollTop());
location.reload();
}
}
setInterval(refresh, refreshTime);
I'm not 100% sure that you want to bind to the scroll event of #feed1 or just of body, I haven't seen your page. If anybody clicks "load more" on the news feed, those additional items will be hidden again since you're reloading the page. Not ideal at all.
Many users will hate having the page periodically reload, it's also an accessibility failure since this will interfere with screen reading software. It might be a simpler idea to just put a refresh newsfeed icon on the page, which just reloads the whole page, when the user wants to (instead of periodically).
Related
I have hooked up a simple long touch function that after 500ms uses the "open" API command to open the context menu. The menu opens. However, on "touchend" the menu disappears. It only stays if I touchmove over the context menu before "touchend". Is there a way to prevent this sort of behaviour? From the source code, only a "touchstart" in a different part of the dom should trigger a close event.
Code is below, in case useful. Not that a delegate of tr is required by my context menu - to explain the targetTr variable use below.
var mobDevice_onLongTouch,
mobDevice_touchTimer,
mobDevice_longPressDuration = 500; //length of time we want the user to touch before we do something
//handle long press on the datatable
var touchArea = document.querySelector("#table");
touchArea.addEventListener("touchstart", touchAreaTouchStart, false);
touchArea.addEventListener("touchend", touchAreaTouchEnd, false);
function touchAreaTouchStart(e) {
var targetTr = $(e.target).closest('tr');
mobDevice_touchTimer = setTimeout(function () { touchArea_onLongTouch(targetTr) }, mobDevice_longPressDuration)
};
function touchAreaTouchEnd(e) {
if (mobDevice_touchTimer) {
clearTimeout(mobDevice_touchTimer) //reset the clock
}
};
function touchArea_onLongTouch(target) {
$('#table').contextmenu('open', target);
};
I solved this. ContextMenu was working fine, but the DOM control I was touching on registered a change event (to highlight a table row) on touchend. So the context menu popped up during touch and hold, then got cleared by a DOM change at touchend.
The solution was to manually add the highlight table row event to touchstart and preventDefault on touchend (when the touch target was inside the table)
I've created a fiddle to reproduce the problem.
https://jsfiddle.net/rvwp47Lz/23/
callback: function (key, option) {
console.log("You clicked the test button", this);
// Need the iframe contents to regain focus so the mouse events get caught
setTimeout(function () {
$iframe[0].contentWindow.focus();
}, 100);
}
Basically, what I want to happen is the mouse move events to be caught after closing the context menu.
I can call focus on the iFrame's body or document but it doesn't seem to have any effect.
After you right click one of the items within the iframe and select an item, the mousemove event on the iframes body is no longer called (you can also notice that the hover CSS effect on the items are no longer working).
Ideas?
After some debugging and playing around with jQuery.contextMenu's code it seems the issue actually comes from the itemClick function. I added comments to the code and will add an issue to their github for a possible fix (unless there's some reason they're disabling default here)
// contextMenu item click
itemClick: function (e) {
var $this = $(this),
data = $this.data(),
opt = data.contextMenu,
root = data.contextMenuRoot,
key = data.contextMenuKey,
callback;
// abort if the key is unknown or disabled or is a menu
if (!opt.items[key] || $this.is('.' + root.classNames.disabled + ', .context-menu-submenu, .context-menu-separator, .' + root.classNames.notSelectable)) {
return;
}
// This line is causing the issue since it's preventing the default actions which puts
// mouse events back into place. Chrome must disable mouse move events when the contextmenu event
// gets triggered to improve performance.
//e.preventDefault();
e.stopImmediatePropagation();
I have long vertical list of links that user can scroll through, and I need to prevent triggering a click event (touch) on this links if user scrolls.
In current scenario, when user start scrolling by tapping over the link, it also triggers a click on link. Which is obviously bad. So, is there any way to prevent such a behavior?
Working fiddle
We could use a flag in this case to prevent click event just during the scroll and enable it after the scroll stop.
To listen on scroll stop you could use jQuery’s data method that gives us the ability to associate arbitrary data with DOM nodes and using setTimeout() function that will check every 250ms if the user still trigger the scroll, and if not it will change the flag :
var disable_click_flag = false;
$(window).scroll(function() {
disable_click_flag = true;
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
disable_click_flag = false;
}, 250));
});
$("body").on("click", "a", function(e) {
if( disable_click_flag ){
e.preventDefault();
}
});
Hope this helps.
I'm trying to reliably identify when a browser window/tab is activated and deactivated. Normally, window's focus and blur events would do, but the document contains several iframes.
When an iframe is focused, the main window gets unfocused and vice versa, so we have the following possibilities of focus events [(none) means the window/tab is deactivated]:
current focus new focus events
----------------------------------------------------------------------
window (none) window:blur
window iframe window:blur + iframe:focus
iframe (none) iframe:blur
iframe window iframe:blur + window:focus
iframe another iframe iframe:blur + iframe:focus
(none) window window:focus
(none) iframe iframe:focus
It is no problem to register all of these events, as shown by this fiddle. But whenever we switch from the main window to an iframe or vice versa, or between two iframes, the respective blur and focus events both fire; and they fire with a small delay at that.
I am worried about the concurrency here, since the blur handler could go and start doing stuff, but it should have never started because the user actually just switched focus somewhere in between the frames.
Example: A page should do some AJAX requests periodically whenever it is currently not active. That is, it should start requesting whenever the user deactivates the tab and stop requesting as soon as it's activated again. So we bind a function to the blur event that initiates the requests. If the user just clicks on another iframe, blur, and shortly after that, focus is triggered. But the blur handler already fires away, making at least one request before it can be stopped again.
And that's my problem: How can I reliably detect when a user actually (de-)activates a browser window containing iframes, without risking to get a false alarm caused by two immediate blur and focus events?
I wrote a half-baked solution that uses a timeout after a blur event in order to determine if there was an immediate focus event after it (fiddle):
var active = false,
timeout = 50, // ms
lastBlur = 0,
lastFocus = 0;
function handleBlur() {
if (lastBlur - lastFocus > timeout) {
active = false;
}
}
function handleFocus() {
if (lastFocus - lastBlur > timeout) {
active = true;
}
}
$(window).on('focus', function () {
lastFocus = Date.now();
handleFocus();
}).on('blur', function () {
lastBlur = Date.now();
window.setTimeout(handleBlur, timeout);
});
$('iframe').each(function () {
$(this.contentWindow).on('focus', function () {
lastFocus = Date.now();
handleFocus();
}).on('blur', function () {
lastBlur = Date.now();
window.setTimeout(handleBlur, timeout);
});
});
But I believe this could be very problematic, especially on slower machines. Increasing the timeout is also not acceptable to me, 50 ms is really my pain threshold.
Is there a way that doesn't depend on the client to be fast enough?
you could poll for the document.hasFocus() value, which should be true if either an iframe or the main window are focused
setInterval(function checkFocus(){
if( checkFocus.prev == document.hasFocus() ) return;
if(document.hasFocus()) onFocus();
else onBlur();
checkFocus.prev = document.hasFocus();
},100);
function onFocus(){ console.log('browser window activated') }
function onBlur(){ console.log('browser window deactivated') }
I was trying to do it without polling, but the iframe doesn't fire an onblur event (if the browser window is deactivated when the iframe was on focus, I get no events fired), so I ended up needing polling for half of it anyway, but maybe someone can figure something out with this code
function onFocus(){ console.log('browser window activated'); }
function onBlur(){ console.log('browser window deactivated'); }
var inter;
var iframeFocused;
window.focus(); // I needed this for events to fire afterwards initially
addEventListener('focus', function(e){
console.log('global window focused');
if(iframeFocused){
console.log('iframe lost focus');
iframeFocused = false;
clearInterval(inter);
}
else onFocus();
});
addEventListener('blur', function(e){
console.log('global window lost focus');
if(document.hasFocus()){
console.log('iframe focused');
iframeFocused = true;
inter = setInterval(()=>{
if(!document.hasFocus()){
console.log('iframe lost focus');
iframeFocused = false;
onBlur();
clearInterval(inter);
}
},100);
}
else onBlur();
});
I would like to display a helpful DIV that basically shows the user how to accomplish something on a particular page, but only if the user has been idle for a period of time, say, 30seconds.
What I mean by "Idle" is:
Not clicking any links
Not right clicking anywhere
Exceptions:
I would like to exclude the following conditions from the Is User Idle rule:
User has scrolled up or down/left or right
User has pressed mouse button on an empty area on the site/ or on an element which has no source/link for example, an image with no hyperlink.
and, Pressing keyboard buttons
Can this be done? Or can we only detect when a particullar event occurs?
Any thoughts/suggestions/resources will be greatly appreciated.
Thank you
fairly basic...
var trigger = 30000
$.(function(){
setInterval('displayInf()',trigger );
$('body').bind('click dblclick keypress mousemove scroll', function(){
clearDisplayInf();
});
});
function displayInf()
{
$('body').append('<div>Your notification div</div>');
}
function clearDisplayInf()
{
trigger = clearInterval(trigger);
trigger = setInterval('displayInf()', 30000 );
}
that should do the trick - you could add some script to make the div removable and start the timer again once its removed but that just polishing up really..
Event in DOM would bubble from leaf to root, thus add a event listener on document would make sense.
But since we are possibiliy stop bubbling for click event in certain element, register click event on document may not work perfectly, in that case, register mousedown and mouseup event would help:
var timer; // create a timer at first
// restart timer on click
function startIdle() {
timer = setTimeout(function() { /* show div */ }, time);
}
if (document.addEventListener) {
document.addEventListener('mouseup', startIdle, false);
}
else {
document.attachEvent('onmouseup', startIdle);
}
// start the first timer
startIdle();