Detect if browser has more then 1 tab/window open - javascript

So i am developing a quiz web application. And i wanted to add a setting that the administrator of the quiz could set that would make it so the user could only have 1 window/tab open while the quiz is being taken.
The reason for this is to make it so they cant goto like google and google the answer while the quiz window/tab is open. Of course they could always open a different browser and do it that way, but still thought it would be a nice feature to have for them to enable.
Now i dont know if this would fall under a security sandbox violation (and thus not be available at all) but since i only want to detect if another tab or window is open and not get actual information about the tab/window i am hoping that this is someway possible using javascript.

You can't, but a possible workaround would be to use the new HTML5 fullscreen API. You could use a setInterval function to regularly test that document.fullScreen == true to ensure that the user has not toggled off the full screen.
This only works in modern browsers, and it's trivial to work around if the user knows his way around the JS console, but it does seem to fit your requirements.
Note that all fullscreen API implementations are currently vendor-prefixed.

There seems to be viable alternative to the approach described below the line: using Page Visibility API, currently supported by all the modern browsers. This looks like far more reliable than listening for blur. There's one possible way to do it:
// on quiz start
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
console.log('Y U hide?');
}
});
The problem is that visibilitychange event is fired only when page goes from visible to hidden (and vise versa). It still lets user open two browser instances - one with the quiz page, one with any favorite search engine, for example.
While you cannot detect the number of tabs open, you can try to check when the user goes away from the quiz page with this trick:
$(function(){
$(window).blur(function() {
console.log('I see what you did here!');
});
});
Sadly, it'll also give you plenty of false positives.

Can't, and shouldn't, be done.

Related

JavaScript speechSynthesis.speak() without user activation is no longer allowed since M71

I used speechSynthesis API in this way:
speechSynthesis.speak(new SpeechSynthesisUtterance("hello world"));
But right now I get error after update Google Chrome:
[Deprecation] speechSynthesis.speak() without user activation is no
longer allowed since M71, around December 2018. See
https://www.chromestatus.com/feature/5687444770914304 for more details
speechSynthesisMessage #
application-2c16c437c2795ae01c0a8852e5f8da58dad99d6e17814a31f1eea19922c5ebd2.js:147
How I can fix this issue and ask permission?
This is part of Chrome's new policies regarding making sound from web-pages.
You simply need your user to provide an user-gesture (for which you can find a list here) during the lifetime of the parent document (i.e the event may long be dead, as long as the user ever interacted with the page).
Note that these events can even traverse frames, so for instance, in StackOverflow, the simple fact that you do have to click on the "Run" button will make the inner frame allowed to execute this code:
const ut = new SpeechSynthesisUtterance('No warning should arise');
speechSynthesis.speak(ut);
And in your code, you simply have to provide some kind of an UI that will ensure your users have interacted with the page before you call this method (e.g a button / toggle will do perfectly).
If you set your site address as "trusted" in chrome://settings/content/sound it seems to enable sound and speech synthesis even without user interactions.
I use Chrome in a TV just as a system monitor, using kiosk mode and without any user interactions. It doesn't even have keyboard and mouse.
Still, I was able to enable in some versions of Chrome/Chromium, but not in others.
This error means entire document (Website) has no user interaction and Google Chrome update its policy regarding making sound from the website without user interaction.
User interaction means: click, dblclick, mouseup, pointerup, reset, submit etc.
Solution:
So, if you want to run speechSynthesis.speak(); without real user interaction, then you just create temporary user interaction using a method like .click(), etc.
Although I haven't found any way to ask permission, the user can enable permission in Google Chrome:
Click on the icon on the left of the URL bar, and open Site settings
Change the Sound setting from "Automatic (default)" to "Allow"
After doing that, the site will be able to make sounds without any user interaction, including speech.
Unfortunately, I haven't found a way in code to know whether this is working or not. (Perhaps we could try one of the other audio APIs and see if it responds with an error message.)
I resorted to swal("Click OK to speak").then(() => speakButton.click()); (with https://sweetalert.js.org) -- https://patarapolw.github.io/tts-api/?q=你好&lang=zh-CN&rate=0.8
Note that if (confirm("Click OK to speak")) speakButton.click() doesn't work.
I was having same issue, and could sort it by using window.onload like this:
window.onload = function(){
var u = new SpeechSynthesisUtterance('All is Ok');
u.text = 'Hello World';
u.lang = 'en-US';
u.rate = 1;
u.pitch = .4;
speechSynthesis.speak(u);
}
Of course this triggers only once after page is loaded, but it was a good solution for me.
A simple hack, without needing a real user activity, is to execute a click event on a hidden button like so.
document.querySelector('button').click();
var msg = new SpeechSynthesisUtterance('Test');

Is there a cross browser event for activate in the browser?

Is there a cross browser event that can be used to show a message to the user returning to their web page?
For example, a user has ten applications or tabs open. They get a new notification from our app and I show a notification box. When they switch to our tab I want to begin our notification animation.
The activate event is common on desktop applications but so far, on the window, document and body, neither the "activate" or "DOMActivate" do anything when swapping between applications or tabs but the "focus" and "blur" do. This event works but the naming is different and the events that should be doing this are not.
So is the right event to use cross browser or is there another event?
You can test by adding this in the console or page and then swapping between applications or tabs:
window.addEventListener("focus", function(e) {console.log("focused at " + performance.now()) } )
window.addEventListener("blur", function(e) {console.log("blurred at " + performance.now()) } )
Update:
In the link to the possible duplicate is a link to the W3 Page Visibility doc here.
It says to use the visibilitychange event to check when the page is visible or hidden like so:
document.addEventListener('visibilitychange', handleVisibilityChange, false);
But there are issues:
The Document of the top level browsing context can be in one of the
following visibility states:
hidden
The Document is not visible at all on any screen. visible
The Document is at least partially visible on at least one screen. This is the same condition under which the hidden attribute is set to
false.
So it explains why it's not firing when switching apps. But even when switching apps and the window is completely hidden the event does not trigger (in Firefox).
So at the end of the page is this note:
The Page Visibility API enables developers to know when a Document is
visible or in focus. Existing mechanisms, such as the focus and blur
events, when attached to the Window object already provide a mechanism
to detect when the Document is the active document.
So it would seem to suggest that it's accepted practice to use focus and blur to detect window activation or app switching.
I found this answer that is close to what would be needed to make a cross browser solution but needs focus and blur (at least for Firefox).
Observation:
StackOverflow has a policy against mentioning frameworks or libraries. The answers linked here have upvotes for the "best" answer.
But these can grow outdated. Since yesterday I found mention of two frameworks (polyfills) that attempt to solve this same problem here for visibly and isVis (not creating a link). If this is a question and answer site and a valid answer is, "here is some code that works for me" but "Here is the library I created using the same code that can be kept up to date and maintained on github" is not valid then in my opinion it's missing it's goal.
I know above should probably go to meta and I have but they resist changing the status quo for some reason. Mentioning it here since it's a relevant example.
The Page lifecycle API can be used to listen for visibilitychange events.
[This event triggers] when a user navigates to a new page, switches tabs, closes a tab, minimizes or closes the browser, or switches apps on mobile operating systems. Quote
Current browser support
Reference on MDN

Can I reliably detect whether a web page can be seen by a user?

I am trying to decide whether to do a somewhat expensive javascript-ajaxing-to-the-server operation, but it is only worth doing if the user can see the web page, so I'm trying to detect that.
I was initially excited to find the "visibilitychange" API, but it looks like that only detects if the web page is in a hidden tab. If the user opens up a new browser window instead of a new tab, the event isn't called. Nor is it called when the user changes to a different app.
I also think I'd like to slow down the operation if the browser isn't in the foreground, so there are really three states:
"request-every-5-seconds" Does the browser have the input focus?
"request-every-minute" Is any part of the page actually on the user's display?
"don't-request" the browser is buried under another window.
That way, a user who goes to my webpage and leaves the browser open won't be using resources either on the server or their computer.
For the first state monitoring "onfocus" mostly works, but the focus can get lost to the developer tools. That's a little annoying, but it isn't typical of a customer, so I can live with that.
For the second state, I have no idea where to start. One idea I had was to detect whether the browser is actually "painting", but I haven't found any way to detect that.
How do you decide whether it is worth checking for updates?
[note: I'm using jQuery already, so a jQuery-based answer is fine.]
Thanks.

preventing a browser from losing focus on external app call

I'm building a quick VOIP demo using Skype and when I press a call button, the Skype application takes the focus away from the browser. You can try here http://developer.skype.com/skype-uris/skype-uri-tutorial-webpages where you'll find several "Try it here" links. When I click those links, I would like the browser to maintain focus. Is there a way to do this?
Thanks.
What you would need to do is apparently called "focus stealing" from my web searches.
At least as far as Windows is concerned, there does not seem to be a reliable way to do this from the browser alone.
I just googled "focus stealing" (which is what the JavaScript only solution would need to do to get this done) and found many answers showing that, though theoretically possible, depending on the configuration of Windows stealing the focus away from Skype by the browser would probably not work in the majority of cases.
The complaints in the Google links are numerous and some answers conflict, but it looks like reliably "stealing the focus" back to the browser is not going to be supported.
This is a good thing though, if you think about it - I do not personally want just any old JavaScript program running in my browser to change my focus from what I am working on back to the browser willy nilly - this would be a very annoying behavior for a web page to be able to do at best, making my system useless at worst.
If you could do it in this case using some methodology allowed in a browser, so could anyone else - even malevolent websites.
The best answer is to never let the focus leave the browser, but I have no idea how to do that in your specific case. Perhaps whatever means you are using to launch Skype may have an option or something to launch it in the background or whatever, never changing the focus.
I did not hit on specific links pertaining to Apple OSes, Linux or mobile OSes, but I have a feeling the same concerns and limitations apply for those as well.
Here are some of the links on the Google search (and sorry about the bad news for your needs):
Microsoft Answers Forum Post
Focus stealing is evil
http://pcsupport.about.com/od/windowsxp/ht/stealingfocus02.htm
you can open it on new window, then close the new window and refocus on yours
somthing like:
a=window.open('skype:ohadcn?chat',10,10);
//i couldn't find a relevant event, onload() do not work for me here
//so i used setTimeOut, hoping that two seconds is enough to open skype but not enough to loose the user
setTimeout(function(){ a.close();window.focus();},2000)
I went to the skype tutorial page in Chrome, brought up the console and tried Ohad's answer, but it would not return the focus to the tutorial web page.
I even tried a script to perpetually put the focus in the Search textbox:
function ASDF() {
document.getElementsByName("q")[0].focus();
setTimeout(ASDF, 1000);
}
setTimeout(ASDF, 1000);
Still no luck.
I tried changing Ohad's script so that it would reopen the tutorial page in a new window after the skype app opened. It would work if the tutoral/console page was the only tab in the window:
a=window.open('skype:ohadcn?chat',10,10);
setTimeout(function(){
a.close();
a=window.open('http://developer.skype.com/skype-uris/skype-uri-tutorial-webpages', 10, 10);
window.close();},2000);
However, if the tutorial page/console script was in window with other tabs, it did not return focus to the reopened page. Not to mention, IE might warn the user that the original page is trying to close.
I do not think there is a way to consistently achieve your goal, but I reserve the right to be wrong.

How do I force a browser window to always be on top and in focus

Is there a way to force a browser window to always be on top and in focus? I am working on a project that I need to have the browser window on top and in focus all the time except when closing the browser window. I have tried a few things through javascript, but have not had any success keeping the window in focus.
I am not trying to do this to be forceful to the user. I am working on a project to implement online testing and I don't want the user to be able to switch away to look up answers on the web.
You will need to install a windows application on the clients machine which will force the browser to be on top. This is the only way.
If you are using IE, you can open a Modal dialog which will always be on top and in focus but only while in that browser session, the user is free to switch applications.
Edit: If you are writing a testing application, you are honestly better off just putting a reasonable time limit on each question. trying to prevent them from looking up the answers is worthless. What if they have two machines side by side? What if they have their buddy next to them helping with the answers. You are going to have to go with the honor system on this one.
This is not possible, as the application level focus is handled by the Windows operating system.
You would need to alter the operating system in order to achieve this functionality.
I commented on the question, but realized this is worth posting as an answer...
Find another solution. Think a little about it. If a user is off looking at answers in another window/tab/browser, what would be the side-effects of that? Detect those side-effects, and penalize/block in those cases.
For instance, you can detect the blur event on the window and then poll for activity (focus, click, mousemove, keypress and so on) to determine "idle" time for the user. If the user is "idle" long enough to have gone elsewhere to find an answer, they are more than likely "cheating". You can otherwise simply impose time constraints on questions, and skip those questions if the time allotted runs out.
You can't guarantee that your user is not "cheating". Either construct the "physical" rules of the test such that the chance of "cheating" is minimized, or construct the test itself so that "cheating" is less consequential. Do not try to circumvent in-built user protections in browsers that disallow users from operating their browser as they would any other application.
The browser window belongs to the browser, not to you. Don't screw around with it.
Don't do it, that is, unless you wrote the browser.
It once took me 15 minutes to create a reasonable web browser by using the Windows Forms WebBrowser control. I suggest you require the students to view your site through this custom browser program. Since this program really will be yours, you can force it to stay on top, or anything else you like.
JavaScript has the capabilities do this but it is disabled by default in most modern webbrowsers (And, as you would surely agree, there was a good reason for that!)

Categories