Articles Archive
Articles Search
Director Wiki
 

Hey Browser it's Me! Shockwave? Hello?

March 16, 1999
by Alan Levine

This article started at 30,000 feet over south Texas, enroute home after a family visit. Scribbling notes on a pad of paper, I noticed a businesswoman on the aisle pull out a sleek Dell laptop. Thinking this would be an opportunity to help pass time with conversation about technology, my hopes were dashed as she started a marathon Solitare session streitching from central Texas to southern Arizona. My informal research this year indicates that 8 out of 10 people lugging laptops onto planes are using them to play Solitaire, and the other two are writing mundane Word memos. I go back to drawing flow charts and screen ideas, muttering bad kharma about wasted electricity.

What does this have to do with anything? A connection awaits at the end of this article. Don't scroll yet, you'll miss the good stuff.

This article covers some things I have learned in trying to get a shockwave application to "talk" to the web browser, using Lingo introduced with Director 6. It also illustrates what happens when you get an idea at 8:00 AM, fail implementing it, recode it, appeal to the documentation in vain, try some more code, ask for help on the net, and if lucky, by the afternoon, you've got a new feature working. Or you return to the pre-modified copy of your files (we experiment on copies of our current project files, correct?)

In other words, a normal day in the world of slash n' burn Lingo.

Why would Shockwave Need to Talk to the Browser?

Maybe your shockwave project is its only little beastie, a game, a presentation, that sits in its assigned rectangular web page location and happily interacts with the person looking at the page. However, In many projects I work on, the Shockwave may only be something that is part of a larger web site, perhaps integrated with other features of the site. This happens quite a bit when you start using JavaScript to provide increased functionality, especially when shuttling information between web browser frames or windows. I've used JavaScript to create parent-child data structures.

You may want the shockwave application to be able to spawn a new web browser window where JavaScript is used to define the window properties (buttons, size, location, etc). Or you may send information to a JavaScript function that can then spawn a new web browser window with a layout that includes this dynamic, run-time information-- for example, to create a game score summary or a student test result page that can then be printed from the browser (since for some deeply arcane security reason, you cannot do from shockwave without an Xtra or a letter from the Pope).

For several projects I have found it useful to be able to send data from my Lingo programming environment to the browser scripting environment.

The Project Needs

This came up during some prototyping for an on-line Biology educational project. The interaction occurs within a shockwave application; the main entry page is normal HTML content, with a link that uses JavaScript to open the .dcr in a new browser window. JavaScript allows me to open this window without all the browser buttons, URL fields, etc to in a fixed window size to maximize the shockwave stage size. Yes, I am trapping the user in my world and the only way out is to close the window.

A first need was to create an "exit" button for all shockwave screens that would do some application clean-up, and then uses a JavaScript function to present a confirmation dialog box, which is chosen by the user, would then close the browser window.

It works something like this

The second need was to have a "help" button on all screens that would open up the appropriate content yet another web browser window. To do this, my help button needs to track an identifier for the current part of the program and then send this string to a JavaScript browser function that would then open the specified "help" window.

From the Browser Side

It looked pretty simple on paper. The JavaScript for a confirm dialog box and closing a window is trivial.


<SCRIPT LANGUAGE="JavaScript">
<!--
function closeLab() {
  if ( confirm( "Are you sure you want to 
  leave the Laboratory?"))  {
    self.close();
  }      
}
// -->
</script>

So the exit button from Shockwave would simply need to call this JavaScript function. In fact, before even trying it from Lingo, I test the JavaScript functions from the browser-- in NetScape, I load the HTML page and enter in the URL field:

javascript:closeLab()

which invokes the function (Can't do this in MSIE!). It makes sense to make sure the JavaScript even works before you start mucking from the Lingo side. The "help" button JavaScript function need only take the input string, and then construct a relative path to the appropriate HTML file to pop into a new browser window.


function goHelp( hDoc ) {       
  var help_win = window.open(hDoc, 'hlab', 
    'width=580,height=320,screenX=20,
    screenY=20,top=20,left=20');                
    
//----- for NetScape, we can bring the 
// window to the front
  if (navigator.appName.substring(0,8) 
    == "Netscape") help_win.focus();
}

If You Can Do That, Try it From Lingo

Scanning the Lingo docs, it seemed it was as simple as contructing a string that comprised the entire function call to JavaScript, and then send this string via

externalEvent("someJavaScriptFunction('param')")

One of the pitfalls I have seen people make is to try to send a browser script that includes the value of a lingo variable:

externalEvent("doThisFunction('name','age'))"
where name and age are some lingo variables that we may have garnered from some editable text member. If you do it this way, you are simply sending to your JavaScript function the names of these variables, not the values! So you have to do some simple Lingo gymnastics to write:

externalEvent("doThisFunction('" & name & "',¬
  '" & age & '"))"

more or less creating a string that contains the values of the variables. Note also that calling these functions in JavaScript requires that the parameters are explicit strings, the reason for the single quotes.

The exit button one is easy since we do not have to send any parameters, so that has something like looks like:

on mouseUp me
   externalEvent("closeLab()")
end

To make the work flexible, the sprite for the "help" button has a behavior that stores the name of the help file as a property that represents the current area of the virtual lab that we need to provide help-like information:

property pHelpDoc
on mouseUp me
  externalEvent("goHelp('" & pHelpDoc & ¬
  ".html')")  
end
on getPropertyDescriptionList  
  return  [ #pHelpDoc: [ #comment:"help doc ¬
  name:", #format:#string, #default:"help"] ] 
end
on getBehaviorDescription
  return "Sends javascript command to open ¬
  specified help doc page. Do not include '.html'!" 
end

The Gotcha's

Life gets complicated once you start trying to confirm performance on a range of browser brand/version permutations. To use externalEvent with NetScape, the browser requires LiveScript to be activated, hence invoking Java. So in the NetScape tag, when you use JavaScript, you must set the flag for swLiveConnect=true, meaning that if the viewer has not yet seen a page that used Java, then they have the pleasure of watching that little spinning cursor and watching "Loading Java...".

Why? externalEvent requires some of the security features in Java to talk to the browser.

One thought as a work around was to forget the whole externalEvent approach and instead invoke the JavaScript functions via commmands like:

getNetText ("javascript:closelab()")

No need for the Java dance! It works on NetScape 3,4 (Mac and Windows) and MSIE 4 (Windows) but not MSIE 3. Not cool, there are a lot of these browsers out there. More importantly, this sort of construct neatly identified a few years back by Dave Yang, is pretty much a hack (although a clver one, thanks Dave!) and I would question its availabilty in the long run.

Going back to the externalEvent approach, we find that it works on NetScape browsers but not MSIE. Why? The Omnicient Oracles in Redmond decided that their browsers would respond only to VBScript, which to me is more or less some Visual Basic jargon stamped on top of JavaScript constructs.

Now I do not know squat about VBScript and the Micrsosoft site is pretty cryptic. Don't expect much in the way of examples on your Director CD either. What can you do? I quickly posted a request on a listserv, and within an hour Eric Coker sent me some code I can work from.


<SCRIPT FOR="enzymeTA" 
EVENT="externalEvent(swParam)" 
LANGUAGE="VBScript">
<!--
  DIM myString
        
  IF swParam = "closeLab()" THEN              
    strPrompt = "Are you sure you want to leave 
      the EnzymeTA Laboratory?"
    strTitle  = "Exit the lab..."
    result = MsgBox(strPrompt, vbOKCancel, strTitle)
    IF result = vbOK THEN
      self.close()
    END IF              
  ELSE
    myString = Left( swParam, Len( swParam) - 2  )
    myString = Right( myString , Len(myString) - 8)
    objHelpWin = window.open( myString, "hlab", 
      "width=580,height=320,top=20,left=20")
  END IF
-->
</SCRIPT>

From what I was able to tinker with, the VBScript more or less gets the whole function call and parameters as a string, and I have to chunk out not only the variables but the names of the functions and test which function was sent from Lingo.

Note that the value of the FOR parameter in the SCRIPT tag (FOR="enzymeTA") must match the value of the NAME paramater in your OBJECT tag (NAME="enzymeTA")-- otherwise this will not work in Internet Explorer (Thanks NoiseCrime!)

So here is the winning combination:

And the missing piece? Nothing ever works as expected in MSIE/Mac. The closelab() function worked but the help() does not. The whole browser is 404 as far as I am concerned, and I sniff out this dog from my initial JavaScript function that first opens the shockwave window. By testing the Browser version, I can weed our pre 3.x browsers and by sniffing out the browser brand and platform, I can then weed out MSIE/Mac:

<script language="JavaScript">
<!-- 
function get_version () {
  return Math.round(parseFloat(navigator.appVersion) * 1000);
}
function enter_lab() {  
  if ( get_version() < 3000 ) {      
    alert ("We are sorry, but to open the lab you will 
      need a browser of version 3.x or later.");
  } else {
    if ( (navigator.appName.substring(0,9) == "Microsoft") && 
      (navigator.appVersion.indexOf("Mac") > 0 ) ) {               
      alert('Because of limitations in Internet Explorer 
        for Macintosh, some features of this site will 
        not work. You are better off with NetScape!');
        }
//----- we've passed the tests by here, so proceed to open the 
//----- Shockwave page in a new window....      

Sorry, MSIE has some nifty features but since day 1 with shockwave its been a voodoo-like combination.

Another very useful thing I found during testing of this approach was to include some dumb old alert messages so I could trace the action. In my lingo, before calling externalEvent, I would add something like:


alert("Hey Browser, this is Shockwave! I am ¬
  sending" && QUOTE & eString & QUOTE)

and in my JavaScript/VBScript functions, write similar lines:


alert("Hey Shockwave, this is your Browser! ¬
  I got" && QUOTE & param1 & QUOTE)

Yes, a Paleolithic approach, but it was the only way I could identify which of my functions were even messaging and that they were sending/recieving the correct parameters.

And this is really only half the trip! Getting the Browser to send something to Shockwave is another story, another column.

The project is more or less in a semi-dormant state, but you see most of it from http://www.mcli.dist.maricopa.edu/mobius/enzyme/

The Freebie

For my shockwave buttons, I went for a low tech button approach-- a simple Text member and a behavior that allows a custom cursor and a highlight on rollover (by swapping with inks). It is yours for the taking at http://www.mcli.dist.maricopa.edu/alan/nojava/cheaproll/

The Moral

What about the female suit with the Dell Solitare device?

"I was the clever Lingo code with data and interest in communicating to the browser across the aisle, but although I thought I could properly format my function call she was not a compatible version or perhaps she was just to busy loading Java..."

Alan Levine is an Instructional Technologist at the Maricopa Center for Learning & Instruction at the Maricopa Community Colleges. Among other random things, he tries to maintain the DirectorWeb, does side work as dommy media, and not often enough, mountainbikes in the desert.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.