Say I have a string named html that has this in it:
<script>
document.write("Some random stuff here");
</script>
<script src="someremotejsfile"></script>
I want to display this within an iframe window dynamically.
My original solution was to do:
document.open();
document.write(html);
document.close();
But this causes problems in firefox where the spinner keeps spinning as if its loading forever even though the content has already loaded. My next attempt was to:
document.body.innerHTML = html;
This adds the scripts to the body, but that doesn't actually execute them. So lastly I tried:
div = document.createElement("div");
div.innerHTML = html;
document.body.appendChild(div);
But this also doesn't seem to execute the scripts inside the html string.
So my question is, given a string of html, how do I dynamically add it to the page? For instance, it can be an ad tag that has any number of scripts and other html elements in it. I have no control over what that html string has in it. It's a black box to me. I just have to be able to take that long string of html and load it into the window (an iframe in this case).
document.write works:
<iframe id="ifr"></iframe>
<script type="text/javascript">
var scr = decodeURIComponent("%3Ch1%3EHello%20World%3C%2Fh1%3E%3Cscript%3Ealert(%27Some%20random%20stuff%20here%27)%3B%3C%2Fscript%3E");
document.getElementById("ifr").contentWindow.document.write(scr);
document.getElementById("ifr").contentWindow.document.close();
</script>
(Never mind encoded URI string, just needed it to be able to assign code <h1>Hello World</h1><script>alert('Some random stuff here');</script> to a string variable inside of script tags
If you're using jQuery you can use .html to load, and it will fire your script
$(document.body).html( $(document.body).html() + htmlToAdd );
If you're not using jQuery, you can eval manually your script..
function appendHTMLtoBody(html){
var body = document.body;
var scriptsLoaded = [].slice.apply(body.getElementsByTagName("script"),[0]);
for(var i = 0; i < scriptsLoaded.length; i++){
scriptsLoaded[i].setAttribute("data-loaded","true");
}
body.innerHTML += html;
var allScripts = body.getElementsByTagName("script");
for(var i = 0; i < allScripts.length; i++){
if( allScripts[i].getAttribute("data-loaded") !== "true" ){
var script = allScripts[i].innerHTML;
eval(script);
}
}
}
i think will solve your problem.
Related
Essentially, I would like to querySelect a specific text node on the page and replace that node's textContent/data. I have successfully done this via Chrome Console, but when I try to replicate the steps in Tag Manager, I'm seeing nothing happen.
Here is the structure of the relevant portion:
The phone number I need to replace is blacked out. As you can see, I can querySelect this by targeting span.telephone b and then the second childNode.
Here is the node tree for the b element:
The steps I went through in the Console were...
var ogtel = document.body.querySelector("span.telephone b");
var split = ogtel.childNodes[1];
split.textContent;
" (555) 555-5555"
split.replaceData(0,15," new telly baby");
But when I fire a Custom HTML tag in GTM that does the same thing, it shows the tag successfully firing, but that number on the page isn't replace in preview mode.
Here's that Custom HTML tag script. I tried replaceData() and deleteData()...
<script> ( function () {
var ogtel = document.body.querySelector("span.telephone b");
var tel = ogtel.childNodes[1];
var tel2 = tel.deleteData(0,15);
} ) </script>
Any idea what I'm doing wrong? Can GTM even select/edit/delete text data within nodes like this?
ANSWERED!
I wasn't activating the function (like an idiot...)
New GTM code that works..
<script> function changeTel() {
var ogtel = document.body.querySelector("span.telephone b");
var tel = ogtel.childNodes[1];
var tel2 = tel.deleteData(0,15);
}
change = changeTel();
</script>
I have a source HTML page from which I open a virtual (not bound to a file) pop-up by clicking a generic button and by which I push some Html and Javascript code in its innerHTML.
This is a short simplified extract of the Source Page in which I define the Html+Javascript content of the pop-up and open it:
<script language="javascript">
<!--
function fxOpenWindow()
{
// Init objects
var retVal = ''; // contains the Html+Javascript to push in the pop-up innerHTML
var popup = ''; // pop-up to open, not generated by loading a file but only by pushing the "retVal" code inside its innerHTML
// constructing the HTML to push
// defining a function() to show a simple alert : "1"
retVal = retVal + '<script>';
retVal = retVal + ' function fxMessage() { alert(1); }';
retVal = retVal + '</script>';
// defining the html object with which execute the above function
retVal = retVal + '<button onClick="fxMessage();">CLICK ME</button><br>';
// opening the virtual POPUP
popup = window.open('','title');
popup.document.body.innerHTML = retVal;
popup.focus();
}
-->
</script>
<button onClick="fxOpenWindow();">OPEN THE POP-UP WINDOW AND SHOW ITS CONTENT</button>
My problem is that I can't make the fxMessage() function work, it just doesn't do anything at all.
I have used the eval() method too, trying to make the string become live executable code:
// all these methods are a "NO-GO"
retVal = retVal + '<button onClick="fxMessage();">CLICK ME</button><br>';
retVal = retVal + '<button onClick="eval(fxMessage);">CLICK ME</button><br>';
retVal = retVal + '<button onClick="eval(fxMessage());">CLICK ME</button><br>';
// the "direct method" is the only one that works:
retVal = retVal + '<button onClick="alert(1);">CLICK ME</button><br>';
Since the real code is more complex, I have the need to use a function() for simplifying some recursively calls I have to write in order to dynamically build more html objects in the popup itself, so I DO really mind to write all the code inside the onClick event; another thing I'm not willing to do is to have the pop-up load a html file stored on the hard-disk in which I have wrote all the retVal as its html in order to be able to have the fxMessage() function working correctly: the pop-up must be just a virtual page resident only in memory the time is open.
My question is : is there a way to have the fxMessage() to be elevated a as function in the pop-up and make it work out its job?
If you try to insert some <script> by innerHTML after the page load, it won't work (I've explained it yesterday here).
So, move the fxMessage's declaration to your script, like:
<script>
fxOpenWindow(){
//Code here
}
fxMessage(){
//Code here
}
</script>
And call it simply onclick="fxMessage()", no need for eval here.
How cool is this ?
<script language="javascript">
<!--
function fxOpenWindow(id) {
var win = window.open('');
var script = document.createElement('script');
script.text = 'function fxMessage() { alert(1); }';
win.document.head.appendChild(script);
var retVal = '<button onClick="fxMessage();">CLICK ME</button><br>';
win.document.body.innerHTML = retVal;
}
-->
</script>
<button onclick="fxOpenWindow();">OPEN THE POP-UP WINDOW AND SHOW ITS CONTENT</button>
Basically, scripts added with .innerHTML aren't executed. For this you need to create a script node and append it to the child window's HEAD
My specific need is to have the pop-up to be able to create html objects inner-self using a function() (fxMessage() { ...create html objects... }); I have put at work all your answers in different scenarios; there are some differences between the two methods and both of them are working fine and smooth.
I am automating a process wherein I have to login to website and download only the CSV files from the different types of files.
My jQuery code is getting executed in the console but not getting executed after integrating with HTML. Please find the jQuery code below :
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
$(window).on("load", function() {
$('.ibody tr').each(function(a, b) {
var count = 0;
var name = $('.cl', b).text();
if (name.indexOf(".CSV") !== -1 && name.indexOf("TAS") !== -1) {
var d = a - 9;
var hiddenIFrameID = 'hiddenDownloader' + count++;
var iframe = window.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
window.body.appendChild(iframe);
iframe.src = "https://www.shipper-ml.com/viewReports.do?ctrl=reportListForDownload&action=DownloadReport¶m=" + d;
}
});
});
</script>
</head>
<body></body>
</html>
EDIT: I was, indeed, off-base with this. Didn't read your code carefully.
leaving this here for historical purposes...
I might be completely off-base with my assumptions here, and apologize in advance if this is the case. That said, it really looks like you are trying to load a page inside an IFrame and use jQuery outside of the IFrame to read data from inside the IFrame.
Long story short: you cannot use jQuery (or any javascript, or, indeed, ANYTHING AT ALL, if the browsers are working as they should) to manipulate or read content that is inside an IFrame, from outside the IFrame, if that IFrame has a src tag.
You can only manipulate / read from iframe you have built from scratch by yourself. This is by design, and for an important security reason. If you want to use IFrame to display a page, you are severely restricted to only show the page to user as-is.
If my assumption was correct, you need to either:
Get your JavaScript embedded (nicely) into the page you are now loading in your IFrame or
Use an AJAX call to get the contents of that page into your current page's memory context. This will probably mean jumping through some hoops if you really want to use jQuery to find all the elements you want.
...or, you may be able to create an empty IFrame, put the content you got from the AJAX call into that IFrame along with your Javascript, and get it to work. maybe. Not sure about this one.
can you please try with this? replace your window.createElement with document.createElement .
$(document).ready(function() {
$('.ibody tr').each(function(a, b) {
var count = 0;
var name = $('.cl', b).text();
if (name.indexOf(".CSV") !== -1 && name.indexOf("TAS") !== -1) {
var d = a - 9;
var hiddenIFrameID = 'hiddenDownloader' + count++;
var iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.src = "https://www.shipper-ml.com/viewReports.do?ctrl=reportListForDownload&action=DownloadReport¶m=" + d;
}
});
})
Once a first page is loaded nomally in my website, I request all other pages body contents with javascript ajax (ajaxObject).
I simply grab the body innerHTML with ajaxObject (javascript) and replace the actual one:
<script type="text/javascript">
function get(url) {
var myRequest = new ajaxObject(url, uGotAResponse);
myRequest.update('','GET');
}
function uGotAResponse(responseText,responseStatus) {
//Create a temp div to be able to use getElementById on it.
var theTempDiv = document.createElement('div');
//put the grabbed body innerHTML into it.
theTempDiv.innerHTML = responseText;
//my pages are like <body><div id="divcontent">content of pages here</div></body>
//so i get that div containing the innerHTML i really need.
var allDiv = theTempDiv.getElementsByTagName('div');
for (var i=0; i<allDiv.length; i++) {
if (allDiv[i].getAttribute('id') == 'divcontent') {
//i now replace the actual body innerHTML by the one i requested.
document.getElementById('divcontent').innerHTML=allDiv[i].innerHTML;
}
}
}
</script>
On a page, I have youtube objects for embed videos:
<object type="application/x-shockwave-flash" data="http://www.youtube.com/v/1ahKNnolR30" height="315px" width="420px"><param name="movie" value="http://www.youtube.com/v/1ahKNnolR30"></object>
In Firefox everything is fine if I either load the page using the address or with that ajax code.
With IE, it works only if I go to the page using the address.
When I try to use the ajax code the videos appear as the image below.
I tried it with IE tester, all versions give me the same error behaviour.
Does anyone have a fix for this maybe?
As you can see, it looks like the object video is there, but looks like IE is not interpreting it because its loaded by ajax.
I want a Javascript function that returns a correct DOM when input is HTML content.
I have used the follwing function for the same. Here input is HTML content and output is DOM.
function htmltoelement(elementHTML)
{
var temDiv = document.createElement('div');
temDiv.innerHTML = elementHTML;
return temDiv;
}
This function works well for Firefox, but not for IE or Chrome, when the HTML is broken.
I need a suggestion for a function that works fine on all the browsers even when HTML is broken.
With "broken" HTML (which I am assuming is invalid) the way it is interpreted is largely up to the browser and the mode that the browser is in. The DOCTYPE at the top will dictate how the innerHTML property is parsed when it is set. For XHTML, it will give you some odd results because "broken" HTML will mess up your entire page. The function you are using is correct, but it seems you need to check your input for compliance before attempting to create the div.
You can achieve this by writing it out to a hidden iframe:
<iframe id="frame" style="display:none"></iframe>
<script type="text/javascript">
function htmltoelement(elementHTML)
{
var temp = document.getElementById('frame');
// Cross-browser way to get the iframe document
var idoc = (temp.contentWindow || temp.contentDocument);
if (idoc && idoc.document) idoc = idoc.document;
// Put the HTML in the iframe
idoc.write("<html><body>" + elementHTML + "</body></html>");
temDiv = document.createElement('div');
temDiv.innerHTML = idoc.body.innerHTML;
return temDiv;
}
document.body.appendChild(htmltoelement('<b><i>hi</b></i>'));
</script>
The hidden IFRAME seems to be necessary, document.createElement('iframe') didn't work in Opera.