I'm attempting to call a javascript function (in our code) from a silverlight control. I'm attempting to call the function via:
HtmlPage.Window.Invoke("showPopup", new string[] { "http://www.example.com" });
and I get the error "Failed to Invoke: showPopup"
I can call HtmlPage.Window.Invoke("alert", new string[]{"test"}); without issue, but not my own function.
I can also open up the page in question in the IE developer tools and manually call showPopup("http://www.example.com") and it works as expected.
So the js function works, and the Silverlight binary can find other js functions. What am I missing here?
Additional Notes:
The function call is in a button click event handler, so it happens after the page (and the script) have been loaded)
Aha! I figured it out. Our app uses an iframe, so the rendered html looks something like this
<html>
<head></head>
<body>
Stuff
<iframe>
<html>
<head></head>
<body>Other Stuff</body>
</html>
</iframe>
<body>
</html>
And the Silverlight control in question is in the iframe. The problem was that the file that contained the showPopup function was referenced in the outer <head> (why I could call the function with the IE toolbar) but not the inner <head>. Adding a reference to the file in the in-the-iframe <head> solved the problem.
Sort of anticlimactic, but thanks for all the help.
Actually referencing the script again from the iframe is not the most efficient way to reference code contained in the parent. If your function is called "showPopup", you can insert this in your iframe:
<script type="text/javascript">
var showPopup = parent.showPopup;
</script>
And voilà. The explanation for this is that all "global" functions and objects are part of this "global namespace"... which is the "window" object. So if you're trying to access "global" functions from a child, you need to either call the function on the parent (e.g parent.showPopup('....')) or declare a local alias for it (which is what we do in the above example).
Cheers!
Is the showPopup javascript function on the same html or aspx page as the Silverlight control? You will normally get the "Failed to Invoke ..." error if the javascript function does not exist:
HtmlPage.Window.Invoke("functionThatDoesNotExist", new [] { "Testing" });
What browser are you using when you are getting this problem?
Are you using the latest version of Silverlight?
Are you using the ScriptableType attrbiute anywhere?
Is it possible to list the code for a short but complete program that causes this problem to happen on your machine...
Make sure your script is fully loaded before trying to invoke functions from it.
Here's how I do it. But I'm creating silverlight without visual studio. I just have raw html, xaml, and js (javascript). Notice MouseLeftButtonUp and it's value "LandOnSpace"
<Canvas x:Name="btnLandOnSpace" Background="LightGreen" MouseLeftButtonUp="LandOnSpace"
Cursor="Hand" Canvas.Top ="0" Width="70" Height="50">
<TextBlock Text="LandOnSpace" />
</Canvas>
function LandOnSpace(sender, e) { //on server
if (!ShipAnimateActive && !blnWaitingOnServer) {
blnWaitingOnServer = true;
RunServerFunction("/sqgame/getJSLLandOnSpace");
ShowWaitingBox();
};
else {
alert('Waiting on server.');
};
}
I had the same problem in VS 2010 with SL 4. I had created a few methods and put them into one single JS file. However this file had not been added to the head section of the ASPX file. Adding it solved the problem. The difference is that though I did not have a separate head section in the iframe, I had the problem and it got solved.
Related
I have a knowledge base for my work. I'm trying to get full html w/scripting setup within a iFrame instance.
Below is a Chrome expansion of my setup. When I click the button in my div/iframe, I get a Uncaught ReferenceError: test is not defined error.
Thoughts?
http://bytes.com/topic/javascript/answers/153274-script-iframe-can-not-call-functions-defined-parent-document
Per link:
Functions are not properties of the document, but of the window.
Try
parent.foo();
or
top.foo();
<button onclick='parent.test();'>test</button> works now... top.test() works too, BUT, I'd like a way to normalize this. Its not very intuitive.
Is there a way to NOT have to prefix top. or parent.?
Make sure the jQuery library is being called before any other script inside your <head> section.
Most of the times I get this error, I just change the order the scripts being called on the page (always under jQuery) and it solves the problem.
This is a late answer, but I'll share my solution.
I needed an iframe as a preview container. So parent.something would be a hassle.
This seems to work:
<iframe id='iframe' sandbox="allow-same-origin allow-scripts"></iframe>
And populate it with this (example using jquery):
$(function() {
let $iframe = $('#iframe');
$iframe.ready(function() {
let ifhead = `
<meta charset="UTF-8"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"><\/script>`;
let ifbody = `<h1>My Body</h1>`;
let ifscript = `$(function() { $('h1').css('color', 'blue')})`;
let html = `<html><head>${ifhead}</head><body>${ifbody}<script>${ifscript}<\/script></body></html>`;
document.getElementById("iframe").contentWindow.document.open();
document.getElementById("iframe").contentWindow.document.write(html);
document.getElementById("iframe").contentWindow.document.close();
});
});
Now the iframe acts as a stand-alone page.
<textarea name="widget-generalcode" cols="50" rows="13" id="widget-generalcode"></textarea>
and javascript
<script>
document.getElementById('widget-generalcode').innnerHTML = 'test';
</script>
When I run code, error TypeError: document.getElementById(...) is null, how to fix it ?
May be you should put it on pageload:
<script type="text/javascript">
window.onload = function(){
document.getElementById('widget-generalcode').innerHTML = 'test';
};
</script>
You should consider where you place javascript statements.
It will effect to the desired result.
I recommended that you should use web development tool such as Firebug in Firefox (press F12)
It will help you to debug javascript code and you can use Timeline feature to detect which parts of your Html/javascript "spent" a lot of resources.
Hope this information is useful.
First of all, check that your JavaScript is executed when DOM is loaded. One option is to put your <script> tag just before </body>.
Then, you should use value property for form fields:
document.getElementById("widget-generalcode").value = "test";
you are trying to access the element before it is rendered on your page so you will never get that element so write your code in function as below
<script>
function call()
{
document.getElementById('widget-generalcode').value = 'test';
}
</script>
and now in body tag palce onload ="call()" as given below it will work
<body onload ="call()" >
</body>
Sorry I'm new 2 Stackoverflow
In asp.net Actualy Startup is my id but on clientside it will be displayed as ctl00_dmrcontent_Startup
so in ur script change id form widget-generalcode to what display in clientside
<div id="Startup" runat="server">
This caused me much grief. It's a matter of understanding the sequence of execution of the "onLoad" (which occurs after all the PHP has been executed and turned into HTML), and the running of a js command after say parsing the url parameters (which occurs before onLoad).
The javascript function ran before the html page with rendered by the browser. So the element with the id="widget-generalcode" did not exist when the code ran.
Use window.unload= functionName at the top of your javscript file, without parentheses (). This tells the browser to run the function after the html page loads. This way the html element will exist when the function runs and the javascript can act on it.
I'm a javascript beginner, and I'm trying to figure out why this code works when written in the head, but not when it's being referenced from an external file.
in the head of my html document, I'm referencing the javascript file "quote.js" as follows.
<script type="text/javascript" language="JavaScript" src="/js/quote.js"> </script>
the contents of quote.js are as follows
var textarray = [
"Be Good.",
"Our future depends powerfully on how well we understand the cosmos.",
"Bottomless wonders spring from simple rules... repeated without end.",
"All our science, measured against reality, is primitive and childlike — and yet, it is the most precious thing we have.",
"To use violence is to already be defeated."
];
function RndText() {
var rannum= Math.floor(Math.random()*textarray.length);
document.getElementById('ShowText').innerHTML=textarray[rannum];
}
window.onload = function() { RndText(); }
finally, the div I'm replacing in the body is as follows...
<div id = "ShowText"></div>
it's probably a stupid mistake, but I've been trying to track it down for a while now, and I'm missing something. When I write the contents of quote.js in my html head, it works fine. Any ideas? Thanks in advance.
If the code works in the head, but not when included, it's likely to be a problem with the path to the script. Double check that /js/quote.js is an appropriate location. It may need to be js/quote.js, you you may have a typo. In browsers like FireFox and Chrome, if you view the source code of your page you can click on the path to files like this and it loads the included file or shows you an error if the file is not found.
If you can share a link to the page, I can tell you with more certainty exactly what the problem is.
Also, you don't have to the language attribute if you're using XHTML, but that's not causing the problem.
Perhaps the code is running before the DOM is ready
Instead of onload use the event DOMContentLoaded
document.addEventListener('DOMContentLoaded', function () {
//code here
}, false);
I want to ask a question about the Javascript’s onload.
I’m writing a JSP page with the code <%# include file ="body.jsp". The included body.jsp contains:
<table onload="function()">
This should load the javascript function, but it doesn't appear to have any effect on the page. Is onload only usable on the body tag?
Onload can only be used for <body>, <img>, <script>, <iframe> tags, because it tells you when an external resource (image, script, frame) or the whole page (body) has been loaded
Since HTML5 these can also fire a load event: <link>, <style>, <input type=image>, <object>
Support for these can still be a hit or miss though (e.g. older Android browsers)
Why not just include it via a <script tag>?
Inside your .jsp file
<script>
window.onload = function() {
alert("Hello!");
}
// or to execute some function
window.onload = myFunction; //notice no parenthesis
</script>
As the other guys already stated the onLoad event will not fire on a table. What you can do ist attaching the onLoad-handler to the body element (which will then fire, when the page is loaded) and manipulate the table by for example assigning an id to the table.
<body onload="function() { var table = document.getElementById("table-id"); ... }">
<table id="table-id"></table>
</body>
Are you using some javascript framework?
"onLoad" may be used on body- and frameset-tags.
To see some action you may use:
<body onload="function(){alert('This is an action!')}">
The easiest way i find is to use an external javascript file and jquery.
// Variables and functions you want to declare
var socket = io.connect();
// .....
// Function you want to run on load
$(function() {
$('#submit').click(function() {addUser();});
// ... any other functions you want to run on load
});
This is a code snippet from something that i was working on. The variable is declared before the code runs (It creates a web socket).
Then there is the jquery document selector ($) which runs on load and calls the init function to modify my html. I use it to call an anonymous function which runs right away.
You can throw a <script> tag right after your table with code. Once it gets to the script tag it would mean that the DOM for the table element above it has been loaded and can now be accessed in your script below it.
Note: The following below isn't applicable to the question but rather the other answers being given.
I recommend using the addEventListener function in javascript for adding the event. This makes sure that you are not overwriting or going to be overwritten by anyone else wanting to listen to the event.
Example
var iframe = document.getElementsByTagName('iframe')[0];
iframe.addEventListener('load', function(event){ console.log("iframe Loaded", event); })
I am using JQuery to inject dynamically script tags in the body tab of a webpage. I got something like :
function addJS(url) {
$("body").append('<script type="text/javascript" src='+url+'></script>');
}
I add several scripts this way, and try to use them right after. E.G :
lib.js
function core() {...}
alert("I'am here !");
init.js
addJS("lib.js");
c = new core();
test.html
<html>
<head>
<title>test</title>
<script type="text/javascript" src="init.js"></script>
</head>
<body>
Hello
</body>
</html>
Loading test.html pops up "I'm here" and then ends up with an error "core is not defined". Of course merging both of the JS files will make them work perfectly.
I just don't get it o_O.
EDIT
I simplified this example, but Jeff answer made me understand that it was a mistake. So here are some details :
init.js is not in the head of test.html when it reload because I inject it with a code exectuted on a bookmarklet.
So the real execution process is the following :
reload test.html > run the bookmarklet > jquery and init.js are inserted > lib.js is inserted
Sorry for the confusion.
EDIT 2
Now I have the solution to my problem (that was quick :-)) but I am still interested to the answer to my question. Why does this go wrong ?
jQuery has this functionality built in with getScript.
You get the "core is not defined" error because the scripts are loaded asynchronous. Which means that your browser will start loading lib.js in the background, and continue executing init.js, and then encounter "new core()" before the lib.js has finished loading.
The getScript function has a callback that will be triggered after the script is finished loading:
$.getScript('lib.js', function() {
var c = new core();
});
Notice your addJS function is appending to the end of the body element.
Since browsers will run scripts as they appear in the HTML source,
c = new core()
will run before your lib.js script is loaded (at the end of the body element).
I would recommend moving c = new core(); into the $(document).ready(function() {...}); or into a script element AFTER the body tag.
IMO, appending the script tag to the end of the document to load a script is rather unsightly. Reason:
you are trusting the browser to automatically fetch the script and load it.
You have no way of finding out whether the script is loading, has loaded, or if it encountered an error (maybe 404?)
The appropriate way would be to either use $.getScript(), or for a finer-grained control, fetch the script file with $.ajax() and use eval().
However, the second method has some issues: if you invoked eval() inside a function, then the script won't be available outside it! This mandates workarounds...
but why bother! use $.getScript() and get over with it :)
cheers, jrh.
In response to why your code is failing: Adding a script tag to the body does not block further script execution. Your code adds it, which starts the browser download process. Meanwhile, your script tries to call core(), which doesn't exist because lib.js hasn't finished downloading. jQuery works because it waits till the script finishes downloading before executing your callback function.