« January 2006 | Main | March 2006 »

Yahoo Gets It

Feb 19 by Andre in Ajax » , Javascript »
Eric Miraglia at the Yahoo! User Interface blog talks about creating their JavaScript library. One point  he touches on is the hetrogeneity of client configurations, and how that underscored the need for a robust cross-browser toolkit:

Continue reading "Yahoo Gets It" »

Collective thinking: Pong for 5,000 people

Feb 18 by Andre in Misc »
In Hive Mind, Kevin Kelly describes 5,000 people in an auditorium playing a collective game of Pong -- each participant's input is aggregated in real time to determine the ultimate movement of the paddles.
Without a moment's hesitation, 5,000 people are playing a reasonably good game of Pong. Each move of the paddle is the average of several thousand players' intentions. The sensation is unnerving. The paddle usually does what you intend, but not always. When it doesn't, you find yourself spending as much attention trying to anticipate the paddle as the incoming ball.
Read it here: http://www.kk.org/outofcontrol/ch2-b.html

Google Maps at Night

Feb 17 by Andre in Web 2.0 »

google_night.jpgAn interesting application for Google maps overlays. The zoom levels are limited, but still very cool.
The underlying 128 megapixel night imagery from NASA uses a map projection different from Google Maps'. The two are aligned near the NYC-Madrid-Tokyo axis only.
http://www-static.cc.gatech.edu/~pesti/night/
 

Map APIs for Google, Yahoo, MSN

Feb 17 by Andre in Ajax » , Web 2.0 »
StrataVarious has an excellent comparison of online mapping APIs (Google, Yahoo's AJAX maps, MSN virtual earth). For each API, it includes code examples for instantiation, how to zoom and place markers, etc. Very useful! stratavariousmap.png

JavaScript: Namespaces

Feb 13 by Andre in Ajax » , Javascript »
The more things you build in Javascript, the more you will need to partition them into namespaces. There are (at least) two reasons for this:
  • so your functions/objects don't conflict with other peoples code. If you're writing code you intend to distribute, or if you are utilizing anyone else's code, you want to ensure none of the functions have the same name. Javascript will happily replace your setCookie() function with someone else's setCookie() function without so much as mentioning it to you. Problems like this are hard to track down. Namespacing your code is the solution.
  • to organize your functions/objects into groupings that make sense. If you were programming in Java, you wouldn't put all your classes in the same package, right?

How to namespace

In Javascript, you can namespace functions by making them properties of an object. Here's an example, which namespaces an augment() function I will utilize later:

var EC = new Object(); // EC is the first-level namespace, short for EarthCode
EC.F = new Object(); // F is the second-level namespace, short for foundation.

// now define the augment function itself
EC.F.augment = function (oSelf, oOther) {
  if (oSelf == null) {
    oSelf = {};
  }
  for (var i = 1; i < arguments.length; i++) {
    var o = arguments[i];
    if (typeof(o) != 'undefined' && o != null) {
      for (var j in o) {
        oSelf[j] = o[j];
      }
    }
  }
  return oSelf;
}
Now, in real usage, you will be placing multiple functions in a namespace. Here's the syntax I use:
// first, declare the two namespaces if they do not already exist
if (EC == null || typeof(EC) != "object") { var EC = new Object();}
if (EC.F == null || typeof(EC.F) != "object") { EC.F = new Object();}

// all the functions in the EC.F namespace will go in this block
EC.F = {
  augment: function (oSelf, oOther) {
    // contents of the augment function
  },
  Observer: function () {
    // contents of the Observer class
  },
  thirdFunction: function () {
    // function contents
  }
} // end of the EC.F namespace


Tips on namespace names
  • Make 'em short. You're going to be typing the "full path" to the function a lot in your code, and if it's long and a pain to type, you'll revert back to declaring everything in the root namespace.
  • Keep the whole path short. In Java it's common practice to name your packages "com.mycompany.etc.etc.," but this is unnecessary in Javascript. Again, you will be typing the full path a lot, so you want to keep it brief and utilitarian. Most of my namespaces are two packages deep, i.e, "EC.F.Augment()".
  • Plan for future growth. For example, if you're creating a pop-up notifier class, do you anticipate making other kinds of notifiers? Is it worthwhile placing it in a "notifier" package?

Amazing interface utilizing touch

Feb 09 by Andre in Misc »

Via James Mc Parlane's blog (who, BTW, posts excellent stuff on JavaScript)

This is a user interface which utilizes multiple touchpoints on an interactive display. The description doesn't do it justice, so just watch the video -- you will be impressed!

While touch sensing is commonplace for single points of contact, multi-touch sensing enables a user to interact with a system with more than one finger at a time, as in chording and bi-manual operations. Such sensing devices are inherently also able to accommodate multiple users simultaneously, which is especially useful for larger interaction scenarios such as interactive walls and tabletops

Look for the parts in the video where they are 1) sorting photos; 2) navigating Google Earth.

 touchinterface.jpg

http://mrl.nyu.edu/~jhan/ftirtouch/

New Yahoo Layout?

Feb 07 by Andre in Misc »
Robert Ricci spotted a new yahoo homepage and posted it:

yahoo_home_beta_lg.jpg

Definitely an improvement from an aesthetic standpoint . . .

Screenshot of Gmail Chat at Techcrunch

Feb 07 by Andre in Web 2.0 »
Techcrunch has some screenshots of the new Gmail chat inside gmail. Will knowing that your chat history is permanently recorded on Google's servers alter your chatting habits at all? Of course you can take your chats "off the record" -- but the default is that everthing is saved.

Simplicity is good at DEMO 06

Feb 07 by Andre in Gadgets » , Misc » , Web 2.0 »
What is DEMO '06? From PC Mag:

A select group of digerati will roll into the Pointe South Mountain Resort in Phoenix, Arizona next week for the DEMO '06 conference. The annual event is often a showcase for eye-popping emerging technologies, often from early startup companies. While not all the companies become successful with their ideas, many do.

A report on the morning session s is here DEMO 06: Morning Report (from HorsePigCow)

Chat Peanut Butter and Email Chocolate

Feb 07 by Andre in Web 2.0 »
I know every blog out there is posting on Google's Chat/Email integration, but I have to call out Techdirt's article for their  title: Google Mixes Chat Peanut Butter With Email Chocolate

Ajax photo editor

Feb 06 by Andre in Web 2.0 »
PXN8.gif pxn8.com has an Ajax image editor which works pretty well. Good enough to actually utilize in place of firing up the trusty Photoshop? You decide.

Wired: Monetize your roof

Feb 06 by Andre in Misc »
Apparently Google Maps and the like have opened up new business opportunities for some:

"I'm currently launching RoofShout.com with no money, no real experience running a business on the internet, and no real solid business plan," Fitz-Gerald said. "But I figure there's a lot of blank roofs and a lot of advertising that could go on the roofs."
Wired's story here

Stowe Boyd on RSS "breaking through"

Feb 06 by Andre in Web 2.0 »
Cogent thoughts by Stowe Boyd, based on an earlier post by Dave Winer. On the centralization vs. decentralization aspect, I'm with Stowe (decentralization). It's the social aspect of finding others who share our interests, and discovering new content in the process.

Super Bowl ads on Google Video

Feb 05 by Andre in Misc »
budlight.jpg

I can't believe godaddy wasted as much money as they obviously did on such lame ads. Bud Light had the best of the bunch, with "Hidden Bud Light" and "Save Yourself" as my favorites.

How to take advantage of web 2.0

Feb 05 by Andre in Web » , Web 2.0 »
Dion Hinchcliffe has an excellent post on ten Ways To Take Advantage of Web 2.0 (web2.wsj2.com)

IBM, others take opensource approach to Ajax

Feb 02 by Andre in Ajax » , Web » , Web 2.0 »
The story is here. A few notable excerpts:

In Ajax's case, there is little need to spur emergence of a market, because the market is already there. In most cases, it's been a situation of web developers taking the laws into their own hands, a strategy that Google Maps legitimized.
Very true, and I think precisely one of the reasons developers have been so enthusiastic about Ajax -- when there are no ground rules, it opens up a lot of creative options for developers.

. . . but with battle lines drawing on the future of rich Internet clients, something was bound to give. Like Linux previously, Ajax has become too popular for vendors to ignore.
Also true. The commercial market for Ajax tools and skills is about to explode.

The article goes on to talk about the proliferation of Ajax toolkits (70 at last count), Ajax support in Eclipse, and more.

Javascript: Event broadcasting/listening

Feb 02 by Andre in Ajax » , Javascript » , Web »

A key advantage of OO programming is reuse. The more broadly useful an object is, the more likely it is you will need to "wire it in" to your page (or other objects) in unanticipated ways. But, if you want the object to trigger event X when Y happens, how do you do it without changing the actual methods in your object?

To connect up your object up to other objects without violating its integrity, you need event broadcasting/listening.

To make this concrete, imagine a simple object representing a tri-state checkbox. HTML checkboxes are two-state (either checked or unchecked), and you need one with three states (checked, unchecked, and grayed out). You will program this as an image which responds to onClick events by cycling the image source through a series of three graphics. So far so good?

What do you want to invoke when the checkbox object changes state? If you're programming it in a non-reusable way, you can hard-code the action directly into the onclick event: if (state==checked) do X; if (state==grayed_out) do y; etc. If you're programming it as a reusable component, you need a more flexible solution.

First, in psuedo-code, for the onClick event:

// PSUEDO CODE!
method onClick() {
  if (state == unchecked) {
    update graphic src to "checked";
    broadcast "checked" event; 
  } else if (state == checked) {
    update graphic src to "grayed_out";
    broadcast "grayed_out" event; 
  } else if (state == grayed_out) {
    update graphic src to "unchecked";
    broadcast "unchecked" event; 
  }
}

Now, your page just needs a way to listen for the events, and you're set -- you can have anything on the page react to an event in the checkbox instance, without changing code inside the checkbox class itself.

How to do it

We're going to create an Observer object, which takes care of both event management (adding and removing events which can be broadcast) and notification (registering functions to be called in the case of a specific event).

/*
Event handler, intended to be used in composition with other objects
*/
function Observer () {
  this.add=add;
  this.remove=remove;
  this.notify=notify;

  this.oObservers = new Object();

  function add (sEvent, fObserver) {
    // must be one of the event types already defined in observers
    if (this.oObservers[sEvent] != null) {
      this.oObservers[sEvent].add(fObserver);
    } else {
      alert("attempted to add an observer for an event which doesn't exist. "+
       "Event Name is "+sEvent);
    }
  }
  
  function remove (sEvent, fObserver) {
    // must be one of the event types already defined in observers
    if (this.oObservers[sEvent] != null) {
      this.oObservers[sEvent].remove(fObserver);
    } else {
      alert("attempted to remove an observer for an event which doesn't exist. "+
        "Event Name is "+sEvent);
    }
  }
  
  function notify(sEvent,oArgs) { 
    if (this.oObservers[sEvent] != null) {
      var aTemp = this.oObservers[sEvent];        
      for(var i = 0; i < aTemp.length; i++) {
        aTemp[i](oArgs);
      }
    } else {
      alert("attempted to invoke an event which doesn't exist. "+
        "Event Name is "+sEvent);
    }
  }
  
  //initialization. If there are any arguments passed, 
  // add them and the associated arrays
  if (arguments.length >0) {
    for (i = 0; i< arguments.length; i ++) {
      this.oObservers[arguments[i]] = new Array();
    }
  }
}

Now, the tri-state checkbox can hold a reference to an instance of Observer, register the necessary events, and broadcast as appropriate. For this class, there is only one event (clicked), but you could have as many events as you want -- just separate them in a comma-delimited list.

// in the constructor for the checkbox class:
this.observers = new Observer();
this.observers.oObservers = {
	"clicked": new Array()
};

. . . .

// the "click" event for the checkbox 
// Pseudo-code except for the Observer.notify() part
onClick() {
  if (state == unchecked) {
    update graphic src to "checked";
    this.observers.notify("clicked",{"sNewState":"checked"});	
  } else if (state == checked) {
    update graphic src to "grayed_out";
    this.observers.notify("clicked",{"sNewState":"grayed_out"});	
  } else if (state == grayed_out) {
		update graphic src to "unchecked";
    this.observers.notify("clicked",{"sNewState":"unchecked"});	
  }
}

This code broadcasts the "clicked" event for each of the three states the checkbox can be in. The first argument to the observer.notify() method is the event name -- recall that for this example, only the "clicked event is defined.

The second argument to the observer.notify() method is a set of key-value pairs, allowing you to pass whatever information you want to the listener. The listener can use these values or discard them, but it has to know the key to access them. In this case we pass only one key (sNewState), but we could pass as many as we like in a comma-delimited list inside the {}'s.

Attaching listeners to events

So far, we've prepared an object for event broadcasting. All that's left to do set up listeners. Attaching listeners to the events the object broadcasts will let us utilize the class in unforeseen ways, without changing the internals of the class.

// assuming you have an instance of checkbox called oCheckBox:
oCheckBox.observers.add("clicked", 
  function(oArgs) {
    alert("You clicked it! New state is: "+oArgs.sNewState);
});		

The "function(oArgs)" is the event handler. We associated it to an instance of the CheckBox class by calling oCheckbox.observers.add(). We're specifying the "clicked" event in the first argument to the observers.add() method.

oArgs is the object we passed in the observers.notify() method. Recall that we specified just one key, sNewState. sNewState is used in the event handler alert().

Of course, in actual usage the object would be more complex, and it would broadcast more events. Handlers tend to stay relatively simply, however -- their main purpose is "wiring together" different objects, so an event in one triggers an action in another which is appropriate for the current page.

A final note: you can add as many event handlers as you like for any event on any object! Just call [object].observers.add() as many times as needed -- the handlers will be executed in the order you add them!

Event broadcasting/listening can add a huge about of flexibility to your Javascript OO programming, and allow you to utilize classes in diverse environments without changing their internals.