Enhance Facebook Notes with Greasemonkey

Web April 27th, 2008

The UI of Write a New Note of Facebook is quite straightforward and … shabby:

The UI of Write a New Note in Facebook


If you happen to use Firefox, this userscript would make Facebook’s notes suck less.

Screenshot

The UI of Write a New Note in Facebook


Requirement

Usage
Exactly the same as WordPress’s quicktags, — no wonder, the core functionality is a port from WordPress’s quicktags.js:

  • You may click to button to start a tag, type some words, then click button again to close the tag.
  • Select the words, and click the button to surround it with the corresponding tag.

License
This piece of script is released under the GNU General Public License as WordPress, a compatible license would make my life much easier.

Development
The development is a little bumpy than my expectation. The biggest obstacle in the way is the namespace in Greasemonky is not consistent to the general DOM model. When the page is loaded, GM takes control, we may manipulate the DOM nodes using various ways. When it is done, all the object in GM’s anonymous global namespace runs out of the scope, and they are garbage-collected.

For every rule, there is an exception: the closure as documented in the bible. The anonymous function would create a closure that wraps a function in the GM’s namespace. However this does not work for us since we need to maintain several records to bookkeeping the status. So eventually we have to inject the scripts and objects into the host. Here is a tip to inject the functions, but for the Javascript objects, we have to manually do the dirty work, error-prone and tedious. If you have a better idea to access the objects that resident in the GM namespace, please leave a comment here.

Optimize WordPress in another 4 steps

Web September 21st, 2007

I just moved out from Globat to a new place, Jumpline. It is a good time to clean the house, and throw out all trashes.

Enable WP-Cache + GZIP

Although the official WP-Cache suggests to disable GZIP support, there are some hacks(1, 2) to enable it. That is quite neat.

After this optimization, the total size of front page is 247.6K, 85.1K of that is JavaScript, the built-in prototype.js takes 71.2K. We should take some actions for it.

GZIP the JavaScript and Stylesheet

dailyApps suggests to dynamically gzip the stylesheet and JavaScript to reduce the HTTP download. jotsheet goes even further, a neat method is demonstrated to consolidate all the CSS/JavaScript into one to save the HTTP request.

For normal users, the big bottleneck is the size of prototype.js, and it is most unlikely change unless major version update. So let’s gzip it first and check out the performance boost:
Using Dojo ShrinkSafe, the prototype.js is cut to 49K, not bad.

Thanks to the flexibility of VDS powered by Jumpline, I could easily add mod_deflate to Apache, and enable mod_deflate globally to all CSS and JavaScript. Check out the doc for details.


AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/css

This helps me to save tens of kilobytes, now the gzipped-shrunk protoype.js is 14.6K only, the overall improvement is gzipped 30.2K versus original 142.0K, that is quite impressive.

Use client-side cache

mod_expires just did the right work, load the module and enable it wherever the content would not change:

ExpiresActive On
ExpiresDefault A2592000

Remove ETag

Use these directive to disable ETag globally in httpd.conf:

Header unset ETag
FileETag None

I get B(87) with cache, A(95) without cache in YSlow performance score. The next step optimization may introduce CDN service, for example, Amazon S3.

Optimize WordPress in 5 steps

Web May 8th, 2007

I’ve been bothered by the long latency and slow responsive of my WordPress blog, last night, I would like to dig into this problem and figured it how easy to improve the overall performance.

FireBug is our best friend, there is a built-in module to profile the page loading time, here is the original bloated blog:

Bloated WordPress blog


Without annoying popups, free ipod advertisements, the front page cost 156 KB, and it takes 5.97s to load, that is sooo bloated.

Step 1: Get rid of redundant plugins

The AJAX spell checker plugin consumes around 54 KB, and I seldom uses it since Firefox 2.0 has built-in typo check, say bye bye to AJAX spell checker.

Step 2: Tradeoff between the eye-candy and usability

Nifty Corners decorates the tag block with rounded corner using Javascript and CSS. It is small and neat, but take 690ms to render, that is probably not worthy.

I have never been a big fan of Technorati, the name of the service is too obscure. Just remove the hook and save 250ms.

Now it looks much better

Shrunk WordPress blog


Step 3: Find the less expensive alternatives

I love tag, but Ultimate Tag Warrior is kind of expensive, two php files are parsed in sequence and consume almost 1s. Here is an alternative, Simple Tagging for the similar functionalities, but less expensive. The developer is so considerate to provide the tag import from UTW.

Step 4: Shrink the CSS and JavaScript

Browser does not care the indent or space, developer does. The reader-friendly source code wasted the traffic to transfer the spaces. Here are some tools to help to condense the source code: get rid of the space, shrink the variable name etc. I tried CleanCSS, it cut down the size from 10k to 4k, quite impressive. You might take a try of Dojo ShrinkSafe for your verbose JavaScript as well.

Step 5: Cache

WordPress Cache is a powerful tool to cache the dynamic content to static pages to shorten the loading time and leverage the CPU usage. This is an essential tool if your web site is Slashdotted or Digged.

Now the blog is much more responsive:

Optimized WordPress blog


Further usability optimization may involve AJAX operations, for example, using AJAX to navigate the posts, search. I would try this later.

Debugging Web(3) - Poor man’s debugger

Web December 18th, 2006

This post is for the real poor Web developers who even could not install add-ons on Firefox, at least, there are two spartan debuggers available:

DOM Inspector

A neat tool to demonstrate the DOM structure of the Web page. It is far less attractive than the Web Developer Toolbar’s Display Element Information. However, you might find it useful to inspect the add-on’s XUL.

DOM Inspector in action


Error Console

Error Console supports to evaluate the JavaScript snippet directly. However, the targeted window’s document is not exposed in the global scope, that cripple the usability of this tool and push me to embrace FireBug.
Please leave a comment if I am wrong.

Debugging Web(2) - 10 Pitfalls for the JavaScript Developers

Web December 11th, 2006

Strictly, this post does not belong to this category. But on the other hand, the following pitfalls are usually the evil source.

Note: the code is intentionally to put in one line, just for your convenience to test it in the FireBug.

1. Unexpected global variables

Declare a variable via var state at any time, whether this variable is in the global scope or local scope. Any variable without declaration resides in the global scope, polluting the global namespace.

2. Caution: Boolean operation ahead

JavaScript is extremely tolerate for the type checking, raising an exception is the last thing the interpreter wants to do. The inherent conversion may surprise you especially for the C/C++ programmer. For example,

if (new Boolean(false)) alert(“true”);

Although the constructed Boolean object is false, the if expression returns true. Why? Because the Boolean is an object, if it is not null, the expression returns true.

Here is another example used in the vararg functions: if (arg5 != null) ; C/C++ programmer may jump to the old trick:if (p), Oops, this expression could not differentiate whether p is null or 0 or “” . JavaScript: The Definitive Guide, 5th Edition Section 5.4 disclose the conversion rule for the == operator:

If the two values have the same type, test them for identity. If the values are identical, they are equal; if they are not identical, they are not equal.
If the two values do not have the same type, they may still be equal. Use the following rules and type conversions to check for equality:
If one value is null and the other is undefined, they are equal.
If one value is a number and the other is a string, convert the string to a number and try the comparison again, using the converted value.
If either value is TRue, convert it to 1 and try the comparison again. If either value is false, convert it to 0 and try the comparison again.
If one value is an object and the other is a number or string, convert the object to a primitive and try the comparison again. An object is converted to a primitive value by either its toString( ) method or its valueOf( ) method. The built-in classes of core JavaScript attempt valueOf( ) conversion before toString( ) conversion, except for the Date class, which performs toString( ) conversion. Objects that are not part of core JavaScript may convert themselves to primitive values in an implementation-defined way.
Any other combinations of values are not equal.

typeof operator is also a safe approach, like if (typeof(arg5) == “undefined”)

3. valueOf vs. toString

When JavaScript convert an object to string, the toString function is hidden by valueOf, the valueOf is evaluated, then convert the result to string, like this:

>>> function Foo() {}; Foo.prototype.valueOf = function() { return 3;}; Foo.prototype.toString = function() { return “bar”;}; var x = “foo” + new Foo(); x;
“foo3″

The only exception is Date, the toString is used in + operator, while valueOf is used in the comparison.

4. Immutable String

JavaScript takes this approach to pass the argument to the function: pass by value for primitive data types, pass by reference for objects. String is regarded as the object, but passed by the value:

>>> function foo(s) { s[0] = ‘t’;}; var x=“hello”; foo(x); x;
“hello”

5. Pervasive scope

For C/C++ developer, the declared variable take effects after its declaration, like this:

#include <stdio.h>
int x = 9;

int foo()
{
        printf(“x =%d\n, x);
        int x = 10;
        printf(“x =%d\n, x);
        return 0;
}

int main()
{
        return foo();
}

the output is

x =9
x =10

While in JavaScript, once the variable is declared, it is populated to the whole closure, for instance:

var  x= 9; function foo() { alert(x); var x = 10alert(x); }; foo();

The alerts are undefined and 10. The global value x is shadowed by the local variable x. Local variable x is declared in this closure, but not assigned before the first alert, so its value is undefined.

TO BE CONTINUED…