Cloud Samurai

the open web, web development, and more

Thursday, January 7, 2010

Gmail Notes 2.x

UPDATE: Version 2.2 has been released and improves the look and feel of the note within Gmail, adds an "Add Date" feature, and brings an option to "Unauthorize" Gmail Notes from accessing Google Docs (on the Options page).

UPDATE: Version 2.1 has now been released and brings with it some changes to the User Interface. Instead of inserting a Gmail Notes widget for sign in and adding a note, an icon in the address bar will bring up a sign in popup and allow you to add notes. This was done to make the extension work better for Google Apps accounts and also makes the extension behave the way Google intended extensions to behave.

Version 2.0 of Gmail Notes is now available. This is a big change from the 1.1 version since notes are now synchronized to your Google Docs account- freeing your notes to follow you to any computer running Chrome.

Numerous bugs were also fixed that should make Gmail Notes less picky about the URL and perhaps even run on Google Apps accounts (this hasn't been tested and will likely have bugs).

Please post all bug reports and feature requests in the comments.

Tuesday, December 15, 2009

Gmail Notes - Google Chrome Extension

UPDATE: Gmail Notes 2.0 has been released. Please post bug reports and feature requests there.

I just published, Gmail Notes, a Google Chrome (Beta Version must be installed) Extension that gives users the ability to associate Notes with conversations in Gmail. This post is intended to act as a page where users can file bug reports and I can answer questions. I'll update this post with more information as the extension evolves and gains more features.

IMPORTANT: Any bug reports need to include the URL of the inbox plus the minimum steps required to reproduce the bug

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.

/**
* 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;
});
}
So now we have a 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 productListing
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();
}
});
And there you have it. Methods is a small plugin, but hopefully it makes your life as a JavaScript developer a little easier.

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