You are reading a MIX Online Opinion. In which we speak our minds. Hans Hugli Meet Hans Arrow

Lab Notes

0Comment Retweet

DLR and JavaScript Interoperability with Gestalt

Aug 27, 2009 In Development By Hans Hugli

How can I mix the results of a Python script to do or execute a javascript function with Gestalt?

When one of our smart readers asked the question above, we knew we had a challenge on our hands. We accepted the challenge, took a look at the problem–and came up with two samples that show 1,,) calling a JavaScript function from Python or Ruby and 2) calling a Python or Ruby method from JavaScript. In this article I’ll cover Python; the Ruby version is linked below.

Python, Calling JavaScript.

In the context of a Silverlight application, Python runs in an entirely different process than JavaScript. Still, Python can easily call a JavaScript function by using the HtmlPage class in the System.Windows.Browser namespace. Let’s say, for example, that we have a JavaScript function named “javascriptFunction,” like this:

<script type="text/javascript">
   function javascriptFunction(x) {
      alert(x);
   }
</script>

Here, we’ve imported the HtmlPage class into the Python script. This class contains an Invoke method which accepts a string: the name of the JavaScript function we want to call, plus a parameter list. In this snippet we happen to pass a string as our parameter, but we could just as easily pass an object:

<script language="python" type="text/python">
from System.Windows.Browser import HtmlPage
HtmlPage.Window.Invoke("javascriptFunction", "Hello I'm
   Python!");
</script>

What action results from these two fragments of code? As soon as the Python script executes, it makes a call to the JavaScript method and pops an alert box with the parameter that was passed. Very straightforward.

JavaScript, Calling Python.

Calling Python from JavaScript is a little trickier than the other way around, since Python is running in a different process. One solution is to register a JavaScript click event in the Python script so that when an HTML button click fires an event, it is caught in Python. This works–but is limited–since we want JavaScript to call a function that raises an event in Python. As a workaround we might try raising the button click event, but this doesn’t successfully trigger the Python-registered event. Back to square one.

The best solution here is to expose the JavaScript function “registerDlrFn” that takes an object as a parameter. In this case, the object we’re expecting is an EventHandler, which is assigned to a local variable “DlrFn”. Once the variable is assigned, we can simply fire the event by calling it. We wrap the call to fire the event in the function “callDlrFn”:

<script type="text/javascript">
   function registerDlrFn(fn) {
      DlrFn = fn;
   }
   function callDlrFn(x) {
      DlrFn(x, null);
   }
   callDlrFn ("Hello this is javascript");
</script>

We’re not quite done yet, though. For Python to catch the call to the “registerDlrFn” function, we need to use the HtmlPage.Invoke method again. This time we pass an event handler that’s cast to HtmlEventArgs, which is bound to “PythonMethod,” the method we want to call from JavaScript. Note that when the Python script is executed, the “registerDlrFn” function is invoked immediately. The EventHandler is passed and assigned to “DlrFn” in the JavaScript. Thus, the HTML DOM becomes aware of the EventHandler, making it callable from JavaScript:

<script language="python" type="text/python">
from System.Windows.Browser import HtmlPage
def PythonMethod(s,e):
   window.Alert(s)
HtmlPage.Window.Invoke("registerDlrFn",
   EventHandler[HtmlEventArgs](PythonMethod))
</script>

The Lesson?

As you can see, calling Python from JavaScript was less intuitive than the other way around. This same approach applies to Ruby and JavaScript interoperability. You can find a Python sample here, or a Ruby sample here. Remember to right-click if you want to view the source code for the samples!

We appreciate and look forward to your feedback. Please don’t hesitate to leave a comment, and if you twitter, follow us there to hear when we release new content, opinions or articles.