Cloud Samurai
the open web, web development, and more
Thursday, January 7, 2010
Gmail Notes 2.x
Tuesday, December 15, 2009
Gmail Notes - Google Chrome Extension
Monday, July 20, 2009
Methods Plugin 0.1
Since my introductory post on the Methods Plugin, I've improved the API and published it to jQuery's Plugin Directory.
The latest 0.1 version now adds 2 methods to jQuery: addMethod
for adding methods and methods
for retrieving the methods you added. Let's jump into some example code to explain it better. In this example I'll create a function that returns a jQuery object which has custom methods added to it. These methods can only be called by first calling the methods
method on the jQuery object.
/**So now we have a
* A generic productListing widget that can be displayed in a list...
*
* @param {String} tag - A string of HTML that will be converted to a jQuery Object
* @param {Object} data - A JSON Object of all the data, e.g.: {name: string, quantity: integer, price: float, description: string, freeShipping: boolean}
*/
function productListing(tag, data) {
var $el = $(tag);
$el
.addClass("product-listing")
.append("<h3>" + data.name + "</h3>")
.append("<p>" + data.description + "</p>")
.append('<span class="product-listing-quantity" >' + data.quantity + '</span>')
.append('<span class="product-listing-price" >' + data.price + '</span>')
// And on and on doing DOM stuff.
// Now here is the interesting part!
.addMethod("getQuantity", function () {
return data.quantity;
})
.addMethod("setQuantity", function (quantity) {
data.quantity = quantity;
$el.find(".product-listing-quantity").html(quantity);
})
.addMethod("freeShipping", function () {
return data.freeShipping;
});
}
productListing
function that returns a jQuery object. This object can be inserted into the DOM, hidden, animated, or anything else you like to do with jQuery. However, you can also call the methods
method, which returns a simple object of your functions, and start calling any of the methods you added previously: getQuantity
, setQuantity
, and freeShipping
. If any of these methods does not return a value, the methods object is returned so you can continue to call methods in a chain. You can also call the method end
to get back to the jQuery objects scope (included for chainability).To explain this better, let's get back to code:
// Some data or our productListingAnd there you have it. Methods is a small plugin, but hopefully it makes your life as a JavaScript developer a little easier.
var data = {
name: "Internet Celebrities Spoon Set",
description: "Now get the Star Wars Kid on a coffee spoon! These commemorative spoons...",
quantity: 10,
price: 19.99,
freeShipping: false
};
// Create a new productListing object
var commemorativeSpoonSet = productListing("<li/>", data);
// Append it to a DOM node, manipulate it, and call custom methods
$("#products-list")
.append(commemorativeSpoonSet)
.hide()
.methods()
.setQuantity(20)
.end()
.show();
// Look it up in the DOM too
var products = $(".product-listing");
products.each(function (i) {
if (!$(this).methods().freeShipping())
{
$(this).hide();
}
});
Wednesday, July 8, 2009
Better Objects Using jQuery
I've been working almost exclusively with JavaScript building single page applications recently. jQuery has made developing the apps enjoyable but one area I find a bit awkward is creating complex objects.
Classes work well but can be cumbersome when creating a user interface since the object reference returned from the constructor is not a DOM node but a JavaScript object. Therefore, in order to insert the user interface component into the page, a special method like getHTML
must be available for that object. This isn't terrible but creates more complicated code. Here's an example user interface widget - a simple box displaying a name:
function Widget(name) {
var container = $("<div/>");
function setName(newName) {
name = newName;
container.html(name);
}
this.getHTML = function () {
setName(name);
return container;
};
this.getName = function () {
return name;
};
this.setName = function (newName) {
setName(name);
};
}
And the code that uses it:
var nameWidget = new Widget("Dave");
var widgetNode = nameWidget.getHTML();
$(document.body).append(widgetNode);
This isn't too bad but gets a bit ugly when you need the ability to hide, show, animate, or do anything interesting. The choice is either to attach more methods to the Widget
class or work with the jQuery object returned by getHTML
. Pattern-wise, adding more methods to Widget
is the cleanest but could require creating a lot of methods. Working with the jQuery object returned by getHTML
is easy but leads to managing two objects in your code: nameWidget
and widgetNode
What would be really nice is the ability to call any jQuery method on the nameWidget
object PLUS all the methods specific to the Widget
class. It occurred to me that this could be possible with the addition of a small jQuery Plugin I've dubbed Methods.
(function ($) {
$.fn.methods = function (arg0) {
if (arg0)
{
return this.each(function (i) {
$(this).data("methods", arg0);
});
}
else
{
return $(this).data("methods");
}
};
})(jQuery);
This plugin adds the methods
method to jQuery. A collection of functions can be passed to methods
to attach it to a specific jQuery object. Calling methods
then returns the collection of functions. Here's a rewrite of the Widget
class to explain this better:
function widget(tag, name) {
var container;
container = $(tag)
.html(name)
.methods({
getName: function () {
return name;
},
// Return "this" for chainability
setName: function (newName) {
name = newName;
container.html(name);
return this;
},
// Add the end method for chainability
end: function () {
return container;
}
});
return container;
}
And the code that uses this:
var nameWigdet = widget("<div/>", "Dave");
$(document.body).append(nameWidget);
Now we have a nameWidget
that directly corresponds to the user interface component and, using jQuery, can be inserted anywhere in the page. To access the object's specific methods, you simply call methods
. Here's an example that shows the combination of the methods and chaining:
nameWidget
.hide()
.methods()
.setName("Bob")
.end()
.show()
.addClass("widget");
Since the Methods plugin uses jQuery's data method behind the scenes, the nameWidget can actually be retrieved through a DOM lookup.
var nameWidget = $(".widget")
.hide()
.methods()
.setName("Sally")
.end()
.show();
And that's it. In the end, Methods is a simple jQuery plugin that lets you create complex objects with custom methods and closures and can still be used like a regular jQuery object.
Sunday, November 16, 2008
Upgrading Dell Mini to Ubuntu 8.10 + Netbook Remix
Since I want to upgrade to Ubuntu 8.10 and install the Netbook Remix, the first hurdle to overcome was the lack of a built-in optical drive. The folks at the Ubuntu Mini blog have a great post about upgrading the mini to Ubuntu 8.10 and provide details on installing Ubuntu from a USB Drive.
Unfortunatley, their instructions on using the built-in "Create a USB startup disk" resulted in a "Missing Operating System" error when trying to boot from the USB Drive. I think the USB Drive I bought was subject to this error. However, after a bit of searching, I came across the most excellent UNetBootin.
UNetBootin is not is the official Ubuntu repositories but the instructions on the site are easy to follow. In order to get UNetBootin to work I had to use synaptic to install the p7zip-full package. Other than that, the instructions on the site worked as expected and I ended up with a bootable USB Drive in minutes. And as an added bonus, I didn't have to fix the USB mounting problem after install.
I neglected to disable compiz in Preferences > Appearance > Visual Affects so when it came time to installing the Netbook Remix packages, the display was acting really wonky. Disabling Visual Affects after the fact made everything work fine but I would still recommend disabling them in advance. If the lack of visual affects is a turn-off, then you'll be pleasantly surprised with the nice visuals the Netbook Remix employs.
Dell Inspiron Mini Has Arrived
The Dell Inspiron Mini I ordered back in mid-September (over 2 months ago) finally arrived. The wait time was atrocious and I don't really believe Dell's excuse about a global shortage of components causing the delay (other orders for the mini were still shipping much faster) but its water under the bridge. Plus I can vent in the customer satisfaction survey they sent me.
The size of the unit surprised me. Since it has a higher resolution display than the original Eee PC I played with about a year ago, I assumed the mini would be a little larger too. Not so, the mini is roughly the same size. The track pad is much easier to use, however, and the keyboard isn't nearly as bad as reviews make it out to be (but I haven't tried out every netbook either).
The next step is upgrade from Dell's version of the Ubuntu 8.04 to Ubuntu 8.10 and install the Netbook Remix packages. More posts on this to come.
Friday, November 14, 2008
Nice JavaScript Animation
I just popped over to Ubuntu's site to download the Intrepid Ibex (Ubuntu 8.10) and saw a very well produced animation made entirely out of JavaScript. I'm not at all surprised to see that Flash was snubbed (given that Ubuntu is Open Source) but was impressed with the smoothness and quality of the animation.
Nicely done!
Friday, November 7, 2008
Enumerating Objects in JavaScript
Enumerating through objects is something I only occassionally do in JavaScript, but when it does come up, I always find it a bit unintuitive. Here's some sample code for the future me that is faced with this task again:
var dataObject = {
foo: "bar",
one: "fish",
hello: "world"
};
var key;
for (key in dataObject)
{
document.write("Key: " + key ", Value: " + dataObject[key]);
document.write("\n");
}
This code will produce the following lines:
Key: foo, Value: bar
Key: one, Value: fish
Key: hello, Value: world