IE unknown runtime error while setting innerhtml - javascript

I am trying to set style inside head tag dynamically inside a iframe so as to set the class
on body of the iframe while loading of the iframe itself, say I want to apply the ze_edit
class on the body of iframe like this ::---
<head>
<style type="text/css">
.ze_edit{font-family:Verdana,arial,Helvetica,sans-serif;font-size:12px;}
</style>
</head>
<body class = "ze_edit">
</body>
Below is the full code of the sample test file.
<html>
<head>
<script>
test = function()
{
var _style,
_iframe,
_doc,
_head,
ff,
fs;
ff = "georgia,times new roman,times,serif";
fs = "30pt"
_doc = document;
_iframe = _doc.getElementsByTagName("iframe")[0];
_iframe.contentWindow.document.designMode="on";
_style = _doc.createElement("style");
_style.type = "text/css";
_style.innerHTML = ".eclass{font-family:"+ff+";font-size:"+fs+"}";
_head = _iframe.contentWindow.document.getElementsByTagName("head")[0];
_head.appendChild(_style);
_iframe.contentWindow.document.body.className = "eclass";
}
</script>
</head>
<body>
This is a just a test
<iframe onload ="test()">
satyam
</iframe>
</body>
</html>
But this script throws error "Unknown runtime error" at this line
"*_style.innerHTML = ".eclass{font-family:"+ff+";font-size:"+fs+"}*";
" in IE .
Any workaround solution for this..

This could be some IE bug/feautre. Do it like in this post:
How to change/remove CSS classes definitions at runtime?

Related

Clean the cache of iframe

I have an erroneous html+javascript. It returns a Uncaught ReferenceError: number is not defined, which is expected:
<!DOCTYPE html>
<meta name="robots" content="noindex">
<html>
<body>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = number();
</script>
<script id="jsbin-javascript">
function number() {
return 1;
}
</script>
</body>
</html>
However, if I run the code as a string by iframe twice (plnkr), the second run oddly returns a result. It is because the number function is cached somewhere by the first run, which is not what I want.
<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script>
</head>
<body>
<iframe></iframe>
<script>
var iframe = document.querySelector('iframe');
var iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
var iframe = document.querySelector('iframe');
var iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
</script>
</body>
</html>
So does anyone know how to clean the cache, such that each run of iframe is completely a new one?
Edit 1 Following the answer of #LeonidVasilyev, I have added in html:
<section id="output">
<iframe></iframe>
</section>
And in JavaScript of my playground:
this.render = function (code) {
var source = prepareSource(code);
var placeholder = document.getElementById("output");
while (placeholder.firstChild) {
placeholder.removeChild(placeholder.firstChild);
}
var iframe = document.createElement("iframe");
placeholder.appendChild(iframe);
var iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
}
What is odd is that, every time I reload/refresh the page, the paper icon in the Chrome tab and the reload round icon each flash twice. It is because of placeholder.appendChild(iframe), because if i remove this line, it flashes once.
Does anyone know how to avoid this icon twice-flashing?
That is a Chrome bug. In your case document.open() must create new global object. Excerpt from description of document.open() algorithm in HTML specification:
Call the JavaScript InitializeHostDefinedRealm() abstract operation with the following customizations:
For the global object, create a new Window object window.
For the global this value, use the current browsing context's
associated WindowProxy.
Let realm execution context be the created JavaScript execution
context.
Firefox 51 and Internet Explorer 11 properly create new Window object.
As a workaround you can create new iframe node on each iteration:
<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script>
</head>
<body>
<div id="placeholder"></div>
<script>
var placeholder = document.getElementById("placeholder");
var iframe = null;
iframe = document.createElement("iframe");
placeholder.appendChild(iframe);
var iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
iframe = document.createElement("iframe");
placeholder.appendChild(iframe);
var iframe_doc = iframe.contentDocument;
iframe_doc.open();
iframe_doc.write(source);
iframe_doc.close();
</script>
</body>
</html>

How to inject HTML, CSS and jQuery in realtime to iframe

I am trying to build a HTML, CSS and jQuery (not just JavaScript) editor, and show the rendered content in an iFrame. Although adding HTML, CSS part is easy, I am unable to execute the JavaScript part.
var html = ""; // HTML code
var content = $("#preview").contents().find("body"); // iframe id is 'preview'
content.html(html);
var cssLink = "<style>" + csVal + "</style>"; // cssVal contains css code
var head = $("#preview").contents().find("head");
head.append(cssLink);
var js ='<script>'+jsEditor()+'<\/script>' ;
// following part is not working
var content = $('#preview').contents();
$content.find('head').append('<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>' );
$content.find('body').append(js );
I am able to execute to core JavaScript using window.eval(), however it is not working for any JS library included, e.g. jQuery etc.
I think your only problem here is your variable naming:
var content = $('#preview').contents();
$content.find('head').append('<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>' );
$content.find('body').append(js );
should be ($content ==> content)
var content = $('#preview').contents();
content.find('head').append('<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>' );
content.find('body').append(js );
I modified your script slightly but only to provide some pre-canned values for html, csVal and a result from jsEditor().
This worked for me in Chrome, Safari & Firefox running off a server on localhost:
HTML:
<html>
<head>
</head>
<body>
<div>Look at your new iFrame</div>
<iframe id="preview"></iframe>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</body>
</html>
Code (also in the html body):
$(document).ready(function() {
var html = "<div>Hello from iframe</div>"; // HTML code
var content = $("#preview").contents().find("body"); // iframe id is 'preview'
content.html(html);
var csVal = "div { color: red; font-size: 40px;}";
var cssLink = "<style>" + csVal + "</style>"; // cssVal contains css code
var head = $("#preview").contents().find("head");
head.append(cssLink);
var jsCode = "alert('you are in the iframe')";
var js ='<script>'+jsCode+'<\/script>' ;
// following part is not working
var content = $('#preview').contents();
content.find('head').append('<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>' );
content.find('body').append(js );
});
Resulting source in the iFrame:
<html>
<head>
<style>
div {
color: red;
font-size: 40px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</head>
<body>
<div>Hello from iframe</div>
<script>
alert('you are in the iframe')
</script>
</body>
</html>

Scripts do not execute when changing the content of an iframe with innerHTML

I would like to load the content of an iframe with JavaScript. I don't want to change the src but directly the content with:
document.getElementById('frame').contentDocument.body.innerHTML = data;
It works but the JavaScript in data is not executed. Is it a security protection or I forgot something?
It looks like the problem is not the iframe, but the fact that scripts are not executed when inserted into the DOM text with innerHTML.
You may want to check the following Stack Overflow post for a couple of solutions:
Can scripts be inserted with innerHTML?
Use this for getting the document crossbrowser
//returns iframe document
function getIFrameDocument(iframe) {
var doc;
if (iframe.contentDocument) {//FF-Chrome
doc = iframe.contentDocument;
} else if (iframe.contentWindow) {
doc = iframe.contentWindow.document;
} else if (iframe.document) {//IE8
doc = iframe.document;
} else {
doc = window.frames[iframe.id].document;
}
return doc;
}
Try this
in a page index.html write:
<script type="text/javascript">
function init()
{
var s = document.createElement("script");
s.innerHTML="alert('ops');"
document.getElementById("frame").contentDocument.getElementsByTagName("body")[0].appendChild(s);
}
window.onload = init;
</script>
...
<body>
<form id="form1">
<div>
<iframe id="frame" src="test.html"></iframe>
</div>
</form>
</body>
Then simply write test.html like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
</body>
</html>
and load from a web server index.html and the code works!!
Having something like the following would work.
<iframe id = "testframe" onload = populateIframe(this.id);></iframe>
// The following function should be inside a script tag
function populateIframe(id) {
var text = "This is a Test"
var iframe = getObj(id);
var doc;
if(iframe.contentDocument) {
doc = iframe.contentDocument;
} else {
doc = iframe.contentWindow.document;
}
doc.body.innerHTML = text;
}

call function on iframe mouse move

I have a function that i need to call on iframe mousemove(). But i didnt found anything like we have in body tag
We have <body mousemove="Function()"> Do we have anything like this for iframe??
The iframe contains its own document, own body element etc.
Try something like this:
var frame = document.getElementById("yourIframeId");
// IE is special
var frameDoc = frame.contentDocument || frame.contentWindow.document;
var frameBody = frameDoc.getElementsByTagName("body")[0];
var testingOneTwo = function() {
console.log("Hello, is this thing on?");
};
frameBody.onmouseover = testingOneTwo;
Did you mean onMouseOver or onFocus?
e.g.
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<script language="javascript">
<!--
function SayHello()
{
alert("Hi from IFrame");
}
//-->
</script>
</HEAD>
<BODY>
<iframe id="myiFrame" onMouseOver="SayHello()"/>
<iframe id="myiFrame" onFocus="SayHello()"/>
</BODY>
</HTML>

how can you determine location of <script> tag from inside said tag?

I am trying to figure out the location of the script tag the current javascript is running in. What is really going on is that I need to determine from inside a src'd, dynamically inserted javascript file where it is located in the DOM. These are dynamically generated tags; code snippet:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>where am i?</title>
<script type="text/javascript" charset="utf-8">
function byId(id) {
return document.getElementById(id);
}
function create_script(el, code) {
var script = document.createElement("script");
script.type = "text/javascript";
script.text = code;
el.appendChild(script);
}
</script>
</head>
<body>
<div id="find_me_please"></div>
<script>
create_script(byId("find_me_please"), "alert('where is this code located?');");
</script>
</body>
</html>
You could give the script an id tag, like this dude does...
You can use document.write to create a dummy DOM object and use parentNode to escape out. For example:
<script>
(function(r) {
document.write('<span id="'+r+'"></span>');
window.setTimeout(function() {
var here_i_am = document.getElementById(r).parentNode;
... continue processing here ...
});
})('id_' + (Math.random()+'').replace('.','_'));
</script>
This assumes you don't actually have control of the <script> tag itself, such as when it's inside a <script src="where_am_i.js"></script> - if you do have control of the <script> tag, simply put an ID on it, as in:
<script id="here_i_am">...</script>
If you are just running this on page load, this works
<script>
var allScripts = document.getElementsByTagName('script');
var thisScript = allScripts[allScripts.length];
alert(thisScript);
</script>

Categories