Thoughts on web development, tech, and life.

Category: Web development (Page 3 of 3)

I’m speaking at OSCON in July

Now that the OSCON 07 site is up, I guess it’s official–for the second year in a row, I’ve been selected to give a talk at O’Reilly’s annual Open Source Convention (OSCON) in Portland, OR from July 23-27.

The title of my talk this year is “High-Performance JavaScript: Why Everything You’ve Been Taught is Wrong“. I’m basically going to share all the secrets we learned the hard way while building Plaxo Online 3.0 and trying to make it fast. It turns out that so many of the techniques and axioms used by the AJAX community have serious performance implications, so I’ll explain how we discovered and worked around them. I’ll also argue that a different design philosophy is necessary if performance is truly a goal–one in which every line of code you write has a cost that needs to be justified and in which you assume the platform (web browser) is fragile and brittle rather than infinite and omnipotent. In other words, you have to stop asking “what can I make the browser do?” and instead ask “what should I make it do?”.

In the last few years I’ve been going to a lot of conferences on behalf of Plaxo, and OSCON is easily my favorite of them all. (Thanks again Terry for turning me on to it!) I think it’s because there’s a higher signal-to-noise ratio of people attending who are really building and influencing things to those that are just attending to figure out what all the latest hype is about. It doesn’t feel corporate; it feels like a bunch of smart hackers trying to figure things out together and share what they’ve learned. It’s what many conferences aspire to but so rarely achieve these days. Plus Portland is a really fun town to spend a week in (last year I went to the rose garden, Japanese tea garden, a custom martini bar, and not one but two Dresden Dolls shows).

I can’t wait. See you there!

Handling GeoCoding Errors From Yahoo Maps

One of the best features of Yahoo’s AJAX Maps API is its ability to geo-code full-text mailing addresses into lat/long on-the-fly, so you can say for instance “draw a map of 1300 Crittenden Lane, Mountain View, CA 94043“. (By now, Google and MSFT also offer geocoding, but Yahoo had it way earlier because they embraced JSON-P at a time when everyone else was still scratching their heads).

Yahoo does a pretty good job of geocoding addresses even if the format is a bit weird or some the info is missing, but of course they can’t always figure it out, especially if the address is garbage to start with. Their API indicates (somewhat cryptically) that you can capture an event when geocoding completes, but they don’t tell you what data you get or how to deal with it. Since there doesn’t appear to be much discussion of this on the Internets, I thought I’d provide the answer here for the record.

When creating a YMap, you can register a callback function to get triggered every time geocoding completes, like so:

var map = new YMap( ”¦ );
YEvent.Capture(map, EventsList.onEndGeoCode, myCallback);
”¦
function myCallback(resultObj) { ”¦ }

Yahoo’s API claims that you can also pass an optional private context object, but as far as I can tell they never send it back to you. Of course you can always use a closure around your callback function to achieve the same thing.

Now for the part they don’t tell you: your callback is called with a single resultObj argument. You can figure out the contents of this argument by just writing your callback function to take an argument and then writing console.dir(resultObj) to print out its full nested structure in the unbelievably useful Firebug (Joe, you’re my hero!). Here’s what you’ll see:

var resultObj = {
  success: 1, /* 1 for success, 0 for failure */
  /* Original address you tried to geo-code */
  Address: “1300 Crittenden Lane Mountain View, CA 94043”³,
  GeoPoint: {
    /* This is a YGeoPoint, which also has a bunch of functions you can call */
    Lat: 37.424663,
    Long: -122.07248
  },
  ThisMap: { /* reference to the YMap */ }
};

So in your callback function you just test for resultObj.success, and if the geocoding failed, you can show an appropriate error message.

One trick I found for showing an error message is that you can embed a hidden div with an error message inside the map-holder div you pass to the YMap constructor, and YMap won’t get rid of it. If you use absolute positioning and give it a z-index, you can then show it when geocoding fails and get a nice “Map not available” right where the map would normally be.

Here’s a working example of handling geocoding and showing an error message. Thanks Yahoo! for the great API, and hopefully some of this info will find its way into the next rev of your API docs. :)

PS: Special thanks to Mark Jen for finding me a decent code-writing plug-in for Windows Live Writer! Boy did I struggle with getting WordPress not to mangle my code in the eval post!

Fixing eval() to use global scope in IE

[Note: This is the first in what I hope will become a series of technical articles on the lessons I’ve learned “from the trenches” of my web development work at Plaxo. Non-techy readers are invited to skip any articles categorized under “Web development”. :)]

Update: This article has been picked up by Ajaxian, and it’s sparked an interesting discussion there. 

At Plaxo I’ve been working on a new (soon to be released) version of Plaxo Online (our web-based address book, calendar, and more) that is very ambitious both technically and in terms of user experience. We’re currently deep into performance tuning and bug fixing, and we’ve already learned a lot of interesting things, most of which I hope to share on this blog. The first lesson is how to correctly eval() code in the global scope (e.g. so functions you define inside the eval’d code can be used outside).

When we built the first version of the new site, we combined all the JavaScript into one giant file as part of our deployment process. The total codebase was huge and it had the predictable effect that initial page-load time was terrible because the user’s CPU was solidly spiked for several seconds while the poor browser choked through the massive amount of code it had to parse. So we started loading a lot of our code on-demand (packaging it into several logical chunks of related files and using dojo’s package/loader system to pull in the code as needed).

All was well until we started defining global functions in the loaded JavaScript. (We did this mainly for event handler code so we didn’t have to spend time walking the DOM and finding all the clickable nodes after injecting innerHTML to hook them up to the right scoped functions.) In Firefox, everything kept working fine, but in IE, none of the global functions were callable outside of the module being loaded on-demand (you would get a typically cryptic IE error that in effect said those global functions weren’t defined). It seemed clear that when the code being loaded got eval’d, the functions weren’t making it into the global scope of the page in IE. What was unclear was how to fix this.

Here’s a simplified version of the situation we faced:

function loadMyFuncModule() {
  // imagine this was loaded via XHR/etc
  var code = 'function myFunc() { alert("myFunc"); }';
  return eval(code); // doesn't work in FF or IE
}

function runApp() {
  loadMyFuncModule(); // load extra code "on demand"
  myFunc(); // execute newly loaded code
}

The thing to note above is that just calling eval() doesn’t stick the code in global scope in either browser. Dojo’s loader code solves this in Firefox by creating a dj_global variable that points to the global scope and then calling eval on dj_global if possible:

function loadMyFuncModule() {
  // imagine this was loaded via XHR/etc
  var code = 'function myFunc() { alert("myFunc"); }';
  var dj_global = this; // global scope object
  return dj_global.eval ? dj_global.eval(code) : eval(code);
}

This works in Firefox but not in IE (eval is not an object method in IE). So what to do? The answer turns out to be that you can use a proprietary IE method window.execScript to eval code in the global scope (thanks to Ryan “Roger” Moore on our team for figuring this out). The only thing to note about execScript is that it does NOT return any value (unlike eval). However when we’re just loading code on-demand, we aren’t returning anything so this doesn’t matter.

The final working code looks like this:

function loadMyFuncModule() {
  var dj_global = this; // global scope reference
  if (window.execScript) {
    window.execScript(code); // eval in global scope for IE
    return null; // execScript doesn't return anything
  }
  return dj_global.eval ? dj_global.eval(code) : eval(code);
}

function runApp() {
  loadMyFuncModule(); // load extra code "on demand"
  myFunc(); // execute newly loaded code
}

And once again all is well in the world. Hopefully this is the type of thing that will be hidden under the hood in future versions of dojo and similar frameworks, but for the time being it may well impact you if you’re loading code on demand. So may this article save you much time scratching you head and swearing at IE. 🙂

(PS: Having found the magic term execScript, I was then able to find some related articles on this topic by Dean Edwards and Jeff Watkins. However much of the details are buried in the comments, so I hope this article will increase both the findability and conciseness of this information).

Mashup University Talk

Smarten Up Your Address Book with a Plaxo Mashup
Mashup University (part of Mashup Camp 2)
Mountain View, CA (Computer History Museum)
July 12, 2006

Download PPT (1.7MB)

Watch the complete video of my talk (QT, 78MB)

Plaxo sponsored me to give a talk at the beginning of MashupCamp2 (alongside speakers from Microsoft, AOL, and Intel) during its new “Mashup University” section. I talked about the Plaxo widget and our APIs and why they’re a useful ingredient for many sites. MashupCamp itself was also great fun, and it made me a strong believer in the style of un-conferences (where the schedule is formed ad-hoc by the participants when the conference starts), something I’ve since used at Plaxo to cut down on scheduling meetings. Rather than trying to get on everyone’s calendar, we just reserve Tuesday afternoons for an internal unconference we call Meataxo (yes, the spelling is intentional–we had to do something to make the idea of a meeting marathon sound fun :)).

I’ve covered my talk at MashupU in more detail on Plaxo’s blog, and Joe “Duck” Hunkins also wrote a great summary.

Cross-Site Ajax (OSCON 2006)

Cross-Site Ajax: Challenges and Techniques for Building Rich Web 2.0 Mashups
O’Reilly Open Source Convention (OSCON) 2006
Portland, OR
July 26, 2006

Download PPT (1.8MB)

This was the first OSCON I ever attended. I had a great time and I met a lot of amazing people. I’m definitely going back next year. Much of what I discussed in the talk came from work I did on the Plaxo widget, and the point of this talk was to share the techniques I’d learned and also to raise awareness and debate of the larger issues and privacy/technology tradeoffs involved. I’ve covered this talk in more detail on Plaxo’s blog (thanks Plaxo for sending me!). Kevin Yank also blogged a summary of the talk.

Newer posts »

© 2024 Joseph Smarr

Theme by Anders NorenUp ↑