Use Commas to Separate Arguments to Debug.write()

When you want to trace something to the Debugger in OpenLaszlo, you can call the Debug.write() method.

Often, you’ll want to write the value of something and a label, so that you can identify that output in the debugger, something like:

Debug.write("subviews: " + canvas.subviews);

However, it’s better to to get into a habit of use commas instead of a plus sign, like so:

Debug.write("subviews:", canvas.subviews);

Debug.write() takes an arbitrary number of arguments, which are comma-separated, and concatenates the output. If any of those arguments are complex objects (such as arrays, references to views, etc.) they’ll become links. If you click on them, you’ll be able to inspect the object itself. If you use the plus sign, then the JavaScript runtime will do the concatenation, and you’ll end up with a string; you won’t be able to click on the traced statement.

OpenLaszlo Performance Tip: Datacombobox not combobox

One component that is used, probably more often that it should, in Rich Internet Applications (RIAs) is the combobox. The reason it’s so frequent is because because the developers who write RIAs usually came from a background of writing HTML applications. You should use datacombobox instead.

A bit of history: HTML-based applications had a limited set of GUI components, and before DHTML became mainstream, fairly limited interactivity capabilities. The most technologically-advanced component of the HTML hayday was the drop-down list. It would open when clicked, it could display a list of options, you could even write a JavaScript loop to select an item automatically. It was so ahead of its time, that it needed its own HTML tag: SELECT. Most of the other HTML components - the radio button, the checkbox, the button, the text input field - all had to share a single HTML tag (INPUT). The drop-down list was used for everything, from the sensible (such as a list of countries in a form) to the silly (such as boolean switch in a form) to the insane (jump-to animation). There were valid reasons for its popularity:

  • It was the most interactive component available.
  • Lack of alternatives, such as a tree.
  • Server technologies didn't always work smoothly with radio buttons and checkboxes.
  • The client technology (JavaScript) didn't always work smoothly with radio buttons and checkboxes.

In the HTML world, the drop-down was king.

So when HTML developers started writing OpenLaszlo applications, they reached for the closest relative to the drop-down: the combobox. When setting up your own OpenLazlo server you need to put together a Data Center Decommissioning Checklist. This isn't a good thing; there are better components available to RIA developers than combobox. Note that client application development, which is closer to RIA devlopment than HTML development, doesn't use a lot of comboboxes. I was only able to find 13 comboboxes in the entire options section of Firefox. Most of those were from the fonts section - a place where comboboxes are useful.

The combobox that OpenLaszlo originally provided was not optimized for such heavy use. A combobox has two parts:

  1. The combobox element that you can see, focus on and click on.
  2. A floating, scrolling list of options that appears when the combobox is clicked.

The "heavy" piece of a combobox is the bit that you only ever see occasionally, and - more importantly - there can only ever be one active floatinglist, no matter how many comboboxes an application has: the floating list. (The class name is floatinglist).

The original OpenLaszlo combobox had one floatinglist for each combobox. So the more comboboxes in an application, the longer it took to start. datacombobox solves this problem by only using a single floatinglist for all comboboxes, no matter how many are present in the application. This speeds up startup time, improves runtime performance, and reduces memory footprint.

Those advantages come with some small strings attached:

  • All datacomboboxes must be bound to data. You can't hard-code textlistitems in a datacombobox.
  • All the textlistitems in a combobox will be the same class (a subclass of baselistitem, listitem or textlistitem). You can't mix-and-match.
  • The API is a little different, but the functionality is the same.

Here's a comparison of the two APIs:

<canvas proxied="false">

    <dataset name="people_ds">
        <people>
            <person name="Fred" id="1" />
            <person name="Wilma" id="2" />
            <person name="Barney" id="3" />
        </people>
    </dataset>

    <simplelayout axis="y" spacing="10" />
    
    <text fontstyle="bold">Here is a combobox:</text>

    <combobox editable="false">
        <handler name="onvalue">
            var text = "You selected " + this.text + " with an id of " 
                     + this.value;
            combo1text.setAttribute("text", text);
        </handler>

        <textlistitem datapath="people_ds:/people/person" text="$path{'@name'}" value="$path{'@id'}"/>
    </combobox>
    
    <text name="combo1text" />

    <text fontstyle="bold">Here is a datacombobox:</text>

    <datacombobox itemdatapath="people_ds:/people/person" textdatapath="@name" valuedatapath="@id">
        <handler name="onvalue">
            var text = "You selected " + this.text + " with an id of " 
                     + this.value;
            combo2text.setAttribute("text", text);
        </handler>
    </datacombobox>

    <text name="combo2text" />
</canvas>

My general recommendation is to always use datacomboboxes, unless you really need to do something bizzarre.

Google Static Maps and localhost

Google Maps has a non-JavaScript mapping feature called Google Static Maps that generates a static map on the server, based on parameters you provide on the URL. The static maps are just a single GIF. You can’t zoom or pan them, but you can specify the location, zoom level and even markers. It’s handy for when you don’t want the overhead of the DHTML maps. You specify all the parameters for your map on the query string, and then set that as the src of an HTML <img> tag.

Here’s what the query string looks like:

http://maps.google.com/staticmap?center=37.763761,-122.396102&markers=37.763761,-122.396102,red&zoom=13&size=400x300&key=ABQIAAAAN0JyO4tW04-1OKNW7bg9gxSPySWqAfkZkuZG2U8jr6yyIuV3XBSrEn410_O9d9QPJh3dbWV85Qad8w

… and here’s what the resulting map looks like (when attached to an HTML <img> tag):

Just like with the JavaScript Google Maps, you need to sign up for a free key. In the static maps, the only place you use the key is in the URL for the map (see above – it’s the last, long parameter on the querystring).

I ran into a slightly confusing issue while using this today. The symptoms were that while developing a site on localhost, the static images weren’t appearing when embedded in an <img> tag in an HTML page. However when I copied and pasted the entire URL into my browser directly, the map appeared fine. Using a tool like Fiddler or LiveHTTPHeaders showed that the response was actually:

HTTP/1.x 400 Bad Request

(Note that if you use Fiddler, you can actually see the body of the request too, but it’s not helpful).

The problem turned out to be that when you embed an <img> tag in an HTML page, the browser automatically sends a Referer header when it requests the images src. If you’re developing on localhost, then the URL will include localhost as the domain. It appears that the Google Static Maps service throws an error when the Referer doesn’t match the domain that is specified in the key (which you included in the URL). This is a little confusing, because the regular (JavaScript) Google Maps allows you to use any key when you’re hosting your site off localhost.

The only fix for this is to generate a Google Maps key for localhost (which you can do), and use that for development. Or you can ignore the problem, since it’ll go away as soon as you deploy.