I'm looking to detect clicks in an iframe and based on this answer posted here a while ago (http://jsfiddle.net/oqjgzsm0/), I've got this piece of code working for all browsers except safari 9. For some reason, safari seems to not detect the elem.blur(); and keeps looping the action (in this case, a function call to refresh another iframe). Any ideas on how I can make this solution work for safari as well?
function reload() {
document.getElementById('iframe#2').src += '';
}
var monitor = setInterval(function(){
var elem = document.activeElement;
if(elem && elem.id == 'iframe#1'){
reload();
elem.blur(monitor);
return false;
}
}, 100);
Related
I have a React app, I've added eventlisteners to the window. So, this way I can detect if the user actually viewing the page or not. On computer browser, everything works as expected.
But I tried this on IphoneX (it's irrelevant but the browser was Safari), and I came across this: If the user holds the bottom of the menu and swipe away all the open ones, then onBlur doesn't work. It stays on the onFocus event. So actually window.eventlistener not working properly on mobile.
Also, when I open the browser again (but not clicking anything, just opening the browser and view the page) onFocus event also not working. It waits for me to touch or click somewhere on the page.
How to handle user focus/blur completely on mobile side?
In the documentation for iOS / Safari supported events, they suggest pageshow and pagehide to listen for the kind of activity that I think you're talking about.
you can use window.navigator to get all OS and browser info
You can use requestAnimationFrame to check if the user is watching the page.
function isWatching(){
console.log("watching: " + Date.now());
requestAnimationFrame(isWatching);
}
requestAnimationFrame(isWatching);
See the example here: https://jsfiddle.net/t2r1sp56/ and you should also read more about it here: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
You can use visibilityChange event and for the complete compatibility, you need to use webkit, ms, etc. prefix. I hope it helps :)
let visibilityEventName = '';
let hiddenProperty = '';
if (typeof document.hidden !== 'undefined') {
hiddenProperty = 'hidden';
visibilityEventName = 'visibilitychange';
} else if (typeof document.msHidden !== 'undefined') {
hiddenProperty = 'msHidden';
visibilityEventName = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hiddenProperty = 'webkitHidden';
visibilityEventName = 'webkitvisibilitychange';
}
// check whether this API is available or not and then proceed
if (visibilityEventName) {
document.addEventListener(visibilityEventName, () => {
if (document[hiddenProperty]) {
// not visible
} else {
// visible
}
}, false);
}
I have solved the issue using below event listeners.
document.addEventListener("visibilitychange", handleActivity);
document.addEventListener("blur", handleActivityFalse);
window.addEventListener("blur", handleActivityFalse);
window.addEventListener("focus", handleActivityTrue);
document.addEventListener("focus", handleActivityTrue);
I just found out that my script is working fine in Chrome, but not in FireFox - and I can't figure out why.
This is the site in development: www.fireflycovers.com
The script should execute when one of the round green buttons is clicked. (scrolls the window to the next container)
The script looks like this at the moment:
$('.scroll').css('display' , 'block');
$('.scroll').on('click', function(e) {
var container = $(this).parent();
// Scans if last container in group
while (document != container[0] &&
container.find('~.col, ~:has(.col)').length == 0) {
// If so, search siblings of parent instead
var container = container.parent(),
nextdiv = container.nextAll('.col, :has(.col)').first();
}
// Back to first .col (when no next .col)
if (nextdiv.length == 0) {
nextdiv = $(document).find('.col:first')
};
// Animates scrolling to new position
$('body').animate({scrollTop:nextdiv.offset().top}, 1000);
return false;
});
});
Did you try debugging at all? As in, putting console.log statements throughout your method to see what the values of things are at certain times and watching it execute? Anyway, does using this help at all?
$('body,html').animate({scrollTop:nextdiv.offset().top}, 1000);
Verified from Animate scrollTop not working in firefox
You need html because firefox behaves differently when it comes to overflow.
Thanks to Refresh (reload) a page once using jQuery? answer I could solve an issue.
I have a popup window with a checkbox I want to reflect changes from referred main page, almost instantly.
It works great in Safari, Firefox, Chrome, Opera but Internet Explorer.
Thank you
function updateDiv(){
var ord = getCookie('ordinals');
if( ord.indexOf("<?=$ordinal?>")==-1 ){
document.getElementById("chk<?=$ordinal?>").checked=false//no checked
}
else {
document.getElementById("chk<?=$ordinal?>").checked=true//checked
}
$('chk<?=$ordinal?>').html(newContent);
}
setInterval('updateDiv()', 1000); // that's 1 second
......
......
<body onload="updateDiv(); ....
I think your problem is with:
$('chk<?=$ordinal?>').html(newContent);
Try with this:
var jEl = $('chk<?=$ordinal?>');
jEl.empty();
jEl.append(newContent);
I need to know if the user is currently viewing a tab or not in Google Chrome. I tried to use the events blur and focus binded to the window, but only the blur seems to be working correctly.
window.addEventListener('focus', function() {
document.title = 'focused';
});
window.addEventListener('blur', function() {
document.title = 'not focused';
});
The focus event works weird, only sometimes. If I switch to another tab and back, focus event won't activate. But if I click on the address bar and then back on the page, it will. Or if I switch to another program and then back to Chrome it will activate if the tab is currently focused.
2015 update: The new HTML5 way with visibility API (taken from Blowsie's comment):
document.addEventListener('visibilitychange', function(){
document.title = document.hidden; // change tab text for demo
})
The code the original poster gives (in the question) now works, as of 2011:
window.addEventListener('focus', function() {
document.title = 'focused';
});
window.addEventListener('blur', function() {
document.title = 'not focused';
});
edit: As of a few months later in Chrome 14, this will still work, but the user must have interacted with the page by clicking anywhere in the window at least once. Merely scrolling and such is insufficient to make this work. Doing window.focus() does not make this work automatically either. If anyone knows of a workaround, please mention.
The selected answer for the question Is there a way to detect if a browser window is not currently active? should work. It utilizes the Page Visibility API drafted by the W3C on 2011-06-02.
It might work after all, i got curious and wrote this code:
...
setInterval ( updateSize, 500 );
function updateSize(){
if(window.outerHeight == window.innerHeight){
document.title = 'not focused';
} else {
document.title = 'focused';
}
document.getElementById("arthur").innerHTML = window.outerHeight + " - " + window.innerHeight;
}
...
<div id="arthur">
dent
</div>
This code does precisly what you want, but on an ugly way. The thing is, Chrome seems to ignore the title change from time to time (when switching to the tab and holding the mouse down for 1 sec seems to always create this effect).
You will get different values on your screen, yet your title won't change.
conclusion:
Whatever you are doing, don't trust the result when testing it!
For anyone who wants to swap page titles on blur and then go back to the original page title on focus:
// Swapping page titles on blur
var originalPageTitle = document.title;
window.addEventListener('blur', function(){
document.title = 'Don\'t forget to read this...';
});
window.addEventListener('focus', function(){
document.title = originalPageTitle;
});
I found that adding onblur= and onfocus= events to inline bypassed the issue:
This could work with JQuery
$(function() {
$(window).focus(function() {
console.log('Focus');
});
$(window).blur(function() {
console.log('Blur');
});
});
In chrome you can run a background script with a timeout of less than 1 second, and when the tab does not have focus chrome will only run it every second. Example;
This doesn't work in Firefox or Opera. Don't know about other browsers, but I doubt it works there too.
var currentDate = new Date();
var a = currentDate.getTime();
function test() {
var currentDate = new Date();
var b = currentDate.getTime();
var c = b - a;
if (c > 900) {
//Tab does not have focus.
} else {
//It does
}
a = b;
setTimeout("test()",800);
}
setTimeout("test()",1);
Here is the situation. I have some javascript that looks like this:
function onSubmit() {
doSomeStuff();
someSpan.style.display="block";
otherSpan.style.display="none";
return doLongRunningOperation;
}
When I make this a form submit action, and run it from a non IE browser, it quickly swaps the two spans visibility and run the long javascript operation. If I do this in IE it does not do the swap until after onSubmit() completely returns.
I can force a dom redraw by sticking an alert box in like so:
function onSubmit() {
doSomeStuff();
someSpan.style.display="block";
otherSpan.style.display="none";
alert("refresh forced");
return doLongRunningOperation;
}
Also, the obvious jquery refactoring does not affect the IE behavior:
function onSubmit() {
doSomeStuff();
$("#someSpan").show();
$("#otherSpan").hide();
return doLongRunningOperation;
}
This behavior exists on IE8 and IE6. Is there anyway to force a redraw of the DOM in these browsers?
Mozilla (maybe IE as well) will cache/delay executing changes to the DOM which affect display, so that it can calculate all the changes at once instead of repeatedly after each and every statement.
To force an update (to force an immediate, synchronous reflow or relayout), your javascript should read a property that's affected by the change, e.g. the location of someSpan and otherSpan.
(This Mozilla implementation detail is mentioned in the video Faster HTML and CSS: Layout Engine Internals for Web Developers.)
To continue what ChrisW says:
here's flushing script to flash DOM, so you don't have to call alert(""); (found at http://amolnw.wordpress.com/category/programming/javascript/):
function flushThis(id){
var msie = 'Microsoft Internet Explorer';
var tmp = 0;
var elementOnShow = document.getElementById(id);
if (navigator.appName == msie){
tmp = elementOnShow.parentNode.offsetTop + 'px';
}else{
tmp = elementOnShow.offsetTop;
}
}
It works for me!!!
Thanks for the tip.
I had this problem in Chrome 21 dragging a word that had a letter with a descender ('g'). It was leaving a trail of moth dust behind on the screen, which would vanish the next time something made the screen refresh. ChrisW's solution (interrogating a layout-sensitive property) didn't work.
What did work was to add a 1-pixel blank div at the top of the page, then remove it a millisecond later, by calling the following the function at the end of the drag operation:
// Needed by Chrome, as of Release 21. Triggers a screen refresh, removing drag garbage.
function cleanDisplay() {
var c = document.createElement('div');
c.innerHTML = 'x';
c.style.visibility = 'hidden';
c.style.height = '1px';
document.body.insertBefore(c, document.body.firstChild);
window.setTimeout(function() {document.body.removeChild(c)}, 1);
}
Note: You need the delay. Simply adding and removing the div doesn't work. Also, the div needs to be added above the part of the page that needs to be redrawn.
You can also wrap you longterm function in a setTimeout(function(){longTerm();},1);
Can your longRunningOperation be called asynchronously?
element.focus() works for me in IE10
function displayOnOff(){
var elm = document.getElementById("myDiv");
elm.style.display="block";
elm.focus();
for(var i=0; i<1000000; i++){
console.log("waiting...............");
}
elm.style.display = "none";
}