Archive for the ‘Programming’ Category

Handling Pad Events on the Launchpad Pro

March 19, 2017

Building from the basic understanding of how to affect the Launchpad Pro pads, the next thing we will be interested in doing is taking an action when a pad is pressed.

The API defines a number of callbacks that we can hook into to do interesting things. The one we’re interested in today is:

void app_surface_event(u8 type, u8 index, u8 value);

Like the hal_plot_led API call, the type parameter is either TYPEPAD or TYPESETUP allowing us to know when the setup button is pressed as opposed to a normal pad. Similarly, the index parameter tells us which pad is pressed (and can be ignored when the type parameter is TYPESETUP).

The last parameter, value, is different. When a pad is initially pressed, the app_surface_event callback is invoked with a value 1-127. When the button is released, the app_surface_event is invoked with a value of 0. You can see this in action with this bit of code:

void app_surface_event(u8 type, u8 index, u8 value)
{
    hal_plot_led( TYPEPAD, index, value/2, value/2, value/2) ;
}

It will initially alter the pressed button to be some intensity of white depending on how hard the button was pressed. When the button is released a second event with a value of 0 will be received and the pad will turn off.

It is important to note that without the code above pressing a button has no effect. However, that means we can make it do anything we want it to do… such as sending MIDI data…

Setting the Colors on the Launchpad Pro’s Pads

March 18, 2017

Now that I have figured out how to re-program the firmware on the Launchpad Pro it is time to do something useful with it. There’s multiple parts to what I have in mind but today I experimented with coloring the pads.

There is a nice API for setting the color of a pad. From the app.h include file we find:

void hal_plot_led(u8 type, u8 index, u8 red, u8 green, u8 blue);

The first parameter, type, has two possible values: TYPEPAD and TYPESETUP. TYPEPAD is used to address the round and square pads on the Launchpad Pro. TYPESETUP is used for the recessed setup button in the upper left corner of the device. When using TYPESETUP, the second parameter (index) is ignored and the color of the vertical LED on the bottom edge of the device is altered.

The second parameter, index, is used to address the pads on the device. Check out the Novation documentation for a nice picture of the pad indexing but the summary is this: values 0 to 99 starting from the bottom left corner, moving left to right and moving up. So the “Record Arm” button is index 1, while the “User” button is index 98. Indexes 0, 9, 90 and 99 are not mapped to anything. One might think that index 90 would address the Setup button, but it does not.

The last three parameters are fairly obvious: the red, green and blue values required to render a color. Note that RGB values are often expressed as values 0-255. The Launchpad Pro uses 0-63. Therefore, if you use a site like http://htmlcolorcodes.com/color-names/ to find colors you will need to divide the individual values by 4 for similar colors on the Launchpad Pro. RGB(0,0,0) normally corresponds with black. But for our Launchpad, it turns the pad off.

With the API well in hand I’m going to need to create visual differences between a button that’s active and a button that’s available but not active, and a button that’s off or unavailable. Certainly, RGB(0,0,0) will suffice for off/unavailable but how should we represent available but not active? Working with good strong colors like RGB(63,0,0) and RGB(32,0,32) I experimentally determined that dividing each value by 4 or 8 yields a clear enough difference between the full color (active) and reduced color (available) but still allows for a color that properly represents the full/active color.  So, for a nice purple with active/full as RGB(32,0,32) we can use RGB(8,0,8) for the inactive/available situations.

Instructions for Launchpad Pro Firmware Development

March 11, 2017

A bit ago while I was answering a question in the Facebook Circuit Owners group I mentioned that I’d not been able to figure out how to program my Launchpad Pro. It didn’t sit well with me after I wrote that statement. I’ve been a software developer for a long time and embedded systems is my original area of specialty.  What could possibly be that hard about it? So, I went back for a second (actually third) look at what it took…

The original release of the Launchpad Pro celebrated the open platform that Novation was providing as part of the product release. The primary documentation for working with that platform is at https://github.com/dvhdr/launchpad-pro. Turns out, while there’s a fair bit of documentation there, the reality is it is just barely enough documentation to get it done, and it is not quite right (at least not on the master branch). I’ve determined there’s a couple of other branches, one of which has the major corrections in it that I make below, but none with fully detailed instructions.

The end result was that I was able to get some firmware into my Launchpad Pro.  But, it wasn’t perfectly straightforward.  So, I’ve decided to provide some updated and more detailed instructions.  I do presume some reasonable knowledge of software development but hopefully this helps the Novation Launchpad Pro community.

Prerequisites

These instructions are MS Windows biased, but I think they should translate to MacOS easily enough.

You will need the following tools installed and ready to go:

  • A git client
    • git will need to be in your command line path
  • An ssh client (e.g.: part of MinGW)
    • ssh will need to be in your command line path
  • Vagrant
  • VirtualBox
  • A MIDI tool that can send sys-ex (e.g. MIDI-OX)

My personal laptop has Win10 and 8G of RAM on it and for me it is just barely sufficient. I really can’t run much other than the VirtualBox and MIDI-OX at the same time.

First Steps

  • Find or create a folder to work in
  • Open a command prompt in that work folder
  • Execute:
git clone --recursive https://github.com/dvhdr/launchpad-pro.git
  • This creates a launchpad-pro folder in the that work folder

You now have the basic Launchpad Pro files on your computer.

However, the Ubuntu image that is going to be used in this setup has changed since the code was uploaded to github. Therefore, we need to make a small change to one of the files downloaded.

  • Move to the launchpad-pro folder and open the Vagrantfile in a text editor
  • Find the line that starts with ‘config.vm.box’
  • Change it as follows, Before:
config.vm.box = "drmyersii/ubuntu-desktop-14.04-x64"
  • After
config.vm.box = "drm2/ubuntu-14.04-desktop-x64"

Novation support graciously point me at the new location when I asked about why there was a problem originally (and this nicely agrees with the last change on the raw-ADC branch that I found after I asked…).

VM Setup

  • Using your command prompt, move into the launchpad-pro folder
  • Execute:
 vagrant up

Let vagrant complete its work before moving on or logging into the VM.

  • Log you into the Ubuntu VirtualBox instance, execute:
 vagrant ssh
  • Execute:
make

The make is going to run for a good bit of time but we can do a couple of things while it is doing its thing.

Ubuntu/Eclipse Setup

The new Ubuntu image that we are using does not include an Eclipse installation (despite what the original docs say). But, it is not hard to set up.

  • Switch over to the VirtualBox instance and log into VirtualBox
    • It should already be running at this point with the vagrant user prompting for the password – just use “vagrant” as it the password
    • You may get prompted to update. I didn’t, but it is something that should be done soon to ensure all of the security patches are installed if you’re going to use this for anything beyond Launchpad Pro development
  • On the left sidebar there is an icon that looks something like an orange portfolio with an A on it. It is the Ubuntu Software Center. Launch it.
  • In the upper right of the Software Center, there’s a search field. Type in “eclipse” and look for “Eclipse Integrated Development Environment”.
  • Click on that row and there should be an “install” button. Install it.
    • This will take a little bit of time.
    • At the end of the install you will be prompted to authenticate the installation – just use vagrant password again.
    • The install button eventually change to “remove” (don’t remove it)
    • Note that there is now a new Eclipse icon in the left sidebar.
  • Launch Eclipse
    • If prompted for a workspace, accept the default and check the box to make it the default.

Once Eclipse shows you the main window we need to do a bit of configuration in Eclipse

  • Go to the Help/Install New Software… menu
    • I’m not sure what GUI Ubuntu is using these days but they hide the standard toolbar in the top status bar. Simply move your mouse up to the top bar next to the “Eclipse” text and the menu will reveal itself. Yes, I agree, really questionable UX…
  • Using the combobox to the immediate left of the “Add…” button, pick “Indigo Update Site”
  • Scroll down the list to the Programming Languages area and expand the list.
  • Select the “C/C++ Development Tools”
  • Leave the defaults alone from here out and click Next as many times as necessary until you can click Finish, which you also click.
    • You may get prompted to acknowledge licensing agreements and what not… do what you need to do.
  • When it is finished you will be prompted to restart Eclipse. Don’t. Instead, shut Eclipse down completely
    • This is just for the ease of the next step. Normally the restart is just fine.

We need to go back to our ssh session and check on the progress of our make command. When it is done we can switch back to the VirtualBox.

Pulling in the Source Tree

We now have a development environment for building our Launchpad Pro firmware but we need to pull the source code into Eclipse.

  • Launch Eclipse
  • File, Import…
  • Find C/C++ in the list and expand it.
  • Click on “Existing code as Makefile project” and then click “Next”.

It turns out that the launchpad-pro folder in your main computer’s work  folder is mapped into the VirtualBox’s /vagrant folder.

  • Put “/vagrant” in the “Existing code location” text field
  • Set the project name to whatever you want (it defaults to “vagrant” which is probably fine in some situations but isn’t for ours IMO)
  • Leave the other things alone and click “Finish”
    • If you have not closed the “Welcome” tab, go ahead and do so.

Building the Default Code

We now have a project in the upper left of Eclipse with the name we provided in the previous dialog. Time to build this thing:

  • Right click on the project and select “Clean Project”
  • Right click on the project and select “Build Project”

There is now a launchpad_pro.syx file in the launchpad-pro/build folder.

Upload to the Launchpad Pro

Finally, we have a binary image to upload into the Launchpad Pro. Ensure your Launchpad is plugged into your computer (and in bootloader mode) and using your SysEx tool of choice (I use MIDI-OX) to upload it (from <your-work-folder>\launchpad-pro\build\launchpad_pro.syx) and restart the Launchpad Pro.

You might have to hit the setup button to start the new firmware but it is there and running.

Useful References

Problems uploading a new GAE app

May 29, 2015

I was working on a new project – I haven’t done a Google App Engine project in a while.  So I get it working… it finally passed all of my local integration testing.  Now I was ready to upload into GAE (1.9.19 at the time of this writing).

So, first, I made sure I’d created the application in the GAE project console.

then, from Eclipse (Kepler SR2), since I use Maven all the time:

mvn appengine:update

Hmmm:

"Either the access code is invalid or the OAuth token is revoked.Details: invalid_grant"

So it is using Oauth2 to authorize the upload, except it looks like my details are out of date. No amount of logging in or out of Eclipse fixed it.

Finally, I found a post out on the GAE Issues site that said to delete the .appcfg_oauth2_tokens_java file.  After a bit of digging, I had to delete the .appcfg_oauth2_tokens_java in the c:\Users\MyUser folder.

Then I re-run my maven command:

[INFO] Running --oauth2 update C:\Users\...-0.0.1-SNAPSHOT

A which point my default browser is popped up, I have to agree to some things, I do and then am presented with a simple page with a code to copy and past “into my application”.

Which application?
My GAE application?
What in the world?

I happen to flip back to Eclipse and see the console:

Please enter code:

Can I even type into that console? I think I can…

So I do, and hit <enter>

Magically, it starts working…

WordPress 4.0 Menu Behavior Change

September 9, 2014

I recently upgraded a site to the new WordPress 4.0.  As usual, there were no noticeable hiccups… until I looked at my main navigation more closely a couple of days later.  I have a couple menus defined but one called “Primary Navigation” – a pretty typical set up.  I’ve written my own theme, as I have for many, many sites and have used the same menu code for as long as I can remember:

// after_setup_theme callback
register_nav_menus( array( 'primary' => __( 'Primary Navigation',
           'somethingidontrememberwhyitisshereandcantfinditinthedocs' ), ) );

// in template menu 
wp_nav_menu( array('menu' => 'Primary Navigation' ))

This was causing a different menu to show up in the location of the wp_nav_menu.

A quick web search showed I wasn’t the only one running into this as well as no obvious indicators of changes in the behavior of wp_nav_menu. There was a hint, and I followed it, that changing to the actual name of the menu would fix this – and it did. My code now reads:

wp_nav_menu( array('menu' => 'Main Navigation' ))

“Main Navigation” is the actual name of the menu I defined inside of my site.

This doesn’t seem quite right having to know the exact menu name instead of allowing a menu to be abstractly identified and then mapped.

I also tried:

  • switching to using register_nav_menu
  • switching to using the menu identifier/slug “primary”
    • WordPress codex for wp_nav_menu says the menu parameter “accepts (matching in order) id, slug, name”
    • Reminder that the second parameter for register_nav_menu is a “description” not a “name”

Only using the actual menu name worked. 

Integration Testing, Maven, and GAE

September 8, 2013

I’m starting to use REST-assured for integration testing my REST APIs.  It provides a nice clean way of writing integration tests and, of course, I’d like them to be run automatically.

Maven Integration Tests

While unit testing is pretty much ready to go out of the box in Maven, integration testing isn’t.  It is not too hard but there’s a couple of things that need to be done. First, you have to pull Fail Safe into Maven with:
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>${maven.failsafe.version}</version>
  <executions>
    <execution>
      <goals>
        <goal>integration-test</goal>
        <goal>verify</goal>
      </goals>
    </execution>
  </executions>
</plugin>
Now, when you execute the maven verify goal, test classes of the pattern IT*.java or *IT.java are automatically executed. This works well until you realize that real integration tests require a bit more setup than unit tests do.
 

GAE Dev Server and Integration Testing

In particular, I want the GAE dev server running before the integration tests run.  So all we should have to do is get the GAE plug-in to execute the devserver_start goal during pre-integration-test and the devserver_stop goal to execute during post-integration-test.
<plugin>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-maven-plugin</artifactId>
  <version>${appengine.target.version}</version>
  <executions>
    <execution>
      <id>start-gae</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>devserver_start</goal>
      </goals>
    </execution>
    <execution>
      <id>stop-gae</id>
      <phase>post-integration-test</phase>
      <goals>
        <goal>devserver_stop</goal>
      </goals>
    </execution>
  </executions>
</plugin>
Now, executing mvn verify will run your integration tests once your unit tests pass and the GAE dev server should start and stop around the integration tests as well.

Adding Jersey to a GAE Maven Project

September 3, 2013

Continuing from my post yesterday, Getting Maven, GAE, and Eclipse Working Together, I’m adding Jersey to my test GAE project to finish proving the Maven integration and test that I can get my favorite REST library up and running both locally and as a full fledged GAE project.

Adding Jersey

Jersey is one of the few “magical” (read: annotation) libraries I use.  I really don’t like magic in my code.  It is great when it works, and miserable when it fails… and it always fails at inopportune moments…

We start by adding a new dependency to the pom file:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.2</version>
</dependency>

The artifactId started out as “jersey-container-servlet” but since GAE only supports the Servlet 2.5 spec we follow the comment and append “-core”.

Next, we quickly write a test Jersey class:

package mavengaetestproject.mavengaetestproject;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/jerseyws")
public class TestJerseyWS {

    @GET
    @Path("/test")
    public String testMethod() {
        return "this is a test";
    }
}

And then update the web.xml:

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>mavengaetestproject.mavengaetestproject</param-value>
    </init-param>
    <init-param>
        <!-- speed up initial Jersey loading by deactivating WADL -->
        <param-name>jersey.config.server.wadl.disableWadl</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/context/*</url-pattern>
</servlet-mapping>

Finally, run the appengine:devserver maven target, and once the server is up and running open a browser to http://localhost:8080/context/jerseyws/test ; You should see the “this is a test” message.

And there we have it: Maven, Eclipse, GAE and Jersey all working nicely together.

Deploying to the GAE

That’s all well and good, but I want this thing actually in the cloud, not on a dev server.  It may seem obvious, but I failed to do this first: you need to create your project in your GAE account.  You might need to update the application tag in the webapp/WEB-INF/appengine-web.xml to match the GAE application identifier.

At this point you should be able to run the Maven appengine:update target.  If working from inside Eclipse, it is probably easier to log into Google beforehand, AND you WILL need to configure the Eclipse Run As configuration for UpdateApplication to use the external Maven environment (see the other post if you need a refresher on why).  If running Maven from a command line, it will pop open your default web browser, prompt you to log in, and then provide a code to put back into your console/shell to allow it to continue.  For me, it worked cleanly from both environments (once I had the Maven config corrected in Eclipse) and my REST servlet was up and running easily.

At this point I’ve completed everything I intended to accomplish.  It took a little longer than planned and with the mish-mash of tech that didn’t always line up correctly I hope this helps others out.

Getting Maven, GAE, and Eclipse Working Together

September 3, 2013

Today, we turn to some “fun” making Maven, Google App Engine, and Eclipse work together nicely.  I like Eclipse I lot.  I know its not everyone’s favorite, but it is my choice of IDE.  Similarly, I know Maven isn’t everyones… ok, its no one’s favorite, but it does solve a number of problems quite well and I peacefully co-exist with it right now.  Maven and Eclipse are enough to make people complain loudly to me at work, but today I wanted to build a GAE project, in Eclipse, and using Maven to manage my dependencies (I’m going to have a number on this little project of mine and its good for what I need).

Google certainly has a nice Eclipse plugin for managing GWT and GAE projects, but it doesn’t conform to Maven conventions.  After trying several times to coerce a GAE project into a Maven structure I gave up and did some searching.  I found https://developers.google.com/appengine/docs/java/tools/maven to be generally useful but it required some modifications for the current versions of things.  Here is what I had to do to get everything working together:

Steps

Starting Environment

  • Eclipse Java EE IDE for Web Developers, Version: Kepler Release, Build id: 20130614-0229
  • Maven 3.1.0 installed outside of Eclipse (in my devtools folder if it matters)
  • JDK 1.7.0_25
  • Windows 7

Target Implementation

A basic REST servlet using:

  • GAE 1.8.3
  • Jersey 2.2
  • Final WAR deployed into my GAE account

Step 1: Add the External Maven to Eclipse

I didn’t realize it was going to be important to have an external Maven installation but it turns out that it is (reasons later).  In the Eclipse Preferences, search for Maven, and look for the Installations tree node.  Add a new installation by browsing for your devtools equivalent location.  Once added, make sure the checkbox is on the External one.  You may also need to update where your settings.xml is pointing both here in the Installations, and/or in the User Settings.  I have both pointing at the settings.xml in the external maven configuration folder.

Step 2: Update Eclipse Maven with Remote Archetype catalog

In that same Maven area above, look for the Archetypes tree node.  Add a remote catalog providing http://repo1.maven.org/maven2/archetype-catalog.xml in the catalog file box (name it if you want, I didn’t).

Step 3: Create the project stub

Using the Eclipse project wizard create a new Maven Project.  The second step in the wizard selects an archetype, look for com.google.appengine.archetypes:skeleton-archetype.  Select your group and artifact ids (I choose “mavengaetestproject” for both) and it will create a nice stub GAE project. Note that the artifact id becomes the Eclipse project name. That annoys me because my Eclipse project names don’t always match my maven artifact names, but considering what we’re trying to accomplish, I’ll let this one slide.  If I’ve missed where I can name the project, please let me know.

Step 4: Fix up the default pom.xml

The default pom is set up for GAE version 1.7.5 so change the appengine.target.version property to 1.8.3 to pull in the latest GAE environment.

Step 5: Test out the basic war

One of the nice things about the skeleton-archetype is that it comes with appengine-maven-plugin already set up.  That gives us some maven goals that help make up for the lack of the GAE Eclipse plugin.

Right clicking on the project node, Run As, Maven Build…, set the goal to be appengine:devserver and then run it.

Boom!

As of the time of this writing there’s a problem:

[ERROR] Failed to execute goal com.google.appengine:appengine-maven-plugin:1.8.3:devserver (default-cli) on project mavengaetestproject: The plugin com.google.appengine:appengine-maven-plugin:1.8.3 requires Maven version 3.1.0 -> [Help 1]

Eclipse Kepler is running Maven 3.0.4 internally, and in one of those warning messages I never read on the Maven Installations configuration dialog it says “Note: Embedded runtime always used for dependency resolution…”.  Basically, by default, any Run As, Maven command is using Eclipse’s embedded Maven configuration.

This can be fixed by going into the Run As, Run Configurations… dialog and searching for DevAppServer, click on it. At the bottom there is a Maven Runtime combobox, select the external Maven entry.  Apply and then run.  This time it should work better.

Open a browser to http://localhost:8080/_ah/admin to prove that its working.

One annoying side effect: killing the process inside the Eclipse console doesn’t seem to kill the real process so I have to manually kill it when I’m done testing.  Any suggestions on this would be welcome.

Conclusions

At this point we have a working GAE project that does nothing.  But, it is Maven-ized and working in Eclipse.  In the next post, I’ll pull Jersey in and make sure Maven and Jersey and everything are all working correctly.

Striving for Unit Tests with 100% Coverage

October 9, 2010

I’ve found Emma to provide some real insight into what is actually getting tested.  While trying to bolster a suite to 100% coverage that I had though was pretty good already (it was ~85%) it showed me an interesting problem.

I have a method that looked something like this:

public MyMessage parseXMLtoMyMessage( final Reader reader ) {
    MyMessage msg = null ;
    try {
        final JAXBContext context = JAXBContext.newInstance(MyMessage.class);
        final Unmarshaller u = context.createUnmarshaller();
        final SAXSource src = new SAXSource( new InputSource(reader) );
        msg = (MyMessage) u.unmarshal(src);
    } catch (JAXBException e) {
        e.printStackTrace(); // yes I do better exception handling than this...
    return msg ;
}

I can pass in any kind of  Reader I want to for my tests and the JAXB2 code is isolated in one area of responsibility.  This worked great until I found out the real  XML was coming in with a namespace (that fact is not in the provided message spec) and that namespace isn’t reachable… nice.

So, I needed to disable namespace checking.  A quick bit of research turns the method into the following (changes noted in red):
public MyMessage parseXMLtoMyMessage( final Reader reader ) {
    MyMessage msg = null ;
    try {
        final JAXBContext context = JAXBContext.newInstance(MyMessage.class);
        final Unmarshaller u = context.createUnmarshaller();
        final XMLReader xmlReader = XMLReaderFactory.createXMLReader();
        xmlReader.setFeature("http://xml.org/sax/features/namespaces", false) ;
        final SAXSource src = new SAXSource( xmlReader, new InputSource(reader) );
        msg = (MyMessage) u.unmarshal(src);
    } catch (JAXBException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    }
    return msg ;
}

Emma had originally reported that there are no test paths through the exceptions.  OK, it is pretty easy to force the JAXBException by sending in an incomplete or otherwise improperly formatted XML stream. However, because of the need for the XMLReader to disable namespace checking I now have a SAXException that is generated completely internally to the parse method.  There’s no way to mock out the XMLReader without injecting it.  My options are:

  1. I can provide an injection point.  Sorry, no – I don’t think any client to the method should have to know about the namespace problem and exposing the XMLReader in any way amounts to that.
  2. I can alter the system property “org.xml.sax.driver” to point at something invalid,.  Unfortunately, also no.  That wrecks all other tests since I can’t return it to its original null value after the test and the tests shouldn’t be order dependent (i.e. try to make this the last test… of the entire suite).

So here I sit, unwilling to provide an injection point for XMLReader and unable to write a test to cover a specific branch.  I’m open to suggestions.

Applets, Flex and JavaScript

April 10, 2010

I’ve been doing web programming for a very long time.  In the past I’ve done large Swing clients in applets (long before Swing was part of the standard JDK) and lately I’ve been using Adobe Flex to build Flash and AIR applications.  I enjoy how the Flex framework and structure makes Flash work for a mere programmer whereas time-line programming never really worked for me.  All along the way there’s been JavaScript; a misnamed language that has nothing to do with Java and as many platform dependency problems as CSS and HTML.  Throughout my career I’ve carefully avoided its annoyances.  I suppose that’s what’s previously pushed me at applets and Flash – they are technologies that have let me avoid JavaScript.

Recently, I had to develop a prototype that revolved around Google Maps.  One of the requirements was that it had to work on the iPhone.  As we all know, the iPhone (currently) does not support Flash.  So, since no one was jumping up to go buy me an iPhone and a Mac to build my app on, my only real option was JavaScript.  The prototyping went well – the project has been approved to be developed for real.  While I still don’t prefer JavaScript (the faked out object definitions and prolific use of anonymous functions is just ugly) I found the GoogleMaps API to be well designed and the JQuery library to be nearly redeeming of JavaScript in general.

If JavaScript had features like JQuery back in the beginning I probably wouldn’t have had to endure all the craziness of deploying signed applets.  I’ve often lamented the lack of mathematical expressions in CSS.  I understand why it is not there, but there have been so many times I wanted to size something as 100% minus  “whatever that width over there is”… now I can.

I like having good tools available to me so that I have the maximum amount of flexibility when I need to solve a problem.  I’m not throwing away my Flex anytime soon (though I did toss applets away a good while ago), if you’ve been like me, avoiding JavaScript at almost any cost, you might want to check out JQuery. It makes JavaScript programming much more reasonable.