I'm currently working in a system with a bit of a legacy presentation layer -- it uses frames (actual, in a frameset frames).
To get some event handling up and running I would like to get events when the frame resizes or at least be able to measure the height of the frame somehow. There seems to be no cross browser way to do this. Has anyone tried anything like this?
Try this - Also you might have to try this on all browsers too -
<!--
Example File From "JavaScript and DHTML Cookbook"
Published by O'Reilly & Associates
Copyright 2003 Danny Goodman
-->
function getFrameSize(frameID) {
var result = {height:0, width:0};
if (document.getElementById) {
var frame = parent.document.getElementById(frameID);
if (frame.scrollWidth) {
result.height = frame.scrollHeight;
result.width = frame.scrollWidth;
}
}
return result;
}
Related
I have this problem where in firefox the speech gets cut off if the page is auto-refreshed, but in google chrome it finishes saying the speech even if the page is auto-refreshed. How do I fix it so that the speech doesn't get cut off in firefox even when the page is auto-refreshed?
msg = new SpeechSynthesisUtterance("please finish saying this entire sentence.");
window.speechSynthesis.speak(msg);
(function ($) {
'use strict';
if (window == window.top) {
var body = $('body').empty();
var myframe = $('<iframe>')
.attr({ src: location.href })
.css({ height: '95vh', width: '100%' })
.appendTo(body)
.on('load', function () {
var interval;
interval = 750;
setTimeout(function () {
myframe.attr({ src: location.href });
}, interval);
});
}
})(jQuery);
I have this problem where in firefox the speech gets cut off if the
page is auto-refreshed, but in google chrome it finishes saying the
speech even if the page is auto-refreshed.
The described behaviour for Firefox is a sane expected implementation.
Browsing the source code of Firefox and Chromium the implementation of speechSynthesis.speak() is based on a socket connection with the local speech server. That server at *nix is usually speech-dispatcher or speechd (speech-dispatcher). See How to programmatically send a unix socket command to a system server autospawned by browser or convert JavaScript to C++ souce code for Chromium? for description of trying to implement SSML parsing at Chromium.
Eventually decided to write own code to achieve that requirement using JavaScript according to the W3C specification SpeechSynthesisSSMLParser after asking more than one question at SE sites, filing issues and bugs and posting on W3C mailings lists without any evidence that SSML parsing would ever be included as part of the Web Speech API.
Once that connection is initiated a queue is created for calls to .speak(). Even when the connection is closed Task Manager might still show the active process registered by the service.
The process at Chromium/Chrome is not without bugs, the closest that have filed to what is being described at the question is
Issue 797624: "speak speak slash" is audio output of .speak() following two calls to .speak(), .pause() and .resume()
Why hasn't Issue 88072 and Issue 795371 been answered? Are Internals>SpeechSynthesis and Blink>Speech dead? (for possible reason why "but in google chrome it finishes saying the speech even if the page is auto-refreshed." is still possible at Chrome)
.volume property issues
Issue 797512: Setting SpeechSynthesisUtterance.volume does not change volume of audio output of speechSynthesis.speak() (Chromium/Chrome)
Bug 1426978 Setting SpeechSynthesisUtterance.volume does not change volume of audio output of speechSynthesis.speak() (Firefox)
The most egregious issue being Chromium/Chrome webkitSpeechReconition implementation which records the users' audio and posts that audio data to a remote service, where a transcript is returned to the browser - without explicitly notifying the user that is taking place, marked WONT FIX
Issue 816095: Does webkitSpeechRecognition send recorded audio to a remote web service by default?
Relevant W3C Speech API issues at GitHub
The UA should be able to disallow speak() from autoplaying #27
Precisely define when speak() should fail due to autoplay rules #35 (ironically, relevant to the reported behaviour at Chromium/Chrome and output described at this question, see Web Audio, Autoplay Policy and Games and Autoplay Policy Changes)
Intent to Deprecate: speechSynthesis.speak without user activation
Summary
The SpeechSynthesis API is actively being abused on the web. We don’t have hard data on abuse, but since other autoplay avenues are
starting to be closed, abuse is anecdotally moving to the Web Speech
API, which doesn't follow autoplay rules.
After deprecation, the plan is to cause speechSynthesis.speak to
immediately fire an error if specific autoplay rules are not
satisfied. This will align it with other audio APIs in Chrome.
Timing of SpeechSynthesis state changes not defined #39
Timing of SpeechSynthesisUtterance events firing not defined #40
Clarify what happens if two windows try to speak #47
In summary, would not describe the behaviour at Firefox as a "problem", but the behaviour at Chrome as being a potential "problem".
Diving in to W3C Web Speech API implementation at browsers is not a trivial task. For several reasons. Including the apparent focus, or available option of, commercial TTS/SST services and proprietary, closed-source implementations of speech synthesis and speech recognition in "smart phones"; in lieu of fixing the various issues with the actual deployment of the W3C Web Speech API at modern browsers.
The maintainers of speechd (speech-dispatcher) are very helpful with regards to the server side (local speech-dispatcher socket).
Cannot speak for Firefox maintainers. Would estimate it is unlikely that if a bug is filed relevant to the feature request of continuing execution of audio output by .speak() from reloaded window is consistent with recent autoplay policies implemented by browsers. Though you can still file a Firefox bug to ask if audio output (from any API or interface) is expected to continue during reload of the current window; and if there are any preferences or policies which can be set to override the described behaviour, as suggested at the answer by #zip. And get the answer from the implementers themselves.
There are individuals and groups that compose FOSS code which are active in the domain and willing to help SST/TTS development, many of which are active at GitHub, which is another option to ask questions about how to implement what you are trying to achieve specifically at Firefox browser.
Outside of asking implementers for the feature request, you can read the source code and try create one or more workarounds. Alternatives include using meSpeak.js, though that still does not necessarily address if Firefox is intentionally blocking audio output during reload of the window.
Not sure why there's a difference in behavior... guest271314 might be on to something in his answer. However, you may be able to prevent FF from stopping the tts by intercepting the reload event with a onbeforeunload handler and waiting for the utterance to finish:
msg = new SpeechSynthesisUtterance("say something");
window.speechSynthesis.speak(msg);
window.onbeforeunload = function(e) {
if(window.speechSynthesis.speaking){
event.preventDefault();
msg.addEventListener('end', function(event) {
//logic to continue unload here
});
}
};
EDITED: See more elegant solution with promises below initial answer!
Below snippet is a workaround to the browser inconsistencies found in Firefox, checking synth.speaking in the interval and only triggering a reload if it's false prevents the synth from cutting of prematurely:
(It does not NOT work properly in the SO snippet, I assume it doesn't like iFrames in iFrames or whatever, just copy paste the code in a file and open it with Firefox!)
<p>I'm in the body, but will be in an iFrame</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var synth = window.speechSynthesis;
msg = new SpeechSynthesisUtterance("please finish saying this entire sentence.");
synth.speak(msg);
(function ($) {
'use strict';
if (window == window.top) {
var body = $('body').empty();
var myframe = $('<iframe>')
.attr({ src: location.href })
.css({ height: '95vh', width: '100%' })
.appendTo(body)
.on('load', function () {
var interval;
interval = setInterval(function () {
if (!synth.speaking) {
myframe.attr({ src: location.href });
clearInterval(interval);
}
}, 750);
});
}
})(jQuery);
</script>
A more elaborate solution could be to not have any setTimeout() or setInterval() at all, but use promises instead. Like this the page will simply reload whenever the message is done synthesizing, no matter how short or long it is. This will also prevent the "double"/overlapping-speech on the initial pageload. Not sure if this helps in your scenario, but here you go:
<button id="toggleSpeech">Stop Speaking!</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
if (window == window.top) {
window.speech = {
say: function(msg) {
return new Promise(function(resolve, reject) {
if (!SpeechSynthesisUtterance) {
reject('Web Speech API is not supported');
}
var utterance = new SpeechSynthesisUtterance(msg);
utterance.addEventListener('end', function() {
resolve();
});
utterance.addEventListener('error', function(event) {
reject('An error has occurred while speaking: ' + event.error);
});
window.speechSynthesis.speak(utterance);
});
},
speak: true,
};
}
(function($) {
'use strict';
if (window == window.top) {
var body = $('body').empty();
var myframe = $('<iframe>')
.attr({ src: location.href })
.css({ height: '95vh', width: '100%' })
.appendTo(body)
.on('load', function () {
var $iframe = $(this).contents();
$iframe.find('#toggleSpeech').on('click', function(e) {
console.log('speaking will stop when the last sentence is done...');
window.speech.speak = !window.speech.speak;
});
window.speech.say('please finish saying this entire sentence.')
.then(function() {
if ( window.speech.speak ) {
console.log('speaking done, reloading iframe!');
myframe.attr({ src: location.href });
}
});
});
}
})(jQuery);
</script>
NOTE: Chrome (since v70) does NOT allow the immediate calling of window.speechSynthesis.speak(new SpeechSynthesisUtterance(msg)) anymore, you will get an error speechSynthesis.speak() without user activation is no longer allowed..., more details here. So technically the user would have to activate the script in Chrome to make it work!
Firefox:
First of all type and search for the “about: config” inside the browser by filling it in the address bar. This will take to another page where there will be a pop up asking to Take Any Risk, you need to accept that. Look for the preference named “accessibility.blockautorefresh” from the list and then right-click over that. There will be some options appearing as the list on the screen, select the Toggle option and then set it to True rather than False. This change will block the Auto Refresh on the Firefox browser. Remember that this option is revertable!
First of all, sorry for ressurrecting this question here.
I've been trying for two days how to reach this job using javascript/jquery and i think i've read all stack overflow and other blogs posts about that, so please, don't mark it as duplicated because I can't use out-dated scripts from 2012 now in 2017.
I've a single page that redirects to a third party e-learning platform where some content needs flash to work. Many users don't care about which software is installed on their machines (what a new, huh) so i need to detect it and show the tipical message "please install/update flash player clicking here", but i cannot find a "modern" script/way to do this, in any place, simplified, if possible.
All scripts i've tried are deprecated or returns false in all browsers, even i've newest version of flash installed and active.
Anny help will be appreciated (except links to older posts or scripts that don't work nowadays, obviously).
Thanks a lot!
There is a simple way to check for Flash since all the installed and enabled plugins will be listed in navigator.plugins;
Note that if a plugin is installed, but not enabled, it will not be detected in the navigator.plugins array. There is NO way to detect this using Javascript (this Question which confirms the same).
Having said that, use the following function isFlashEnabled(); to detect Flash :
<html>
<script>
if(isFlashEnabled())
{ document.write('Flash is installed (but may need to be enabled)'); }
else { document.write('Flash is either not installed or disabled'); }
function isFlashEnabled()
{
var flash = navigator.plugins.namedItem('Shockwave Flash');
if (!flash) { return 0; }
else { return 1; }
}
</script>
<body> <embed src="https://www.w3schools.com/tags/helloworld.swf"> </body>
</html>
You can get an array which contains all installed plugins of a browser like this:
var plugins = navigator.plugins;
Then you can then check if the array contains the flash plugin.
From https://developer.mozilla.org/de/docs/Web/API/NavigatorPlugins/plugins:
function getFlashVersion() {
var flash = navigator.plugins.namedItem('Shockwave Flash');
if (typeof flash != 'object') {
// flash is not present
return undefined;
}
if(flash.version){
return flash.version;
} else {
//No version property (e.g. in Chrome)
return flash.description.replace(/Shockwave Flash /,"");
}
}
I'm in need of some help.
I'm building a team bio page it keeps crashing IE8 when I call jQuery plugins.
I'm not sure what is going on and can't even run the IE debugger because it crashes so hard.
Any IE8 / jQuery experts out there willing to take a look and offer some help?
Here is the main team page. Clicking through to any of the links causes the crash in IE8.
I am using:
jQuery Tagsphere, AnythingSlider, and jQuery Cycle.
Thanks in advance for any insight into this.
I had a similar problem, most notably closing iframes with IE8. Stumbled across the following code in jquery-1.6.2, which was intended to solve problems with document.domain. Some comments on the web lead me to believe this was a recent problem. Dropped back to jquery-1.4.4 and the problem was resolved.
CODE SEGMENT FROM JQUERY-1.6.2 FOLLOWS:
// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
ajaxLocation = location.href;
} catch( e ) {
// Use the href attribute of an A element
// since IE will modify it given document.location
ajaxLocation = document.createElement( "a" );
ajaxLocation.href = "";
ajaxLocation = ajaxLocation.href;
}
I am curious about people's experiences with replacing the entire document at runtime in an Ajax web app. It's rare, but I've found a few situations where the app requires an entire page rebuild and everything is present locally without needing another server round-trip.
I can easily prepare the new document as either a new DOM tree or as a String. So I'm evaluating the trade-offs for various approaches.
If I want to use the String approach this seems to work:
document.open();
document.write(newStringDoc);
document.close();
Most browsers do this just fine, but many have a slight flicker when re-rendering. I've noticed that on the 2nd time through Firefox 4.0b7 will just sit there and spin as if it is loading. Hitting the stop button on the location bar seems to complete the page render. (Edit: this appears to be fixed in 4.0b8) Also this method seems to prevent the user from hitting refresh to reload the current URL (it reloads the dynamically generated page).
If I use a new DOM tree approach (which has different advantages/disadvantages in flexibility and speed), then this seems to work:
document.replaceChild(newDomDoc, document.documentElement);
Most browsers seem to handle this perfectly fine without flicker. Unfortunately, IE9 beta throws "DOM Exception: HIERARCHY_REQUEST_ERR (3)" on replaceChild and never completes. I haven't tried the latest preview release to see if this is just a new bug that got fixed. (Edit: this appears to be fixed in RC1.)
My question: does anyone have a different approach than either of these? Does anyone have any other caveats where perhaps a particular browser fundamentally breaks down with one of these approaches?
Update: Perhaps this will add context and help the imagination. Consider a situation where an application is offline. There is no server available to redirect or refresh. The necessary state of the application is already loaded (or stored) client-side. The UI is constructed from client-side templates.
I believe that Gmail uses iframes embedded within a root document. It appears the starting document for at least some of these iframes are just a bare HTML5 document which the parent document then manipulates.
Using an iframe would be another variant on the requirement to replace the current document by replacing the entire child iframe or just its document. The same situation exists though of what approach to attach the new document to the iframe.
I guess I will answer this with my own findings as I'm wrapping up my research on this.
Since the two browsers which have issues with one of these methods are both beta, I've opened bug reports which hopefully will resolve those before their full release:
Firefox 4 Beta: https://bugzilla.mozilla.org/show_bug.cgi?id=615927
Edit: Fixed in FF 4b8.
Internet Explorer 9 Beta: https://connect.microsoft.com/IE/feedback/details/626473
Edit: Fixed in IE9 RC1.
I've also found pretty consistently that this...
document.replaceChild(newDomDoc, document.documentElement);
...is 2-10x faster than this...
var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();
...even when including the time needed to build the DOM nodes vs. build the HTML string. This might be the reason for the flicker, or perhaps just another supporting argument for the DOM approach. Chrome doesn't have any flicker with either method.
Note the subtle change of storing the returned document which circumvents the bug in Firefox 4.0b7.
Also note this added MIME type which the IE docs claim is "required".
Finally, Internet Explorer seems to have a bit of trouble resolving link tags that were built before the new document is swapped in. Assigning the link href back to itself appears to patch it up.
// IE requires link repair
if (document.createStyleSheet) {
var head = document.documentElement.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
One could cover all bases and combine them like this...
var doc = document;
try {
var newRoot = newDoc.toDOM();
doc.replaceChild(newRoot, doc.documentElement);
// IE requires link repair
if (doc.createStyleSheet) {
var head = newRoot.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
} catch (ex) {
doc = doc.open("text/html");
doc.write(newDoc.toString());
doc.close();
}
...assuming you have the ability to choose your approach like I do.
I'm pondering switching to protovis for visualizations. One thing that keeps me skeptical however - since protovis creates its output as a div in a browser, I wonder if there is any at least semi-automatic way for me to create a bunch of images at once without opening each one and pressing "print" manually.
So the question would be:
do you think I can use a browserless JS engine like V8 to execute the code and print the result?
can I automate opening and printing within a browser?
is there another way to get automated images from protovis?
Thanks,
Nicolas
Have a look at this Google Groups thread about this very topic.
Check out http://www.phantomjs.org/
It is a headless browser.
It can do exactly what you want :
http://code.google.com/p/phantomjs/wiki/QuickStart#Rendering
rasterize.js:
if (phantom.state.length === 0) {
if (phantom.args.length !== 2) {
console.log('Usage: rasterize.js URL filename');
phantom.exit();
} else {
var address = phantom.args[0];
phantom.state = 'rasterize';
phantom.viewportSize = { width: 600, height: 600 };
phantom.open(address);
}
} else {
var output = phantom.args[1];
phantom.sleep(200);
phantom.render(output);
phantom.exit();
}
An example to produce the rendering of the famous Tiger (from SVG):
phantomjs rasterize.js http://ariya.github.com/svg/tiger.svg tiger.png