Iframe designmode in Firefox problem - javascript

This works in IE, but in firefox it's very strange:
If open it normally if firefox, the designmode doesn't work but if i put a breakpoint on
this.editor.contentWindow.document.designMode
= "On";
line, and then release it (after it breaks on it), the designmode works!
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<script type="text/javascript">
TheEditor = function() {
this.editor = null;
this.mainDiv=document.getElementById("mainDiv");
}
TheEditor.prototype = {
InitializeEditor: function() {
this.editor=document.createElement('iframe');
this.editor.frameBorder=1;
this.editor.width = "500px";
this.editor.height="250px";
this.mainDiv.appendChild(this.editor);
this.editor.contentWindow.document.designMode = "On";
}
}
window.onload = function(){
obj = new TheEditor;
obj. InitializeEditor();
}
</script>
</head>
<body>
<div id="mainDiv">
</div>
</body>
</html>

I don't full understand why, but opening (optionally writing content) and closing the document solves the issue (at least in FF5 on OSX):
this.editor.contentWindow.document.open();
// optionally write content here
this.editor.contentWindow.document.close();
this.editor.contentWindow.document.designMode = "on";
The other idea I had was to set a timeout around the designMode = "on" statement (I remember having to do this in the past for FF), but it did not work.
I think it has something to do with FF loading "something" in the IFRAME and it not being ready to turn designMode on.
I guess you could also use the contentEditable="true" attribute on the DIV instead.
Anyway, I hope this helps.

I think it's because the contentDocument not already created, I think you can also setup the iframe's onload event and set the design mode in this event, because this event is called when the page is loaded so the contentDocument exist !

Related

Calling a javascript function in a document created with document.write

I have a web page with a button. The click code is:
var html = ...html string containing visual and script elements...
var view = window.open();
view.document.write(html);
view.init(<parameters>); // see next code block
the html content is:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
html, body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<div id="id1"></div>
<script>
function init(<parameters>) {
...work...
}
</script>
</body>
</html>
The problem is with the init function call in chrome: all good if I am in IE, but in chrome I get "init function not defined" exception.
How should I do to get this working in all browsers? Of course I am looking for a solution that doesn't require a server round trip.
IM a noob so idk if this is exaclty true but i have read that ie allows you to do alot more then chrome or firefox. It might be one of those example where ie will let you do something.
using document.write does in fact work when it comes to create the page I want. Problem is when I want to call a function defined in a javascript block inside that page. Different browsers give different results so I guess this is a matter not completely standardized yet. There are posts in the internet about this, but I couldn't find a clear and common answer.
I then solved my impasse with a workaround. The initial markup contains now placeholders for the parameters:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
html, body {
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<div id="id1"></div>
<script>
(init = function () {
var parameter1 = ${{placeholder1}}
var parameter2 = ${{placeholder2}}
...
...work...
})();
</script>
</body>
</html>
The creating code, then, replaces the placeholders with actual values:
var html = ...html string containing placeholders...
html = html.replace("${{placeholder1}}", actual1);
html = html.replace("${{placeholder2}}", actual2);
...
var view = window.open();
view.document.write(html);
Now the init function is called in the same page context, and this works in Chrome as well.
It is not possible to write to a new window if its not on the same domain. What I suggest is that you can open an iframe an work inside that.
How to write to iframe
How to write to page on same domain

Adding a <script> node on top of <body> from javascript in <head>

I want to insert some javascript code,
That should be run before other javascript codes in the <body>run.
As they manipulate html in <body>, that are inside <body>.
Normally i would put this javascript in a <script> tag right after the opening <body> tag. But I am not writing the html directly. Its generated for me by a program. (react-storybook). Its API allows to inject html inside <head> but not <body>.
<head>
<script></script> <-- I can inject a script tag here
</head>
<body>
<script></script> <-- I can't directly add this script tag but I need one here
<script>other js</script>
</body>
I tried putting my js in a document load event handler, but they run after body is completely loaded so other js has already run.
I tried putting my js directly in the head then my js can't use appendChild on body, because at that point document.body is null.
Is there a way to insert a script tag satisfying both above requirements with accessing only the <head>?
I don't see any way to do this without probably breaking the tool you're trying to work within and doing some fairly nasty things. I suspect there's a better way to solve your underlying problem.
I tried putting my js directly in the head then my js can't use appendChild on body, because at that point document.body is null...
It's nasty and probably a bad idea, but you could force the body to be started:
document.write("<body>");
At that point, the parser will create the body element. You can then use appendChild (or just continue using the evil document.write). When the body is started again later in the normal course fo things, that second opening tag will be ignored.
It's not a good idea. react-storybook is open source. If there isn't a way to achieve your actual goal with it already, I suggest modifying it so you can rather than doing something like the above.
Here's an example, tested and working in Chrome, Firefox, IE11, IE8, and iOS Safari.(Live copy on JSBin):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Example</title>
<script>
(function() {
var d = document.createElement("div");
d.innerHTML =
"This is the element appended to the body element " +
"that we forced to be created using the evil " +
"<code>document.write</code>";
document.write("<body>");
document.body.appendChild(d);
})();
</script>
</head>
<body>
<div>
This is the first element inside the body element in the markup.
</div>
</body>
</html>
I tried putting my js directly in the head then my js can't use appendChild on body, because at that point document.body is null.
MutationObserver to the rescue!
You can simply wait for the <body> tag to be parsed:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script>
new MutationObserver(function(records, self)
{
for(var i = 0; i < records.length; ++i)
{
for(var j = 0; j < records[i].addedNodes.length; ++j)
{
if(records[i].addedNodes[j].nodeName == 'BODY')
{
self.disconnect();
console.log('herp');
/*
At this point, the body exists, but nothing inside it has been parsed yet.
document.body might be available, but to be safe, you can use:
var body = records[i].addedNodes[j];
*/
}
}
}
}).observe(document.documentElement,
{
childList: true,
});
</script>
</head>
<body>
<script>console.log('derp');</script>
</body>
</html>
Save this to an HTML file, open it in your browser, and you should see this in the console (indicating that the "herp" part runs before the "derp" one (note: Firefox seems to discard message order if the console is opened after the page loads, but the "herp" part is actually still running before the "derp" one)):
herp
derp
(Note: The above code won't work as a stack snippet, because everything is placed in the <body> tag there.)
Now just to be safe, I'd add a check to see if document.body is already set, and only set up the MutationObserver if that isn't the case:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script>
function onBodyLoaded(body)
{
console.log('herp');
/* Do whatever you want with "body" here. */
}
if(document.body)
{
onBodyLoaded(document.body)
}
else
{
new MutationObserver(function(records, self)
{
for(var i = 0; i < records.length; ++i)
{
for(var j = 0; j < records[i].addedNodes.length; ++j)
{
if(records[i].addedNodes[j].nodeName == 'BODY')
{
self.disconnect();
onBodyLoaded(records[i].addedNodes[j]);
}
}
}
}).observe(document.documentElement,
{
childList: true,
});
}
</script>
</head>
<body>
<script>console.log('derp');</script>
</body>
</html>
This way you might not have to add a <script> tag to your body at all, but just place the code you want to run there inside the onBodyLoaded function.
If you do need to add a script tag though, you can do so with:
function onBodyLoaded(body)
{
body.appendChild(document.createElement('script')).src = 'https://example.com/my.js';
}
or
function onBodyLoaded(body)
{
body.appendChild(document.createElement('script')).innerHTML = 'document.write("hi there")';
}
Note that IE 10 and earlier don't support MutationObserver. IE 11 and any other browser from this decade should work though.

Set Window focus with a link

I have a problem with Javascript window focus setting.
I've written a function to open a new window with the JS method window.open() and save the return value to a variable.
Now I have a link on the first page and by clicking on this link the second, with window.open() opened, window should get the focus.
But this won't work. Is there any way to get this working?
My code looks like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<script type="text/javascript" language="JavaScript">
var myWindow;
function checkForRefresh() {
myWindow = window.open("test.html", "TestMain");
myWindow.focus();
}
function switchFocus(umsWindow) {
myWindow.focus();
}
</script>
</head>
<body onLoad="checkForRefresh()">
<p>Test Link</p>
</body>
</html>
This problem has been talked already, some browsers does not listen to window.focus(). Please take a look at comment #2533335.
I got it to work when I made the functions properly global by putting them on the window object
http://jsfiddle.net/u52xE/3/
window.switchFocus = function() {
myWindow.focus();
}
It's not ideal to have that javascript in your HTML and global functions though, I'd recommend using jQuery to attach events

Very strange IE crash problem with stylesheet javascript object

Hello I use javascript stylesheet object, with a specfic style and place it on dom ready. When i do exactly my code IE crash.
The problem is the UL with exactly this style set after the page is load. If I place the styleSheet.cssText = css; before the page load, everyting is correct. If i remove the char f in <DIV>f everything work. I need to use my code after the page is load. Any suggestion to pass over this trouble ?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>test</title>
<script type="text/javascript" src="./jquery-1.4.2.min.js" ></script>
<script type="text/javascript">
var styleSheet = document.createStyleSheet();
var css= "UL{list-style-type:none;display:inline;}LI{padding:0px;}";
$(document).ready(function(){
styleSheet.cssText = css;
});
</script>
</head>
<body>
<DIV>f
<UL>
<LI><a>dfgfdg</a></LI>
<LI><a>fdgdfg</a></LI></UL>?
</DIV>?
</body>
</html>
The problem is IE8 specific. It seems to work on ie7 and ie9.
In order to reproduce the bug it is important to apply the stylesheet after the page is loaded.
We used jquery.ready() for this example but the code also crashes for click and load events.
This bug is very specific. It requires the precise css and html used in the example above. We have tried adding the stylesheet in different ways ( stylesheet.rules[i].lisStyleType='none' for example and adding the stylesheet in a .css file) with no success. We absolutely need to add the style dynamically where this probleme is happening.
createStyleSheet is not a cross-browser friendly solution... Try this code instead:
$(function(){
var styles = "UL{list-style-type:none;display:inline;}LI{padding:0px;}";
var newSS=document.createElement('link');
newSS.rel='stylesheet';
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
});
I can't tell you exactly why IE is crashing, but this code works for me and it shouldn't trigger any unexpected errors.
I tried your code in a jsfiddle and it doesn't bug with IE7 .. what's the problem ?
What version of IE are you using ? Do you have an url of a demo that's crashing for you ? I can't reproduce your problem, please see my jsfiddle ...
Btw why do you use jquery 1.4.2 and not a more recent version ? 1.4.4 or 1.5.2 , in the jsfiddle I choosed 1.4.4
Please Try this. Tested in IE6,7,8,9 FF, Opera, Googlechrome, Safari
<script type="text/javascript">
function createRuntimeStyle(){
//create a style tag
var rStyle=document.createElement("style");
//create the content of the style tag
var cssDef=document.createTextNode(".myclass{display:block;font-family:Verdana;font-weight:bold;}");
//assign the type
rStyle.type="text/css";
if(rStyle.styleSheet){ //check for IE
rStyle.styleSheet.cssText=cssDef.nodeValue;
}else{ //check for Other Browsers
rStyle.appendChild(cssDef);
}
//append to document head
document.getElementsByTagName("head")[0].appendChild(rStyle);
}
//call to the function
createRuntimeStyle();
</script>

Fire link onclick events and follow href from Javascript

I have a page defining a link ('a' tag) and some onclick events associated with it.
I am trying to add an arbitrary HTML element (in this case a div) with the ability to respond to click events by firing the click events of the link.
The code below describes all that.
The end goal is to trigger exactly the same actions whether the click was on the link or on the div without modifying the link or its onclick events.
My problem is that browsers don't respond in a consistent way when the div is clicked:
Google Chrome fires all 3 events and then follows the link href,
Firefox and IE fire the 3 events but do not follow the link href. In that case I can just add window.location = link.href to the div onclick handler.
Is it possible to make all browsers work the same way, whether it is the 1st or 2nd case ?
If it is not possible, do you have any suggestion that doesn't require modifying the link onclick events (event.stop()) or testing for the browser engine (if (not chrome) { window.location = link.href })?
Edit: Safari works the same way as Chrome, so I suppose this is a webkit issue.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>test</title>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("prototype", "1.6.1.0");</script>
</head>
<body>
<div>
<a id="google_link" href="http://google.com" target="_blank">click to go to google</a>
</div>
<div id="google_link_proxy">click here to do the same as the link above</div>
<script type="text/javascript">
function fireEvent(element,event) {
if (document.createEvent) {
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
} else {
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
}
$("google_link").observe("click", function(){alert("action 1");});
$("google_link").observe("click", function(){alert("action 2");});
$("google_link").observe("click", function(){alert("action 3");});
$("google_link_proxy").observe("click", function(event){
fireEvent($("google_link"), "click");
});
</script>
</body>
</html>

Categories

Resources