Setting iframe's window.external members through javascript - javascript

I have some code running in an html page that is calling a function that exists on window.external. The code works:
SomeCode.js (lives in somePage.html):
window.external['someFunction']();
However, for testing purposes, I need to embed that html page within an iframe in a separate test page. The test page code
TestPage.html:
window.frames[0].external['someFunction'] = function() { console.log('success'!); }; // Doesn't work
window.frames[0].src = "http://somePage.com/somePage.html";
window.frames[0].external['someFunction'] = function() { console.log('success'!); }; // window.external['someFunction'] is still null from the perspective of the code in SomeCode.js. oesn't work
I've tried a number of ways of setting the function both before and after setting the src. What's bizarre is that if I print window.frames[0].external to the console, window.frames[0].external DOES appear to have 'someFunction' set. It's almost like window.frames[0].external is a different object than the one used inside of the javascript in the iframe.
Any ideas would be greatly appreciated.
Thanks,
Cicada

If the function someFuction has some paramaters, you must to declare its in the precedent line. If you do not this, it doesn't work.
should be:
window.frames[0].external['someFunction'] = function(params) {console.log('success!');};

Related

Getting Values out of Websocket Functions

I am working on a project which needs to get communication from C++ code to JavaScript on a webserver. Currently, I have data sending properly and it's being received but the issue is that I cant use the data outside of the inner(onmessage) function. This still works fine to overwrite elements of the webpage, but the charts I'm trying to build cant get the live data. If I put the code for the chart inside the inner function the entire program freezes and I can't get the variable out of the function for me to use it in the parent either. Right now, I just want to get the data out of the inner function so I can use it. So, is there any way for me to pull that data out of the inner function and use it in the parent function?
Here is my code:
{
var x;
var ws = new WebSocket('ws://localhost:10011/');
ws.onmessage = function(event)
{
x = event.data;
var testing = document.getElementById('InnerFunctionOutput');
testing.innerHTML = "Run Time: " + x;
}
var testing = document.getElementById('ParentFunctionOutput');
testing.innerHTML = "Run Time: " + x;
}
When I run this code the output from the inner function is the constant stream of data and the output from the parent is a constant 1. If anyone could help me find a solution, it would be greatly appreciated.
One alternative solution is to put the functions for the charts inside the websocket function. That way, I wouldn't have to get data out of the function. however, this solution has its own set of problems. I will put a link below to a thread where I ask about this alternate solution if you are interested in that part.
Plotly and Websockets
Any help would be greatly appreciated.
Thanks,
Luke
I found a solution to the problem. To get the data out of the websocket function I overwrote a text element on the page and simply made that element invisible. After that, just read the text element in order to get it into the rest of the code. However, there could be a better way of doing this so please let me knw if there is.
Also, there is one issue I ran into with this solution. When I originally tried this with normal formatting document.getElementById('some id').innerHTML = some data; it didn't work. But when with adding "window" to the beginning window.document.getElementById('some id').innerHTML = some data; it just worked.

HTML/JS: Calling a value from an object constructed onload in <body>

I'm currently making a website, and I'm creating a "manager" object onload in the body:
body id="real-world" onload="createARSim('ar-world','real-world','phone');">
createARSim(...) returns an object with a bunch of things in it that are useful. One such thing is a
var pageIndex
which monitors the current page.
I want to display the page number somewhere in the web page. Currently I am putting the code inline, like this:
<script> onload.pageIndex.toString(); </script>
the issue is that it throws this error:
TypeError: onload.pageIndex is undefined
And I'm not sure what to do about it. The js code in the constructor runs fine, but I can't find any way to access the returned object once I've finished running the constructor.
EDIT:
ok, I think I might know why it's not working. First, I need to use Document.onload to call the onload object that I've returned. However the bigger issue is how onload works -- I can't call an element of onload inline, because the constructor isn't actually executed yet when I run the inline javascript code (it calls after everything has loaded...).
So I can't just put it inline. I'll have to do some clever editing from the javascript to the div I'm putting it in directly, I think.
You can do the following to solve this problem
window.onload = function() {
var pageIndex = createARSim('ar-world','real-world','phone').pageIndex;
var textNode = document.createElement('text');
textNode.textContent = pageIndex;
document.body.appendChild(textNode);
}
This appends pageIndex to body.

JSP Parsing url and matching key words

Here is my question, I am using jsp script, trying to match a key word in requesting url and do something:
<script>
$url = '${pageContext.request.requestURL}';
if("${fn:contains(url, 'key')}" == true){
...
}
....
But this doest work... I am not sure where the problem is but I want it to be like when url contains this string, go in to the if condition.
Thank you
You are mixing JSP/EL and JavaScript as if they run in sync. This is wrong. JSP/EL runs in webserver and produces HTML code which get executed in webbrowser. JavaScript (JS) is part of the generated HTML code and runs in webbrowser only.
You need to do it either fully in JSP/EL, or fully in JavaScript. You can use JSP/EL to dynamically generate JS code which get later executed when the page arrives at browser. Rightclick page in browser, do View Source to see what JSP/EL has generated. You should not see any line of JSP/EL. You should only see HTML/JS code. It's exactly that JS code which get executed then.
You're using a JSP EL function to test a JS variable which isn't in the variable scope at that moment at all. This is not going to work. It can only test JSP/EL variables.
Here's how you could do it in pure JS:
<script>
var url = window.location.href;
if (url.indexOf('key') > -1) {
// ...
}
</script>
If you really insist in doing it using JSP/EL, you could do as follows:
<script>
var url = '${pageContext.request.requestURI}';
if (${fn:contains(pageContext.request.requestURI, 'key')}) {
// ...
}
</script>
This will then generate the following JS code (rightclick page in browser and View Source to see it):
<script>
var url = '/some/uri';
if (true) {
// ...
}
</script>
But this makes no sense. Whatever functional requirement you need to solve, you need to think twice about the right approach. Feel free to ask a new question about solving the concrete functional requirement the proper way.
If you want a parameter that the page was requested with, use ${param.paramName}. So in this case ${param.key}. See implicit objects in the docs. And if you just want to check it has a value try ${not empty param.key}.

How to code firefox extension which run javascript code in the page's context like firebug does

I know that for safety reasons that this is not easy to achieve, however there would be a way to do so as firebug does...
Please help, would like to invoke some script in the page's context to achieve some effect...
Basically, I would like to achieve two functionality:
1. add jQuery to any web page automatically if not already exist.
2. when open certain address, call a method of that page to auto notify the server. (an ajax functionality of the page)
I have tried to inject on the body, no luck.
tried to get the window object, which however do not have access to call the function.
Will try to change the location to something like: javascript:alert('test inject');
Many thx.
OK, after reading some official documentation and the GreaseMonkey's source, I get the following method which basically works for me.
Hope it will save sb's hour:
var appcontent = document.getElementById("appcontent"); // browser
if (appcontent) {
appcontent.addEventListener("DOMContentLoaded", function (evnt) {
var doc = evnt.originalTarget;
var win = doc.defaultView;
var unsafeWin = win.wrappedJSObject;
// vote.up is the function on the page's context
// which is take from this site as example
unsafeWin.vote.up(...);
}, true);
}
}
Greasemonkey does that. If you are developing your own extension with similar functionality, you can use Components.utils.evalInSandbox.

What causes the error "Can't execute code from a freed script"

I thought I'd found the solution a while ago (see my blog):
If you ever get the JavaScript (or should that be JScript) error "Can't execute code from a freed script" - try moving any meta tags in the head so that they're before your script tags.
...but based on one of the most recent blog comments, the fix I suggested may not work for everyone. I thought this would be a good one to open up to the StackOverflow community....
What causes the error "Can't execute code from a freed script" and what are the solutions/workarounds?
You get this error when you call a function that was created in a window or frame that no longer exists.
If you don't know in advance if the window still exists, you can do a try/catch to detect it:
try
{
f();
}
catch(e)
{
if (e.number == -2146823277)
// f is no longer available
...
}
The error is caused when the 'parent' window of script is disposed (ie: closed) but a reference to the script which is still held (such as in another window) is invoked. Even though the 'object' is still alive, the context in which it wants to execute is not.
It's somewhat dirty, but it works for my Windows Sidebar Gadget:
Here is the general idea:
The 'main' window sets up a function which will eval'uate some code, yup, it's that ugly.
Then a 'child' can call this "builder function" (which is /bound to the scope of the main window/) and get back a function which is also bound to the 'main' window. An obvious disadvantage is, of course, that the function being 'rebound' can't closure over the scope it is seemingly defined in... anyway, enough of the gibbering:
This is partially pseudo-code, but I use a variant of it on a Windows Sidebar Gadget (I keep saying this because Sidebar Gadgets run in "unrestricted zone 0", which may -- or may not -- change the scenario greatly.)
// This has to be setup from the main window, not a child/etc!
mainWindow.functionBuilder = function (func, args) {
// trim the name, if any
var funcStr = ("" + func).replace(/^function\s+[^\s(]+\s*\(/, "function (")
try {
var rebuilt
eval("rebuilt = (" + funcStr + ")")
return rebuilt(args)
} catch (e) {
alert("oops! " + e.message)
}
}
// then in the child, as an example
// as stated above, even though function (args) looks like it's
// a closure in the child scope, IT IS NOT. There you go :)
var x = {blerg: 2}
functionInMainWindowContenxt = mainWindow.functionBuilder(function (args) {
// in here args is in the bound scope -- have at the child objects! :-/
function fn (blah) {
return blah * args.blerg
}
return fn
}, x)
x.blerg = 7
functionInMainWindowContext(6) // -> 42 if I did my math right
As a variant, the main window should be able to pass the functionBuilder function to the child window -- as long as the functionBuilder function is defined in the main window context!
I feel like I used too many words. YMMV.
Here's a very specific case in which I've seen this behavior. It is reproducible for me in IE6 and IE7.
From within an iframe:
window.parent.mySpecialHandler = function() { ...work... }
Then, after reloading the iframe with new content, in the window containing the iframe:
window.mySpecialHandler();
This call fails with "Can't execute code from a freed script" because mySpecialHandler was defined in a context (the iframe's original DOM) that no longer exits. (Reloading the iframe destroyed this context.)
You can however safely set "serializeable" values (primitives, object graphs that don't reference functions directly) in the parent window. If you really need a separate window (in my case, an iframe) to specify some work to a remote window, you can pass the work as a String and "eval" it in the receiver. Be careful with this, it generally doesn't make for a clean or secure implementation.
If you are trying to access the JS object, the easiest way is to create a copy:
var objectCopy = JSON.parse(JSON.stringify(object));
Hope it'll help.
This error can occur in MSIE when a child window tries to communicate with a parent window which is no longer open.
(Not exactly the most helpful error message text in the world.)
Beginning in IE9 we began receiving this error when calling .getTime() on a Date object stored in an Array within another Object. The solution was to make sure it was a Date before calling Date methods:
Fail: rowTime = wl.rowData[a][12].getTime()
Pass: rowTime = new Date(wl.rowData[a][12]).getTime()
I ran into this problem when inside of a child frame I added a reference type to the top level window and attempted to access it after the child window reloaded
i.e.
// set the value on first load
window.top.timestamp = new Date();
// after frame reloads, try to access the value
if(window.top.timestamp) // <--- Raises exception
...
I was able to resolve the issue by using only primitive types
// set the value on first load
window.top.timestamp = Number(new Date());
This isn't really an answer, but more an example of where this precisely happens.
We have frame A and frame B (this wasn't my idea, but I have to live with it). Frame A never changes, Frame B changes constantly. We cannot apply code changes directly into frame A, so (per the vendor's instructions) we can only run JavaScript in frame B - the exact frame that keeps changing.
We have a piece of JavaScript that needs to run every 5 seconds, so the JavaScript in frame B create a new script tag and inserts into into the head section of frame B. The setInterval exists in this new scripts (the one injected), as well as the function to invoke. Even though the injected JavaScript is technically loaded by frame A (since it now contains the script tag), once frame B changes, the function is no longer accessible by the setInterval.
I got this error in IE9 within a page that eventually opens an iFrame. As long as the iFrame wasn't open, I could use localStorage. Once the iFrame was opened and closed, I wasn't able to use the localStorage anymore because of this error. To fix it, I had to add this code to in the Javascript that was inside the iFrame and also using the localStorage.
if (window.parent) {
localStorage = window.parent.localStorage;
}
got this error in DHTMLX while opening a dialogue & parent id or current window id not found
$(document).ready(function () {
if (parent.dxWindowMngr == undefined) return;
DhtmlxJS.GetCurrentWindow('wnManageConDlg').show();
});
Just make sure you are sending correct curr/parent window id while opening a dialogue
On update of iframe's src i am getting that error.
Got that error by accessing an event(click in my case) of an element in the main window like this (calling the main/outmost window directly):
top.$("#settings").on("click",function(){
$("#settings_modal").modal("show");
});
I just changed it like this and it works fine (calling the parent of the parent of the iframe window):
$('#settings', window.parent.parent.document).on("click",function(){
$("#settings_modal").modal("show");
});
My iframe containing the modal is also inside another iframe.
The explanations are very relevant in the previous answers. Just trying to provide my scenario. Hope this can help others.
we were using:
<script> window.document.writeln(table) </script>
, and calling other functions in the script on onchange events but writeln completely overrides the HTML in IE where as it is having different behavior in chrome.
we changed it to:
<script> window.document.body.innerHTML = table;</script>
Thus retained the script which fixed the issue.

Categories