Saturday, October 3, 2009

Accessing Flex-Object via Javascript

About :: Firebug 'is not a function'-Error
Problem :: Call to function before object is fully loaded
Solution :: Delay call until object available


I wanted to embed a flex-object into a web-page and access it via Javascript with the purpose of setting/getting/managing so called 'local shared objects'.

Everything worked fine during the tests, but in the live environment firebug1 threw me an error telling me that getLSO(), which is a function in my flex-object, is actually not a function. That was weird, because the test- and live-environments were exactly the same (same files, only in different folders).

I have been struggling with this problem almost half a day. And now that the problem is solved, I decided to share my insight.
I give you the code first; only the parts that are relevant to the topic at hand but enough that it sums up to a working example, keeping it clipped and clear. Then I'll describe the problem and the solution.


The Code


The flex-file, lso.mxml, looks essentially like this:

   1:  <?xml version="1.0"?>
   2:  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()" >
   3:  <mx:Script>
   4:  <![CDATA[
   5:  import flash.external.*;
   6:  public var so:SharedObject;
   7:   
   8:  <!-- Determine, which functions will be accessible through external calls. -->
   9:  public function initApp():void {
  10:      if (ExternalInterface.available) {
  11:          ExternalInterface.addCallback("getLSO", getLSO);
  12:      }  
  13:  }
  14:  public function getLSO() :String {
  15:      so = SharedObject.getLocal("label");
  16:      return so.data.text;
  17:  }
  18:  ]]>
  19:  </mx:Script>
  20:  </mx:Application>
Figure 1. lso.mxml

The compiling of this file results in the file lso.swf2, which we embed in the file lso.html, directly after the body-tag, in the following way:

   1:  <body onLoad="initPage();">
   2:    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="" id="FlexObject">
   3:      <param name=movie value="lso.swf">
   4:      <embed play=false swliveconnect="true" name="FlexObject" 
   5:        src="lso.swf" quality=high bgcolor=#FFFFFF 
   6:        width="0" height="0" type="application/x-shockwave-flash" 
   7:        ....>
   8:      </embed >
   9:    </object >
  10:    <!-- Further HTML-Code -->
  11:  </body>
Figure 2. lso.html :: Embedded Flex-bject

The Javascript code to acsess this flex-object and call one of its functions, looks like the following:

   1:  <script type="text/javascript">
   2:  function getFlashMovieObject(movieName)
   3:  {
   4:    if (window.document[movieName]) 
   5:        return window.document[movieName];
   6:    if (navigator.appName.indexOf("Microsoft Internet")==-1) {
   7:      if (document.embeds && document.embeds[movieName])
   8:        return document.embeds[movieName]; 
   9:    }
  10:    else {
  11:      return document.getElementById(movieName);
  12:    }
  13:  }
  14:  function initPage() {
  15:    var userID;
  16:    var flexObject = getFlashMovieObject("FlexObject");
  17:    var lso = flexObject.getLSO();
  18:    if(lso != null) userID = lso;
  19:    else userID = 0;
  20:  }
  21:  </script>
Figure 3. lso.html :: Javascript functions to access Flex-Object



The Problem


As said before, while testing there were no problems. After moving everything into the live-environment and removing all the redundant comments and alerts, firebug threw the following error:


Figure 4. Firebug :: Error Message


I had no clue why the function was suddenly not accessible anymore, since I didn't change anything essential. After some research and some experimenting I found out that the script worked fine when I called alert() prior to getLSO().

To cut a long story short, it turned out that the function getLSO() was invoked before the swf-file was fully loaded, and hence was not available. The alert()-call gave the swf-file enough time to load.



The Solution


The function initPage() was being initiated after the page is fully loaded (see Fig.2, Line1). But apparently that does not ensure that the swf-file in the document is fully loaded as well.
We couldn't find a way to determine the point in time/code where the loading of the flex-object is finished. I thought of calling the initPage() function with a certain time delay. This would be done like this:

   1:  <body  onload="setTimeout('initPage();', 1000);">
   2:  <!-- This will delay the execution for 1 second -->
Figure 5. lso.html :: Fixed Time-Delay

But that would not be an elegant solution, since the loading-time will differ from user to user, and we can't make sure that the time delay is enough for the slowest connection.
We ended up using an additional Javascript function:

   1:  <script language="javascript" type="text/javascript">
   2:  function isLoaded() {
   3:    var fo = getFlashMovieObject("FlexObject");
   4:    try {
   5:      var lo = fo.getLSO();
   6:      initPage();
   7:    }
   8:    catch(err) {
   9:      setTimeout('isLoaded();',200);
  10:    }
  11:  }
  12:  </script>
Figure 6. Time-Delay Until Object is Available

This functions catches the error and, after a pause of 0.2 seconds, calls itself again. As soon as getLSO() is available, initPage() is called.
Now let's replace line 1 in Fig.2 with the following:

   1:  <body onload="isLoaded();">


and we're done...



1 Highly recommended: Firebug for Firefox
2 You may want to download the Flex 3.4 SDK (free), unzip it to a convenient location, and then use the compiler mxmlc.exe in the bin-folder.
3 To format your code for your web-page, you may want to use this Formatter

Friday, February 6, 2009

I like coffee so much that I have tea for breakfast :-)

One man's roller coaster history with coffee:
"I like coffee so much that I have tea for breakfast: The first cup of the day in particular is so good that I’m afraid I won’t be able to properly appreciate it when I am half-asleep. Therefore, I celebrate it two hours later when I am fully conscious".

Coffee

Christoph Niemann - Coffee

One man's roller coaster history with coffee.

Christoph Niemann - Coffee
I must have been 5 when I first discovered the taste of coffee, when I was accidentally given a scoop of coffee ice cream. I was inconsolable: how could grown-ups ruin something as wonderful as ice cream with something as disgusting as coffee?
Christoph Niemann - Coffee
When I was 10 I still hated coffee, but fell in love with the ritual of making coffee
Christoph Niemann - Coffee
At 17 I still suffered from coffee schizophrenia: I loved the concept of coffee, but resented the taste
Christoph Niemann - Coffee
When I was 21
I would brew a gigantic pot of coffee around 9 a.m. to help us get through the day
Christoph Niemann - Coffee
I was focused less on taste and more on quantity and price
Christoph Niemann - Coffee
My inner accountant quickly convinced me to buy one of those little espresso machines
Christoph Niemann - Coffee

Here’s a chart that shows my coffee bias over the years.

Christoph Niemann - Coffee
I order large coffees, but stop drinking when the coffee gets too cold
Christoph Niemann - Coffee
Hot milk greatly improves the taste of coffee
Christoph Niemann - Coffee
When you are craving a beer
coffee is the most disgusting
Christoph Niemann - Coffee
my personal choice: drip coffee with steamed milk
Christoph Niemann - Coffee
 blog it

Tuesday, January 27, 2009

aMap - The Argument Map

seems a cool tool worth checking out.
clipped from www.amap.org.uk

aMap is short for ‘argument map’.  The idea’s very simple - to promote the art of arguing by mapping out complex debates in a simple visual format.

aMap has been developed by a team led by Chris Quigley of Delib (part of Team Rubber) to promote the art of arguing.  Initial concepts were developed as part of an academic project in partnership with Perry Walker from the new economics foundation, and various wonderful brains from the LSE (see below for more info)

The theory

aMaps are based around the same structure as “informal logic” - this is the logic people use to argue in everyday life.  Informal logic has a four-tiered structure:

- Your position (I think . . .) - what you think overall
- Propositions (Because . . .) - reasons that support your position
- Arguments (As . . .) - supporting arguments that back up each of your propositions
- Evidence (Supported by . . .) - supporting evidence to back up your arguments

Create your own aMap
Get involved!
Education
  • Buy
  •  blog it