How to print out content of iframe - javascript

I have some response from a server and I have put the response in the content of iframe. Essentially what I need is the item number (see screenshot below), in this case it's 13.
So I tried doing console.log($("#iframe").contents()); which prints out:
I have tried looking through this but cannot find the item number. Is there a easier way to get to the body and obtain the number?

As I understand the question:
There is an <iframe>
The <iframe> has content in a string (i.e. item = 13) that's in a <pre>
But you just want the number from said string (i.e. 13);
The following Demo 1 accomplishes the objectives listed above using plain JavaScript and Demo 2 uses jQuery.
Note: jQuery can be significantly slower than JavaScript which is apparent when dealing with loading iframes. Keep in mind that iframes are the slowest part of your load time. If it doesn't look like you are getting the iframe at all, then run your iframe dependant functions at window.onload.
Also of note: both versions of the function getNumberFromFrame(iframe, target) are reusable. You can use this function on a single element within an iframe and if the target element has any text with numbers✎, it will extract those numbers regardless of the how the string is patterned.
ex. "item = 13" // 13
ex. "August 23, 2017" //23 2017
✎ Edited the regular expression on line 33 to replace non-number matches to a space.
Details are commented in Demo 1 and Demo 2
Demo 1: PLUNKER - Plain JavaScript
Demo 2: PLUNKER - jQuery
Demo 1 - Plain JavaScript: STACK
This is provided as site requires us to post code on the answer, be aware that this copy does not function due to SO security measures. Please review the functioning PLUNKER instead
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<h1>Parent Page</h1>
<iframe id='ifrm1' name='ifrm1' src='child_page.html' width='200' height='200' scrolling='no' frameborder="1"></iframe>
<br> Result:
<output id='display'></output>
<script>
/* Pass an iframe and it's targeted content as
|| selectors (e.g. "TAG", "#ID", ".CLASS", etc)
*/
function getNumberFromFrame(iframe, target) {
// Reference the iframe
var iFrm = document.querySelector(iframe);
/* Reference the iframe's Document Object by
|| using .contentDocument OR
|| .contentWindow.document properties
*/
var iDoc = iFrm.contentDocument || iFrm.contentWindow.document;
/* Now reference the target parameter with
|| the iframe's Document Object.
*/
var iSel = iDoc.querySelector(target);
// Get the target's text
var iTxt = iSel.textContent;
// Then filter out everything but numbers
var iNum = iTxt.replace(/^\D+/g, '');
// Ensure it is a number
iNum = parseFloat(iNum);
// Return number.
return iNum;
}
/* When Window Object is loaded:
|| Call getNumberFromFrame()
*/
window.onload = function() {
var result = getNumberFromFrame('#ifrm1', 'pre');
var view = document.getElementById('display');
view.textContent = result;
};
</script>
</body>
</html>
Demo 2 - jQuery: STACK
This is provided as site requires us to post code on the answer, be aware that this copy does not function due to SO security measures. Please review the functioning PLUNKER instead
<!doctype html>
<html>
<head>
</head>
<body>
<h1>Parent Page</h1>
<iframe id='ifrm1' name='ifrm1' src='child_page.html' width='200' height='200' scrolling='no' frameborder="1"></iframe>
<br> Result:
<output id='display'></output>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script>
/* Pass an iframe and it's targeted content as
|| selectors (e.g. "TAG", "#ID", ".CLASS", etc)
*/
function getNumberFromFrame(iframe, target) {
/* .contents() method "opens" iframe
|| .find() will find the specified target
|| inside of iframe.
*/
var iEle = $(iframe).contents().find(target);
// Get text of target
var iTxt = iEle.text();
//console.log(iTxt);
/* Replace anything that's not a number with
|| nothing.
*/
var iNum = iTxt.replace(/^\D+/g, '');
// Ensure it is a number
//console.log(iNum)
var iRes = parseFloat(iNum);
// Return number.
return iNum;
}
// When Window Object is loaded...
/* Find the element with the id of #display
|| Set output#display text to the return of
|| getNumberFromFrame('#ifrm', 'pre')
*/
window.onload = function() {
$('#display').text(getNumberFromFrame('#ifrm1', 'pre'));
}
</script>
</body>
</html>

Here is a JQuery approach and it's very simple
// this will get you item = 13
var result = $("#iframe").contents().find("pre").html();
// this will get you 13
result = result.split("=")[1];
// 13
alert(result);

You can try this.
console.log($("#iframe")["0"].contentDocument.body.firstElementChild.innerText);
Working evidence

Related

How to select/hide elements inside an object of type "text/html" using javascript [duplicate]

I'm using the object tag to load an html snippet within an html page.
My code looks something along these lines:
<html><object data="/html_template"></object></html>
As expected after the page is loaded some elements are added between the object tags.
I want to get those elements but I can't seem to access them.
I've tried the following
$("object").html() $("object").children() $("object")[0].innerHTML
None of these seem to work. Is there another way to get those elements?
EDIT:
A more detailed example:
consider this
<html><object data="http://www.YouTube.com/v/GGT8ZCTBoBA?fs=1&hl=en_US"></object></html>
If I try to get the html within the object I get an empty string.
http://jsfiddle.net/wwrbJ/1/
As long as you place it on the same domain you can do the following:
HTML
<html>
<object id="t" data="/html_template" type="text/html">
</object>
</html>
JavaScript
var t=document.querySelector("#t");
var htmlDocument= t.contentDocument;
Since the question is slightly unclear about whether it is also about elements, not just about the whole innerHTML: you can show element values that you know or guess with:
console.log(htmlDocument.data);
The innerHTML will provide access to the html which is in between the <object> and </object>. What is asked is how to get the html that was loaded by the object and inside the window/frame that it is producing (it has nothing to do with the code between the open and close tags).
I'm also looking for an answer to this and I'm afraid there is none. If I find one, I'll come back and post it here, but I'm looking (and not alone) for a lot of time now.
No , it's not possible to get access to a cross-origin frame !
Try this:
// wait until object loads
$('object').load(function() {
// find the element needed
page = $('object').contents().find('div');
// alert to check
alert(page.html());
});
I know this is an old question, but here goes ...
I used this on a personal website and eventually implemented it in some work projects, but this is how I hook into an svg's dom. Note that you need to run this after the object tag has loaded (so you can trigger it with an onload function). It may require adaptation for non-svg elements.
function hooksvg(elementID) { //Hook in the contentDocument of the svg so we can fire its internal scripts
var svgdoc, svgwin, returnvalue = false;
var object = (typeof elementID === 'string' ? document.getElementById(elementID) : elementID);
if (object && object.contentDocument) {
svgdoc = object.contentDocument;
}
else {
if (typeof object.getSVGDocument == _f) {
try {
svgdoc = object.getSVGDocument();
} catch (exception) {
//console.log('Neither the HTMLObjectElement nor the GetSVGDocument interface are implemented');
}
}
}
if (svgdoc && svgdoc.defaultView) {
svgwin = svgdoc.defaultView;
}
else if (object.window) {
svgwin = object.window;
}
else {
if (typeof object.getWindow == _f) {
try {
svgwin = object.getWindow();//TODO look at fixing this
}
catch (exception) {
// console.log('The DocumentView interface is not supported\r\n Non-W3C methods of obtaining "window" also failed');
}
}
}
//console.log('svgdoc is ' + svgdoc + ' and svgwin is ' + svgwin);
if (typeof svgwin === _u || typeof svgwin === null) {
returnvalue = null;
} else {
returnvalue = svgwin;
}
return returnvalue;
};
If you wanted to grab the symbol elements from the dom for the svg, your onload function could look like this:
function loadedsvg(){
var svg = hooksvg('mysvgid');
var symbols = svg.document.getElementsByTagName('symbol');
}
You could use the following code to read object data once its loaded completely and is of the same domain:
HTML-
<html>
<div class="main">
<object data="/html_template">
</object>
</div>
</html>
Jquery-
$('.main object').load(function() {
var obj = $('.main object')[0].contentDocument.children;
console.log(obj);
});
Hope this helps!
Here goes a sample piece of code which works. Not sure what the problem is with your code.
<html>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var k = $("object")[0].innerHTML;
alert(k);
$("object")[0].innerHTML = "testing";
});
</script>
<object data="/html_template">hi</object>
</html>
UPDATED
I used this line of Javascript to change the value of a input filed inside an iFrame, taken from How to pick element inside iframe using document.getElementById:
document.getElementById('iframeID').contentWindow.document.getElementById('inputID').value = 'Your Value';
In your case, since you do not have a frame, and since you want to get and not set the value, log it for example with:
console.log(document.getElementById('object').value);
And if you guess or choose an element:
console.log(document.getElementById('object').data);

Pass Variable to a Popup Window using Javascript

I need to pass some text from the current page to a popup window without going for a server hit. The information (herewith represented by 90) is already available in the parent form (it's like a paragraph-long text which is stored in a hidden variable). I just need to display that as a popup.
Here's what I've tried, this works to some extent but doesn't work if I pass text, instead of a number. My second concern is that the solution kinda looks ugly. Any tips? Thank you.
This is SCCE, you can run it straight in your machine.
<html>
<head>
<title>A New Window</title>
<script type="text/javascript">
var newWindow;
var data;
function makeNewWindow(param) {
data = param;
if (!newWindow || newWindow.closed) {
newWindow = window.open("","sub","status,height=200,width=300");
setTimeout("writeToWindow()", 50); /* wait a bit to give time for the window to be created */
} else if (newWindow.focus) {
newWindow.focus( ); /* means window is already open*/
}
}
function writeToWindow() {
var k = data;
alert(data);
var newContent = "<html><head><title>Additional Info</title></head>";
newContent += "<body><h1>Some Additional Info</h1>";
newContent += "<scr"+"ipt type='text/javascript' language='javascript'> var localVar; localVar = "+ k +"; document.write('localVar value: '+localVar);</scr"+"ipt>";
newContent += "</body></html>";
// write HTML to new window document
newWindow.document.write(newContent);
newWindow.document.close( ); // close layout stream
}
</script>
</head>
<body>
<form>
<input type="button" value="Create New Window" onclick="makeNewWindow('90');" />
</form>
</body>
</html>
Actually, I googled and saw some other approach that uses window.opener.document.forms.element, but here, the window has to know in advance what it has to read from the parent. I need to be able to pass it as it will vary:
<textarea rows="15" name="projectcontent" id="projectcontent" cols="87"></textarea>
<b>View Content</b>
<head>
<title>View Project Content</title>
</head>
<body>
<img src="/images/toplogo.jpg"><br/>
<script language="Javascript">
document.write(window.opener.document.forms['yourformname'].elements['projectcontent'].value)
</script>
<img src="/images/bottomlogo.jpg">
</body>
</html>
use window.opener
From Mozilla Developer Network:
When a window is opened from another window, it maintains a reference
to that first window as window.opener. If the current window has no
opener, this method returns NULL.
https://developer.mozilla.org/en-US/docs/Web/API/window.opener
This way you can have on your original window a callback, and you can notify the window it's load and ready, rather than wait a random delay...
you add a function on the original window:
window.popupReady = function (callbackToPopup) {
callbackToPopup(newData);
}
then the popup can tell the parent window it's ready and pass it a callback to update it with data..
and on the popup try something like:
window.dataReady(newData)
{
alert(newData);
}
document.addEventListener("load", function() { window.opener.popupReady (dataReady); }
I didn't test this code, but I would take such a path as this should ensure the popupWindow is ready for you and is along the spirit of JavaScript.
In your onclick attribute you pass '90' to the function, but the function isn't set up to take an argument. So, change the first line of your function like this:
function writeToWindow(data) {
You don't need the global var data; or the local var k = data;, so get rid of them.
And instead of + k + write + data +.
That should do get your data passed.
Use this code, it works perfectly in all browsers .
#desc = parent text area id
#desc_textarea = popup
$("#desc_textarea").val(window.opener.$("#desc").val())

Duplicate iframe: Copy head and body from 1 iframe to another

Simple question which I can't seem to find an answer of:
I have two iframes on a page and I'd like to copy the content of the first one to the second.
But I can't do it by just copying the url of the first iframe to the second since the containing page is a dynamic one.
This code does do it, but a lot of the page-formatting seems to get lost. And I don't know if it's cross-browser either.
iframe2.contentWindow.document.write(iframe1.contentWindow.document.body.innerHTML);
Can this be done?
Native JavaScript Solution As Asked For:
First, to make things simple I created 2 object literals:
var iframe1 = {
doc : undefined,
head : undefined,
body : undefined
};
var iframe2 = {
doc : undefined,
head : undefined,
body : undefined
};
Next, I put everything under iframe1's window.onload handler to make sure it was loaded fully:
document.getElementById("iframe1").contentWindow.onload = function() {
Then I assigned all of the object literal properties:
iframe1.doc = document.getElementById("iframe1").contentWindow.document;
iframe1.head = iframe1.doc.getElementsByTagName("head")[0];
iframe1.body = iframe1.doc.getElementsByTagName("body")[0];
iframe2.doc = document.getElementById("iframe2").contentWindow.document;
iframe2.head = iframe2.doc.getElementsByTagName("head")[0];
iframe2.body = iframe2.doc.getElementsByTagName("body")[0];
Next, I needed to create a couple functions removeNodes() and appendNodes() so that I could re-factor some code that is used for both <head> and <body> routines.
function removeNodes(node) {
while (node.firstChild) {
console.log("removing: " + node.firstChild.nodeName);
node.removeChild(node.firstChild);
}
}
and:
function appendNodes(iframe1Node, iframe2Node) {
var child = iframe1Node.firstChild;
while (child) {
if (child.nodeType === Node.ELEMENT_NODE) {
console.log("appending: " + child.nodeName);
if (child.nodeName === "SCRIPT") {
// We need to create the script element the old-fashioned way
// and append it to the DOM for IE to recognize it.
var script = iframe2.doc.createElement("script");
script.type = child.type;
script.src = child.src;
iframe2Node.appendChild(script);
} else {
// Otherwise, we append it the regular way. Note that we are
// using importNode() here. This is the proper way to create
// a copy of a node from an external document that can be
// inserted into the current document. For more, visit MDN:
// https://developer.mozilla.org/en/DOM/document.importNode
iframe2Node.appendChild(iframe2.doc.importNode(child, true));
}
}
child = child.nextSibling;
}
With those functions created, now all we have to do is make our calls:
console.log("begin removing <head> nodes of iframe2");
removeNodes(iframe2.head);
console.log("begin removing <body> nodes of iframe2");
removeNodes(iframe2.body);
console.log("begin appending <head> nodes of iframe1 to iframe2");
appendNodes(iframe1.head, iframe2.head);
console.log("begin appending <body> nodes of iframe1 to iframe2");
appendNodes(iframe1.body, iframe2.body);
... and finally, we close off the window.onload function:
};

Jquery or Javascript that display content based on the date HELP

Jquery or JavaScript that displays content based on specifics date period
so we have like 3 dates
12/3/2010
12/11/2010
12/20/2010
and
Div Contents
Content 1 should be displaying from 12/3 to 12/11
Content 2 should be display from 12/11 to 12/20
and Content 3 should be displaying from 12/20 there after
First, like others said this whole thing is bad idea as you're depending on the client machine date/time and correct approach would be doing that in server side.
Anyway, guess you have your reasons so here is jQuery solution.
Have such HTML:
<div class="DateDiv"><span class="DateRange">1/1/2010 to 1/1/2011</span>I'll be visible during 2010</div>
<div class="DateDiv"><span class="DateRange">1/1/2011 to 1/1/2012</span>I'll be visible during 2011</div>
<div class="DateDiv"><span class="DateRange">1/1/2012 to 1/1/2013</span>I'll be visible during 2012</div>
Put the date range inside a span inside each div with the class "DateRange".
Next, have such CSS to have them initially hidden:
<style type="text/css">
.DateRange, .DateDiv { display: none; }
</style>
And finally, this script: (jQuery)
<script type="text/JavaScript">
$(function() {
$(".DateDiv").each(function(index) {
var sRange = $(this).find(".DateRange").html();
var arrTemp = sRange.split(" to ");
var dtFrom = new Date(arrTemp[0]);
var dtTo = new Date(arrTemp[1]);
var dtNow = new Date();
if (dtNow >= dtFrom && dtNow <= dtTo)
$(this).show();
});
});
</script>
Test case is available here feel free to mess around with it: http://jsfiddle.net/2BHLd/
I've created a simple code. It should work as you want (if I have understood you well).
I know, there's no doctype in my HTML and there are some missing tags. The HTML I've provided is just a kind of template.
<html>
<head>
<script type="text/javascript">
var date=new Date();
var year=date.getFullYear();
var month=date.getMonth();
var day=date.getDate(); // fixed
function SetDivContent() {
var div=document.getElementById('date_dependent');
if (year==2010 && month==11) { // fixed (the JavaScript months order is 0-11, not 1-12)
if (day>=3 && day<11) { // the following content will be displayed 12/03/2010, 12/04/2010, [...], 12/09/2010, 12/10/2010
div.innerHTML='content 1';
}
else if (day==11 || day==12) { // this one will be displayed 12/11/2010 and 12/12/2010
div.innerHTML='content 2';
}
else if (day>12) { // this one - 12/13/2010 and later, until the end of December
div.innerHTML='content 3';
}
}
else if (year==2011 && month>=0) div.innerHTML='content 3'; // OPTIONAL - just to ensure that content 3 is displayed even after December.
}
</script>
</head>
<body onload="SetDivContent()">
<div id="date_dependent"></div>
</body>
</html>
Please note that if you want to hide some data from users if the specified date hasn't come yet, you should better use something server-side for security reasons. Otherwise, any user may just read the page's source. Also remember that the following code is executed when the body is loaded, i.e. each time a user refreshes the page.
EDIT: Warning: there were two bad lines (I've made a mistake before). Anyway, I've fixed them. The current code works, I've tested it.

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