Articles Archive
Articles Search
Director Wiki
 

Browser. This is Shockwave! I said Print, Damnit!

October 18, 1999
by Alan Levine

The Scene:
The Bridge of the U.S.S. Shockwave, the timer = 5234567439543895432 ticks. Captain James T. Lingo, pounds his fist on his console, breaking off the useless keypad.

Capt Lingo:
We must be able to print from our ship to an external browser window. We .... must....be .... able .... to print ....damnit!.... Engine Room?

First QA Engineer Scott:
(shuffling di-lithium crystals and dot syntax, smoke in background). Cap'n! I caaaahn't work meeeracles! We've searched all the archives, all the technotes, and she just won't work! I'll be as buggered as a bow-legged spring lass --

Capt Lingo:
That's enough. I want answers!

Dr. McVoid:
Damnit Jim! I'm a doctor, not a C-Programmer.

Lt Sprite:
(arching a Vulcan eyebrow) Most illogical.

Okay, that is more than enough old Star Trek silliness.

This column, like most of the random().previous ones, revolves around what I have been tackling lately in Director or perhaps some repeated request I've heard on the listservs (and I actually know enough to respond).

Not many days go by when someone asks about printing from Shockwave. We're going to dive into that one here, but to get there, we had to dance, twirl, and hash out a.... dare I say the word? (shhhhhh) BUG! Bug! El Buggo! in using Shockwave to have the browser create dynamic content via JavaScript.

Maybe bugs do exist?

This was somewhat covered in a recent randomness column here "Hey, Browser, it's Me! Shockwave? Hello?" I got a few emails saying, "dude- your code does not work for me!" so I felt obliged to look into it. These folks were working on projects that clients were paying for, and developers were banging their heads hard against something not widely broadcast in the docs.

Printing not 1-2-3

Here is a guaranteed way not to have a printing capabilty from shockwave- telling your site visitors to use their browser print button.

That is pretty much a game of Russian Roulette, where mostly you will get blanks. Sure you won't get hurt, but the game is pointless.

It is so unreliable that it should be immediately be dismissed. Why? The browser really has no idea what is in the Shockwave cut-out of its screen space. As far as the browser is concerned, it allots some screen real estate to shockwave, calls up its run-time code, and then sits there, maybe called to task by some externalEvent call. Whatever is displayed in that real estate, the browser really is never privy. It is a window to another world.

If you are ever able to print from shockwave by using the browser print button, you are lucky, or using the one obscure browser/version/platform combination where it might work. Alan's Random Law of the Obvious But Perhaps Not Number 3.56 is that just getting it to work on your desktop doesn't mean it will on mine. And on the web, the majority of time you will not know if the code bonks, because they just might silently click elsewhere. And they often do not bother to tell you.

Call in the Xtras

The next appoach for printing from Shockwave, available for D7 users (we are all now, right?) is to use the POM, PrintoMatic Xtra. According to the Electric Ink web site, this Xtra is "Shockwave Safe" meaning that you can use the Xtra and have it downloaded to the viewer of the site if they need it. Using the Xtra might be most useful where you have to do quite a lot of formatting of the content, say to output an order form.

However, at last click, the POM Xtra, for $300, was Shockwave safe only for the Windows version, see the technote at http://www.printomatic.com/technote.cfm?technoteid=17

This technote does claim the free POM-lite version is Shockwave safe too, but still only for Windows:

NOTE: Currently, the auto-downloadable versions of these Xtras are only available for Windows. We hope to fix the bugs that are preventing a Macintosh release soon. However, you can still use a Macintosh to create Shockwave movies that use these Xtras; you just won't be able to browse them on a Mac.

Bugs? How can they say bugs? They shoot bugs, don't they?

If I was reading this, I would hear the annoying "Red Alert" noise in the background. The risk factor sounds high here.

I cannot say good or bad about POM over the web from first-hand experience. One writer on Direct-L, Mike Weiland, reported decent success on a Windows client. If you have better info, please step into the transporter room now. Beam it to me.

Make the Browser Do it

For me, the low overhead way to provide printing capability is to have Shockwave tell the browser to open a new window, write content to that window with JavaScript, and have your site visitor use the browser button to print from there.

The first time I used this method, I routed the request to a server side CGI called from Shockwave. In this application, after performing some tasks, the visitor to our site took a test, and if successful, in Shockwave we would insert their name (entered in a Shockwave field), their test score (stored in a global after the fact), and the date (you should know where that comes from!) into an on-screen diploma.

Of course, in Shockwave, the three text members could be overlaid directly on a single graphic of the diploma. To create an equivalent version for the browser, we broke the graphics into parts, and converted them to GIF images. All we had to send the CGI was the name of the person and their test score (we can rely on the server to grab a system date), and then re-construct the diploma layout in HTML:

on makeDiploma
    global gName        -- user name
    global gCGIURL   -- path for web server cgi directory
   
    -- We gotta go through a CGI, so
    -- sanitize the blanks in the name string for cgi
    -- If we had something other than a name, 
    -- we should do a more robust hex conversion
    
    repeat with i = 1 to the length of gName
      if char i of gName = " " then put "+" into char i ¬
        of gName
    end repeat
    
    -- build the cgi string
    set cgiString = gCGIURL & "make_diploma.pl?"
    put "name=" & gName after cgiString
    put "&score=" & word 1 of field "myScore" after ¬
      cgiString
    
    -- call the CGI and target a new browser window
    gotoNetPage cgiString, "diploma"
end

Again, this is some D5 code fragments presented for principle. If I were doing this in D7, I would be stuffing the parameters into a property list and then send that to the CGI via a postNetText (this does all of the conversion to a proper CGI string and is easier to manipulate from the Lingo side).

The perl script goes like this:


#!/usr/local/bin/perl # Creates the page for the diploma # so folks can print it out. The name and # score are sent from a shockwave movie get method # We use the server to stamp the date and time # Load CGI.pm library, and create standard return header use CGI qw(:standard :cgi-lib); &ReadParse(*in); print header; ####### edit for the base directory where we can find the images var $base_directory = 'http://www.blah.com/html/shockthing/'; ####### get date in a nice string (undef,undef,undef,$mday,$mon,$year) = localtime(time); $year+=1900; / at / months = qw(January February March April May June July August September October November December); $dateString = "$months[$mon] $mday, $year"; ####### Format the output print <<"EOF"; <HTML><HEAD> <base href="$base_directory"> <TITLE>My Diploma</TITLE> </HEAD> <BODY bgcolor=#FFFFFF> <center> <img src="images/diploma_top.gif" alt="--" width="500" height="121"><br> <font size=+4>$in{'name'}</font><br> <img src="images/diploma_mid.gif" alt="--" width="500" height="19"><br> <font size=+2>$in{'score'} / 10</font><br> <img src="images/diploma_bot.gif" alt="--" width="500" height="108"><br> <font size=+2>$dateString</font><br> <img src="images/diploma_seal.gif" alt="--" width="500" height="87"> <p> <hr size=1 noshade> <font size=2 color=#666666>blah.com university<br> http://www.blah.com/univ/ </font> </BODY> </HTML> EOF ;

What I like about using the CGI approach is that, if it is relevant, I could toss in an extra subroutine that would write the data to a log file (where we can also pull environmental variables like the person's IP number, their Browser version, etc) that could be analyzed later. Quite often that is pretty handy info, other times it is just wasted bits and programming time (of course billable hours can be okay for some of you).

But Let's Leave the Server Out of the Loop

These kind of tasks, spawning a browser window and writing content to it, are just as well done with JavaScript, and thus can be used offline or without relying on a net transmission.

That was the thrust of the article I wrote in this space "Hey, Browser, it's Me! Shockwave? Hello?" based upon some Shockwave projects I had been working on that called for opening up a HTML file as a help reference for a shockwave app. That article was an overview of using ExternalEvent to have Shockwave send a command to a JavaScript/VBScript in the browser to do something.

I got several e-mails from folks that were trying to use my examples to have Shockwave tell the browser to spawn a browser window and then use more JavaScript to write content to that window. It seemed like the same approach, but the result was that for Netscape Navigator, shockwave could call a Javascript function, have it spawn the window, but any attempts to document.write (JavaScript talk here) were ignored and the result was a boring, lifeless, empty window (it worked as expected in Internet Explorer, much to my Netscapian dismay).

The frustrating thing was that they could get the JavaScript function to work if called from the browser URL field (issuing javascript:doSomeJSFunction() as a URL).

After rooting out some of the obvious thoughts (not running from a dswMedia folder on local drives, not setting swLiveConnect="true" in the embed tag), I was determined to get to the bottom of this. In retrospect, the project I was working on when writing the article was opening browser windows but just targeting static content to them.

I set up a simple demo where some data was entered in Shockwave, and a button click would send the data to be stored in browser side variables. Then, another button from Shockwave would call a JavaScript function deisgned to open a browser window and then write the data sent from Shockwave to the new window. On the same page, I created an HTML form that used JavaScript to do the exact calls that Shockwave was attempting so I could demonstrate that things worked on the browser side. Both Lingo and Javascript were sprinkled with alert commands to track where the action stopped.

By the way, there is a way around this problem. In the HTML for embedding the shockwave, you can add a paramter in the OBJECT tag:

<param name="sw1" value="ie">

and in the NetScape EMBED tag:

sw1="ns"

So that in Lingo, we have a variable that identifies the browser. When it is time to call the JavaScript function that writes a report page to a window, we test this variable. For Internet Explorer, we can use ExternalEvent safely:

externalEvent("show_report()")

but if we were using Netscape, where this function only produced an empty window, we could reference a JavaScript URL:

getNetText("javascript:show_report()")

which works in Netscape and not Internet Explorer.

This is a kludge, but it works. That is what we want, eh? Still, externalEvent seemed to not be working as specified in the docs.

Bugs in the Pudding

Aha! I had it! A true to life bug! Wriggling on the floor! A clear demonstration that Director did not do as advertised, with a well documented source file. After posting a message on Direct-L and ShockR, a dispatch came from the mothership, starbase-- No, This Is Not A Bug. It Is In The Technotes. You Silly Fool.

And yes, humbly, if you have any luck at finding anything in the Macromedia Technotes, you may come across http://www.macromedia.com/support/director/how/subjects/brwsrscriptips.html

"Using externalEvent to change the contents of another frame on the page with frame.location or document.write will not work. To work around this, trigger a flag so that the update is called from another function after the one called by externalEvent has completed."

It does not explain why, just that you cannot do what I was trying to do. Ipso facto, doltus eruptus.

The solution (in my book, an end run, a work around, but hey call it anything but late for dinner, it works), is to more or less trick the browser so that it delays the call, and triggers it calling again a quarter of second later (the so called "untainting"). You can get to this nugget within another technote at http://www.macromedia.com/support/director/ts/documents/browserscript_timeout_techn.htm

Here is how I implemented it in the JavaScript. The call from shockwave is still the same:

externalEvent("show_report()")

and I do not have to test the browser. But now the browser script looks like:

function show_report (selfcall) {
// Insert a time delay if called with no 
// argument (from shockwave)
// so that the browser repeats the call in 
// 1/4 of a second
  if (selfcall == null) { 
    setTimeout("show_report(1)", 250); 
  } else {
// This is the task for the browser to do once 
// the delay has passed  
// In this case we spawn a new browser window 
// and then document.write
// to our hearts content.
  
    rep = window.open('', 'report', 'status,toolbar,
    scrollbars, resizable,width=500,height=350');
    rep.document.write('<html><title>Data 
    Report</title></head>');
    rep.document.write('<body bgcolor=#FFFFFF 
    text=#333333>');  
    rep.document.write('<center><font 
    face="verdana,helvetica" size=4>');
    rep.document.write('<b>Data Report</b
    gt;</font><p>');
    
    :
    :
    
    rep.document.close();
  }
}

In essence the first call to this function from Shockwave comes with a null value for the parameter "selfcall" so we use the JavaScript delay function setTimeOut to call the same function again, with a valid paramter, a quarter of a second later. The next time, this event is thus triggered from the browser, not from Shockwave, and we can do what we want to do.

You can see for yourself, by comparing the two versions and looking at the D7 source code availablein Mac or PC format.

And if you are truly interested in why I was fiddling around with this, it was all part of an example Shockwave file written for our Writing HTML tutorial, a new lesson that was set to show how to add shockwave content. Originally, I thought it would be worth showing how Shockwave was useful in that it could communicate with the browser and spawn a dynamic content filled browser window, but between the JavaScript, VBScript, it was more HTML than we wanted to cover.

This original concept is alive for your clicking pleasure.

Back to the Bridge

Capt Lingo:
Lt Sprite, what have we learned?

Lt Sprite:
Captain, all logic points to non trivial solutions to printing from Shockwave. Maybe they can do it over in the KlickOn Empire or with some sort of Romulan/VeruSign Xtra Cloaking Device. I am stumped and starting to get emotional...

Capt Lingo:
Let's not have that. At least we can tell the mothership that they can rest assured in their No Bug Prime Directive. There are none in this star system. Navigator CheckBox, let's take this one to maximum frame speed....

Ok. No more Star Trek. Ever.

But seriously, if you are looking at printing from Shockwave, I would try to look first at the nature of the content to be printed. Try to see if you can get the information somehow into an HTML + GIF/JPEG format in another window and use the browser buttons. This does not help if you are creating some sort of paint/creation tool (drawing with trails or tossing around lots of sprites) but someone more clever than me might have a thought.

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-2024, Director Online. Article content copyright by respective authors.