views:

1744

answers:

6

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)
A: 

Make sure your script is fully loaded before trying to invoke functions from it.

Andreas Grech
This all happens after the page (and all scripts) have been loaded. Edited the question to reflect this. Thanks though.
Ryan
A: 

Ryan, what does showPopup do? can you perhaps create a simple method to isolate if it is something within the method that is in violation?

Tim Heuer
Nope, I made a function `testFunction()` in the same file as `showPopup` that doesn't do anything but call `alert()` with the same results.
Ryan
+1  A: 
Peter McGrattan
+1  A: 

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.

Ryan
+2  A: 

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!

Oli
A: 

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.');
};

}

Neo42