How can I write a form into an empty iframe? - javascript

Based on an answer to this question, I am trying to append elements directly into an empty iframe with no src attribute.
However, it seems appendChild on the iframe fails silently.
In the code below, doc.write("Hello World"); works correctly, but myform2.appendChild(input2); does not change the innerHTML of the frame, and also does not throw an error.
<html>
<body>
<iframe name = "myframe" id = "myiframe">
</iframe>
<script>
var myform2 = document.createElement("form");
var input2 = document.createElement("input");
input2.name = "quantity";
input2.value = "10";
myform2.appendChild(input2);
</script>
<script>
var getFrame = document.getElementById('myiframe');
var doc = getFrame.contentDocument || getFrame.contentWindow.document;
// doc.write("Hello World");
doc.body.appendChild(myform2); // Does not work.
</script>
</body>
</html>
What is the correct way to add a form into the iframe using raw Javascript?
I am looking for non-jQuery solutions, because I want to understand how the magic works, rather than just letting jQuery perform the magic.

I think it's a matter of timing. Try to run your script after document has been loaded:
<body onload="loadMe();">
<iframe name = "myframe" id = "myiframe">
</iframe>
<script>
function loadMe() {
var myform2 = document.createElement("form");
var input2 = document.createElement("input");
input2.name = "quantity";
input2.value = "10";
myform2.appendChild(input2);
var getFrame = document.getElementById('myiframe');
var doc = getFrame.contentDocument || getFrame.contentWindow.document;
doc.body.appendChild(myform2); // Does not work.
}
</script>
</body>
http://jsfiddle.net/GR7LJ/2/

This should work in IE 10+, Firefox, and Chrome (and maybe older versions of IE). Basically, I am just creating an iframe, selecting where to place it, placing it inside of it, then opening the new iframe's contentWindow.document and writing pure HTML/CSS/Javascript into it.
var newIframe = document.createElement("iframe");
var container = document.getElementById("container");
container.appendChild(newIframe);
var iframeContent = newIframe.contentWindow.document;
iframeContent.open();
iframeContent.write("<input type='text' />");
iframeContent.close();
newIframe.setAttribute("sandbox", "allow-scripts"); // optional sandboxing
I've run into issues before where attempting to append DOM elements does not always work so in this scenario I just pass them in as a string. I also "close" off the iframe by sandboxing it (security preference) after appending the HTML I need.
Hope this solution helps you.
Here's a fiddle: http://jsfiddle.net/fv2DB/

Related

access a element within hidden div element using javascript

I am having an iframe inside a div element which is hidden/display none, I want to get the href attribute of a tag using javascript my code is
HTML
<div id="questions" style="display: none;">
<iframe id="article_frame" width="100%" height="100%">
Click here
</iframe>
</div>
JS
window.onload = function() {
alert("Hello " + window.document.getElementById("article_frame"));
}
But I am getting alert as "Hello null" any solution
Thanks
Thanks All,
I have got the answer with javascript it just simple code
var anchor = document.getElementById('en_article_link').firstChild;
var newLink = anchor.getAttribute("href")+"sid="+sidvalue;
anchor.setAttribute("href", newLink);
Ok i feel this may be a slight overkill but it will get you what you require (the href value of the anchor tag inside the iframe) :
window.onload = function() {
var frame = window.document.getElementById("article_frame");
var myString = frame.childNodes[0].textContent
, parser = new DOMParser()
, doc = parser.parseFromString(myString, "text/xml");
var hrefValue = doc.firstChild.getAttribute('href');
alert("Hello " + hrefValue);
}
I guess it depends on your requirements but another way would be to create a string and then using functions: substring and indexof you could get your value. Here is how you would get the string:
window.onload = function() {
var frame = window.document.getElementById("article_frame");
var elementString = frame.childNodes[0].textContent;
//then perform your functions on the string here
}
Note that you can only access the contents of an iframe that contains a page on the same domain due to the Same-Origin Policy (Wikipedia).
I recommend using jQuery for this. The tricks here are:
Wait for the iframe to finish loading $("#article_frame").ready()
Access the iframe's document $("#article_frame").contents()
From there you're just handling the task at hand:
$("#article_frame").ready(function() {
alert("Hello " + $("#article_frame").contents().find("#en_link").href);
});

Unable to parse onClick text using DOM

All that I have read says to use the element.onclick property, but that doesn't seem to be working in my situation. I'm trying to parse the number: 629216818 and set it to a varialbe: fbid. This is a Greasemonkey script, so the HTML can't be edited directly. I'm no pro, so I may be just doing something stupid, but here is my HTML and Javascript:
<div id="petRightContainer">
<a title = "Pet trainer bonus: Your companion will level 5% faster." href="setup.php?type=companion&gtRandom=8167343321487308">
<div class="petRight" style="background-image:url(/fb/res/gui4/companion/cu_sith.jpg)"></div>
</a>
<div class="petRightLevel">
Dog
</div>
etc.
<script type="text/javascript">
fbid = 0;
fbidRegex = /\d{3,}(?=&fromWall=1)/;
if ( document.getElementsByClassName("petRightLevel")[0]){
element = document.getElementsByClassName("petRightLevel")[0].firstChild;
codeStore = element.onclick;
fbid = fbidRegex.exec(codeStore);
document.write("it is working ");
}
document.write(fbid);
</script>
The problem is in this line:
element = document.getElementsByClassName("petRightLevel")[0].firstChild;
If you are using Firefox and other browsers which support document.getElementsByClassName and in your HTML, there are spaces between <div class="petRightLevel"> and
<a href="#" onClick= ...>
, the firstChild is actually a text node not the link. All you need to do is remove the spaces and/or line break in between the two elements.
If you are using IE, the problem is still at the same line of the javascript because IE doesn't support document.getElementsByClassName up until version 8.
Update: The following javascript code work for all the browsers I tested without touching HTML:
<script type="text/javascript">
fbid = 0;
fbidRegex = /\d{3,}(?=&fromWall=1)/;
var divs = document.getElementsByTagName("div");
var link = null;
for (var i=0;i<divs.length;i++)
{
if(divs[i].getAttribute("class") ==="petRightLevel")
{
link = divs[i].getElementsByTagName("a")[0];
break;
}
}
if (link){
codeStore = link.onclick;
fbid = fbidRegex.exec(codeStore);
document.write("it is working ");
}
document.write(fbid);
</script>
If you only need to get the anchors, it would be much simpler than this.
I think this might work for you.
<script type="text/javascript">
fbid = 0;
fbidRegex = /\d{3,}(?=&fromWall=1)/;
if(document.getElementsByClassName("petRightLevel")[0]){
element = document.getElementsByClassName("petRightLevel")[0].firstChild;
// callback function to execute when the element onclick event occurs.
codeStore = element.onclick = function(){
fbid = fbidRegex.exec(codeStore);
document.write("it is working ");
document.write(fbid);
}
}
</script>

How to open a new window and insert html into it using jQuery?

I am trying to open a new window from javascript but nothing is being inserted into the html:
var callScriptText = $('#callScriptText').html();
var url = '/Action/CallScript/?callScript=';
// Open the current call script in a new window
var openWindow = window.open(url, 'callScriptPopup', 'width = 500, height = 500');
$(openWindow).html(callScriptText);
Does anyone know why?
Here's an example to open a new window with content using jQuery
<script>
function nWin() {
var w = window.open();
var html = $("#toNewWindow").html();
$(w.document.body).html(html);
}
$(function() {
$("a#print").click(nWin);
});​
</script>
<div id="toNewWindow">
<p>Your content here</p>
</div>
Open​
EDIT:
For those who say that this code doesn't work, here's a jsfiddle to try it http://jsfiddle.net/8dXvt/
Try this:
var x=window.open();
x.document.open();
x.document.write('content');
x.document.close();
I find it works in Chrome and IE.
Building upon #Emre's answer.
With javascript, you can chain, so I just modified the code to:
var x=window.open();
x.document.open().write('content');
x.close();
Also, to force it to a new window (not a new tab), give the first line dimensions. But it has to be the third argument. So change the first line to:
var x=window.open('','','width=600, height=600');
try:
var x = window.open('', '', 'location=no,toolbar=0');
x.document.body.innerHTML = 'content';
var codeContents = $("#contentsfornewWindow").html()
var win = window.open('', 'title', 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=1000,height=1000,left=200,top=70');
win.document.body.innerHTML = codeContents;
VS:
win.document.write(codeContents);
I have notice if there are iframes like youtubes videos , win.document.write loads the iframes where as document.body.innerHTML does not!

Replace the surround of an html element with another document

I have an html page with (among other things) a Unity3D window. I would like to replace everything on the page without causing the Unity window to reload. I have tried the following jquery-tastic
function replaceSurround(keepElem, newElem)
{
keepElem.siblings().remove();
keepElem.prepend(newElem.prevAll());
keepElem.append(newElem.nextAll());
var keepParent = keepElem.parent();
var newParent = newElem.parent();
if (keepParent && newParent)
{
replaceSurround(keepParent, newParent);
}
}
where keepElem is an element in the original document and newElem is the corresponding element in the new document, but it did not work very well.
Here is what I've got, it seems to work...
jQuery.fn.rewrap = function(newWrap){
var $parent = jQuery(this).parent();
var $clone = jQuery(this).siblings().clone()
var $newParent = $clone.wrap(newWrap).parent().clone();
$parent.replaceWith($newParent);
}
$('#header').rewrap('<div class="container" style="background-color:blue;" />');
I tested it on the Stackoverflow website. One small problem though, it seems to be refiring some onX events...?
[edit]
On second thought, that is not what you meant at all....
Can't you just do something like:
$('#result').load('ajax/test.html #result');
?

How do you execute a dynamically loaded JavaScript block?

I'm working on a web page where I'm making an AJAX call that returns a chunk of HTML like:
<div>
<!-- some html -->
<script type="text/javascript">
/** some javascript */
</script>
</div>
I'm inserting the whole thing into the DOM, but the JavaScript isn't being run. Is there a way to run it?
Some details: I can't control what's in the script block (so I can't change it to a function that could be called), I just need the whole block to be executed. I can't call eval on the response because the JavaScript is within a larger block of HTML. I could do some kind of regex to separate out the JavaScript and then call eval on it, but that's pretty yucky. Anyone know a better way?
Script added by setting the innerHTML property of an element doesn't get executed. Try creating a new div, setting its innerHTML, then adding this new div to the DOM. For example:
<html>
<head>
<script type='text/javascript'>
function addScript()
{
var str = "<script>alert('i am here');<\/script>";
var newdiv = document.createElement('div');
newdiv.innerHTML = str;
document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>
You don't have to use regex if you are using the response to fill a div or something. You can use getElementsByTagName.
div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
eval(scripts[ix].text);
}
While the accepted answer from #Ed. does not work on current versions of Firefox, Google Chrome or Safari browsers I managed to adept his example in order to invoke dynamically added scripts.
The necessary changes are only in the way scripts are added to DOM. Instead of adding it as innerHTML the trick was to create a new script element and add the actual script content as innerHTML to the created element and then append the script element to the actual target.
<html>
<head>
<script type='text/javascript'>
function addScript()
{
var newdiv = document.createElement('div');
var p = document.createElement('p');
p.innerHTML = "Dynamically added text";
newdiv.appendChild(p);
var script = document.createElement('script');
script.innerHTML = "alert('i am here');";
newdiv.appendChild(script);
document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>
This works for me on Firefox 42, Google Chrome 48 and Safari 9.0.3
An alternative is to not just dump the return from the Ajax call into the DOM using InnerHTML.
You can insert each node dynamically, and then the script will run.
Otherwise, the browser just assumes you are inserting a text node, and ignores the scripts.
Using Eval is rather evil, because it requires another instance of the Javascript VM to be fired up and JIT the passed string.
The best method would probably be to identify and eval the contents of the script block directly via the DOM.
I would be careful though.. if you are implementing this to overcome a limitation of some off site call you are opening up a security hole.
Whatever you implement could be exploited for XSS.
You can use one of the popular Ajax libraries that do this for you natively. I like Prototype. You can just add evalScripts:true as part of your Ajax call and it happens automagically.
For those who like to live dangerously:
// This is the HTML with script element(s) we want to inject
var newHtml = '<b>After!</b>\r\n<' +
'script>\r\nchangeColorEverySecond();\r\n</' +
'script>';
// Here, we separate the script tags from the non-script HTML
var parts = separateScriptElementsFromHtml(newHtml);
function separateScriptElementsFromHtml(fullHtmlString) {
var inner = [], outer = [], m;
while (m = /<script>([^<]*)<\/script>/gi.exec(fullHtmlString)) {
outer.push(fullHtmlString.substr(0, m.index));
inner.push(m[1]);
fullHtmlString = fullHtmlString.substr(m.index + m[0].length);
}
outer.push(fullHtmlString);
return {
html: outer.join('\r\n'),
js: inner.join('\r\n')
};
}
// In 2 seconds, inject the new HTML, and run the JS
setTimeout(function(){
document.getElementsByTagName('P')[0].innerHTML = parts.html;
eval(parts.js);
}, 2000);
// This is the function inside the script tag
function changeColorEverySecond() {
document.getElementsByTagName('p')[0].style.color = getRandomColor();
setTimeout(changeColorEverySecond, 1000);
}
// Here is a fun fun function copied from:
// https://stackoverflow.com/a/1484514/2413712
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
<p>Before</p>

Categories