May 13, 2008, 3:45 pm · 0 comments · Filed under: JavaScript, Widgets
Can your web browser do this?
You’ll never get rich digging a ditch, nor building Dashboard widgets.
A Kryptonite™ lock can be defeated in 11 seconds, but you still lock your bike, right?
Gaining Twitter followers is a little like losing weight. You have to try.
Over or under? It’s the age-old question when it comes to the orientation of toilet paper rolls.
I am a web developer, recently returned to the States after 3 years in New Zealand. I’m into my family, photography and frisbee sports.
Nothing will benefit human health and increase chances for survival of life on earth as much as the evolution to a vegetarian diet.
–Albert Einstein
Apple · AppleScript · Business · Coda · CSS · Dashboard · Design · Google · InSTEDD · JavaScript · jQuery · Life · Marketing · Music · New Mexico · New Zealand · Open Source Software · Photography · PHP · Politics · Ruby on Rails · Scree · Subversion (SVN) · Twitter · Usability · Web Development · Widgets
CSS Fast Nav: Because (perception of) speed matters! · Personal Branding for Introverts · Stupid WebKit Tricks · Add an interactive legend to a MarkerManager managed Google Map · Dude. Mikeyy can’t even spell his own name. · Dashboard Widgets for Fun and Profit · Animating your iPhone web application · How-to recover from checksum mismatch errors in SVN · Why Apple can afford to charge so little for Snow Leopard · The first 48 hours of PHP Function Reference, by the numbers
CSS Fast Nav: Because (perception of) speed matters! · When is a global variable not a variable? · Our misguided culture of cool · InSTEDD: Open Source Software that saves lives · Add an interactive legend to a MarkerManager managed Google Map · Personal Branding for Introverts · Moments of Rangitoto · Some Twitter conventions · Why Apple can afford to charge so little for Snow Leopard · Stupid WebKit Tricks
Twitshirt is a tweet on a shirt. Buy the one below or check out my most recent tweets.
There is truth. The rest is fashion.
See a random Twitshirt-worthy tweet.
80/20 · 90 Seven Design · Alyson Hurt · Andrew Nimick · Apps & Hats · Ben Young · Brian Arnold · Brian Warren · Carl Bolter · Chris Burgess · Christine Morris · Cristina Stoian · Daniel Lyons · Daniel Schwartz · David Hedges · Hamish Campbell · Jochen Daum · John Visser · Joseph McLaughlin · Joshua Sallach · Julian Pistorius · Justine Sanderson · Kalena Jordan · Katie Graham · Kelly Green · Kevin Potis · Mark Bixby · Matt Henry · Method Arts · Morgan Pyne · Peter Michaux · Philip Tellis · Piers Harding · Rebecca Murphey · Reid Givens · Rey Bango · Rhett Anderson · Richard Paul · Rob Pongsajapan · Robin Taylor · Ryan Park · Shaun Lee · Simon Young · Su Yin Khoo · Toni Barrett · Vaughan Rowsell · Vincent Thomé · Voom Studio
My bias is for references over “cookbooks.” I want to know all of my options, not just one way to do something. Show me the why as well as the how and I am happy.
JavaScript: The Good Parts · Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and libraries · JavaScript: The Definitive Guide · Designing with Web Standards · CSS: The Definitive Guide · Prioritizing Web Usability · The Elements of User Experience · Web ReDesign: Workflow that Works · Don't Make Me Think: A Common Sense Approach to Web Usability
I’ve hosted this website with pair Networks since 1997. They rock.
This blog is powered by…software I wrote.
Feeling generous? Knock yourself out!
You namespace your JavaScript, right? Right?!
Just because Prototype doesn’t do it doesn’t mean you shouldn’t. Better to follow the example of jQuery, YUI, and Dojo and put your JavaScript in a tidy little top-level object so it has less chance of stomping on or getting stomped on by other scripts. I won’t name names, but I recently worked on a site where we were told to include 3rd party ad serving code that put the cleverly named function random() in the global namespace. I’m surprised that’s not used as example #1 in the dictionary for the word “naive.”
Now that I’ve ridiculed you into submission, I’m going to say something you might consider a bit contradictory. In widgets, you don’t have to be so strict about namespacing. There, I’ve said it. Sue me. But first, let me explain.
Unlike the WWW (Wild West Web), where you’re not always in control of all the JavaScript on your pages, in a widget, the environment is more controlled, so it’s easier to know what’s going on. So, rather than putting all of your JavaScript in one namespace (like I myself have done in all my [to-date] published widgets, again with the contradictions, sheesh!), I recommend grouping like functionality into namespaces.
For example, I plan to talk about (though I make no promises, you understand) preferences and version checking. Each of these could go in their own namespace. You know, like PREFS and, oh, I don’t know, maybe VERSION.
There’s nothing magical about this from a coding perspective. Here’s a simple example:
var MYNAMESPACE = {};
MYNAMESPACE.getFunky = function () {
// do funky stuff
};
MYNAMESPACE.getFunky();
Tidy. Orderly. Encapsulated.
The module pattern is a technique for organizing large JavaScripts into public and private members. It was popularized by Douglas Crockford and has been blogged about (and criticized) all over the flipping shop.
One of the important concepts you need to understand to “get” the module pattern is closures. Go read this example-laden overview of closures as they are implemented in JavaScript and come back. I’ll wait.
My use of the module pattern is pretty faithful to the original. The purpose of it, for me, is to be able to create both public and private variables and methods in tight, little, namespaced objects. Here’s an example.
var MYOBJ;
MYOBJ = (function () {
// private variable
var _rgxp;
_rgxp = /^abc$/i;
// private method
var _isMatch;
_isMatch = function (str) {
return _rgxp.test(str);
};
// public method
return {
ask: function () {
var input;
input = prompt('What are the first 3 letters \
of the alphabet?');
(_isMatch(input))? alert('Correct!') : \
alert('Wrong!');
}
};
})();
MYOBJ.ask();
As I said above, this has the advantage of being tidy and encapsulated. I can also run this with confidence that my regular expression (because it’s assigned to a private variable) hasn’t been stomped. The example is contrived, but hopefully you get the idea.
As a reward to myself for finishing each of the posts in this “un-series,” I plan to (again, no promises!) include at the end a little “bonus” code I use to make my widget-building life a little easier. Enjoy!
If you don’t currently localize your widgets, you should. It’s pretty easy and it not only gives you a wider audience for your work, it makes your non-native language users feel all warm and fuzzy.
The following function is based on one generated by Dashcode, Apple’s excellent Dashboard development IDE. Usage is simple. You tell your string you want it localized and it takes care of looking up the string in the localizedStrings array from the proper localized file, and replacing it out.
String.prototype.localize = function () {
try {
var string = localizedStrings[this] || this;
} catch (e) {}
return string;
}
var localString = 'My string'.localize();
In my day job, we use the Symfony PHP framework. Symfony creates a function for localizing strings: __ (That’s 2 underscores, if you’re wondering.)
Being used to the pattern __('My string'), I decided to make it so I could call my localization String method in the same way. It’s simple, really.
__ = function (str) {
return str.localize();
}
var localString = __('My string');
OK, that’s it. I hoped you enjoyed this pre-installment of my un-series. I hope to post the next one, real soon now…
Short URL to this article:
Tweet this article!
Comments close automatically after 90 days.
Still have something to say? Drop me a line!