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');
Related
Related to this question, the workaround to launching a custom protocol after starting a websocket (so as to keep the socket open and polling) is to use an iframe element and set the src to be the custom protocol. But, if a user clicks the button that sets the src too quickly (i.e. they trigger the custom protocol too frequently), FF logs this warning:
"Iframe with external protocol was blocked due to lack of user activation, or because not enough time has passed since the last such iframe was loaded."
I can't seem to find any documentation on:
What constitutes user activation
How much time "enough time has passed" actually is
Does anyone know what exactly that warning means or what either of those bullet points are and how we can get around the limitation to allow launching a custom protocol (without refreshing the page or causing a popup) from within FF?
I've tried both having the iframe exist on the page beforehand and dynamically setting the src, as well as, dynamically creating the iframe with the src at the same time, but both end with the same warning being logged.
User activation means an event triggered by the user, such as mouse or keyboard events. This is similar to the way popup blockers work.
I doubt you'll find the "enough time" limit documented -- the programmers don't want to tell malware writers how to work around the restriction.
You say you're doing this when the user clicks on a button, so that should fit the "user activation" requirement. Are you doing it in a callback function that runs asynchronously from the event listener? That disconnects it from the user interaction -- it has to be directly in the listener function.
This question already has answers here:
Identifying Between Refresh And Close Browser Actions
(13 answers)
Closed 6 years ago.
I am currently looking at the "unload" event of a window to try to determine how the "unload" event was triggered, but am having little success. Is there a way to determine how the javascript event was triggered?
Page Refresh
Back Button (or navigate away from the page)
Closing the Browser
Essentially I need to execute some code only when the browser window is being closed, not refreshed or navigated away from.
Purpose: When a customer does an update of our software, the update will redirect their first Internet request to an offer page. There is a button for a "Do Not Bother" option, but some users will simply close their browser. Upon closing the browser, I need to duplicate the "Do Not Bother" functionality so the user no longer gets redirected to the offer page. Simply attaching to the "unload" event will not work due to the different ways of leaving a page.
No, and if there was it would be browser dependent.
What kind of code are you trying to run when the user closes the page?
Is it to logout the user?
Then the user would not be logged out if the browser crashes or the network connection breaks (and probably not if the computer goes to sleep/hibernation mode).
If it is for logout-purposes you should probably use a timestamp variable at the server that gets updated with every request (or use a ajax-ping), and logout the user if it hasn't been seen for a specified time.
Update: Found this answer here at stackoverflow.
Yes, there is a solution!
I've designed a solution based on onBeforeUnload+onLoad events, HTML5 local storage and client/server communication. See the details on https://stackoverflow.com/a/13916847/698168.
I use a method of doing keyboard "sniffing", in that it looks for keydown's of "F5", "ctrl+r", "alt-f4", "backspace" and others, and if it finds them flowing through the keyboard event queue, it sets boolean variables appropriately to trap that status... then I use a "onbeforeunload" function handler, which tests against those boolean status variables to decide what to do.
You can even shut down various keyboard strokes (like "ctrl+n" or "F1" for instance) by using preventDefault(), bubbles=false and returnValue=false in your keyboard handling.
This stuff is not for the faint of heart, but its certainly doable with some persistence and lots of cross browser testing!
This seems to be a common kind of complaint, but I don't see any exact duplicates and more importantly I don't see any working answers, so I'm joining the crowd.
I have some code that does
window.onbeforeunload = function() { PubNub.publish(...); };
to publish a message to a PubNub channel when the user leaves the current page. It's a chat forum, and we want to publish the fact that User X is no longer in the room. (Please suppress the urge to suggest other designs, such as having every user send a heartbeat; this is just a toy project I'm playing with.)
Watching the channel in another browser tab, I observe that the PubNub message gets published successfully 100% of the time when I
close the tab
and occasionally (both yes and no) when I
refresh by clicking the circley icon in the address bar
but apparently never when I
navigate away by clicking a link
navigate away by entering a new URL in the address bar
refresh by entering the same URL in the address bar
refresh by hitting ⌘R
Notice that even putting return "please don't exit"; in my onbeforeunload handler results in flaky publishing: sometimes I enter the same URL in the address bar and the publish happens, sometimes I enter the same URL and the publish doesn't happen.
Is this some quirk of Safari, and if so is there a known workaround?
Alternatively, is PubNub.publish() somehow "too slow" or "too multithreaded" to succeed during an onbeforeunload event? I don't really understand how onbeforeunload works.
(For the time being, the whole code can be accessed here, but if you're reading this question a month from now, be aware that that link may be dead and/or fixed.)
This is really what our Presence feature is for. Check it out here:
http://www.pubnub.com/docs/javascript/overview/presence.html
This way, when you "leave" the channel, the Presence system can broadcast this to those interested. Is this what you are looking for?
geremy
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.
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.