Tuesday, December 25, 2012

Mac OSX write NTFS

Apple doesn't make NTFS writable even in latest mountain lion operating system, so after I switch to new Macbook with Retina Display, I have not write anything to 'My Book Essential' which is NTFS format. However, due to the macbook 256G storage limit, I have to look for backing up before delete ebooks, photos and videos. Then I need write data to NTFS.

First I downloaded and installed NTFS_1.0d2.dmg by mistake, which was quite old and dated in 2003. I should read the download info carefully before typing my admin password to install this wrong app (which is also using package installer wizard, not the drag&drop app installation).

Then I googled and tried to find a way to uninstall it, but the solution is not straightforward, I even could not find a easy-to-understand way (something like the Window control panel way).  To a rescue, I open the install package, and run the uninstall command shell, but I don't know if the uninstall is complete or not. Apple is always trying to hide the details from end user, good and bad.

OSXFUSE-2.5.4.dmg
https://github.com/osxfuse/osxfuse/downloads
ntfs-3g-2010.10.2-macosx.dmg
http://sourceforge.net/projects/catacombae/?source=dlp
are the solutions to get NTFS writable.

They are also package, but uninstall or update can be found from preference pane, which should be available in System Preferences once you have installed the package. In case you need run shell command from Terminal,
NTFS-3G
/System/Library/Filesystems/ntfs-3g.fs/Support/uninstall-ntfs-3g.sh
OSXFUSE (not sure if below works)
https://github.com/osxfuse/osxfuse/blob/master/packaging/uninstaller/uninstall-osxfuse-core.sh



Thursday, December 20, 2012

4 ways to call parent functions in backbone

Struggled with OOP concept in backbone.js when calling parent function, actually it is not backbone problem, but Javascript itself. After google, I found 4 most discussed ways to make sub class invoke parent class functions.

1. Use backbone plugin
https://github.com/lukasolson/Backbone-Super
this._super(attributes, options);

2. Use standard using Javascript style prototype
Backbone.Model.prototype.xxx.call(this)

3. Use the internal __super__ property
childModel.__super__.xxx.call(this)

4. Create _super function to Backbone Class
Backbone.Model.prototype._super = function(funcName){
    return this.constructor.__super__[funcName].apply(this, _.rest(arguments));
}
this._super('set', arg);

I suggest to use the plugin if possible.

Wednesday, December 19, 2012

Debug FB API in local computer

Facebook Javascript SDK is well-designed and ease-of-use based on well-documented developer web site. There are a couple of steps to use FB APIs, and debug the codes in local computer rather than server.

Step 1:
Setup the app on https://developers.facebook.com/apps/
Usually need fill out the following two major sections:
1) Website with Facebook Login
2) App on Facebook (Canvas URL, Secure Canvas URL)

Step 2:
Change local computer hosts file to map 127.0.0.1 to production domain URL (the one entered in step 1)

Step 3:
Access local computer using production domain, which will be pointing to local code base, and it is easy to debug.

Monday, December 17, 2012

Destroy Backbone View

When look at backbone.js View (http://backbonejs.org/#View), it is a Javascript object for UI piece, and works very well with backbone model (can be updated independently when the model changes). However, there is no handy destroy() or cleanup() or close() method to completely get rid of backbone view.

Then how to destroy a backbone view? 
Suggestion 1:
Backbone.View.prototype.destroy = function(){
  this.remove();
  this.unbind();
  if (this.onClose){
    this.onClose(); // in each view, implement this: like this.model.unbind("change", this.render)
  }
}

Suggestion 2:
Backbone.View.prototype.destroy = function() {
  this.remove();
  this.unbind(); // alias of this.off();
  if (this.model) {
    this.model.off(null, null, this);
  }
  if (this.collection) {
    this.collection.off(null, null, this);
  }
}

Suggestion 3:
Backbone.View.prototype.destroy = function() {
    this.remove();
    this.undelegateEvents(); // use this or this.unbind/this.off?
    $(this.el).removeData().unbind(); // this is to remove custom data from jQuery data cache?
    Backbone.View.prototype.remove.call(this); // this is redundant?
}
Backbone view does provide the following APIs
1. remove() which is to remove a view from DOM
2. undelegateEvents() which is to removes all of the view's delegated events

The call to `this.remove()` delegates to jQuery behind the scenes, by calling `$(this.el).remove()`. The effect of this is 2-fold. We get the HTML that is currently populated inside of `this.el` removed from the DOM (and therefore, removed from the visual portion of the application), and we also get all of the DOM element events cleaned up for us. This means that all of the events we have in the `events: { … }` declaration of our view are cleaned up automatically!

The call to `this.unbind()` will unbind any events that our view triggers directly – that is, anytime we may have called `this.trigger(…)` from within our view, in order to have our view raise an event.

The last thing we need to do, then, is unbind any model and collection events that our view is bound to.

With that, suggestion 1 or 2 is the way to go.

Then how about sub-views?

One best practice is saving sub views in a view property, and when destroy parent view, loop through sub view list to destroy them one by one.

How to render view with sub-view?
The answer is: Use view.setElement() method. For instance,

render : function () {
    this.$el.$html(this.template());
    this.subview1.setElement(this.$('.subview-1')).render();
    this.subview2.setElement(this.$('.subview-2')).render();
    return this;
}

Backbone 0.9.9 
This 1.0 release candidate added listenTo() and stopListening() to help destroy view completely, below is from Backbone online upgrade info.

Most importantly, Backbone events have two new methods: listenTo and stopListening. These are an inversion-of-control flavor of the usual on and off, and make it a little easier to clean up all events that an object is listening to on other objects. When you destroy Views with view.remove(), this will now be done automatically. 

If when bind view to model/collection using listenTo, then our view destory will be:

Backbone.View.prototype.destroy = function(){
  this.remove(); //remove from dom, clean up dom events, and also call stopListening() to remove any bound model events that the view has listenTo'd.
  this.unbind(); //remove self triggered events
}

Sunday, December 16, 2012

Browser is becoming Web OS

Browser as an OS for the Web might be the future of front-end development platform. Google Chrome is getting closer to this, and Firefox OS is also moving toward this direction. Using Javascript, HTML5 and CSS to build native-like apps for the Web, it will bring our WWW more interactive, more user-friendly, more productive and of course more capable.

Recently I started to look at Chrome Web Store, they are many many free apps, extensions and themes in the store. Developing these stuff on top of Chrome browser is kind of fun and straightforward if following Google online tutorial, user manual and API descriptions.

App has hosted app and packaged app. Packaged app is more interesting and need explore further, while hosted app is basically a reference (soft link) to your own hosted web app instead of Chrome web store.

Extensions (plugins) are Javascript/HTML/CSS built package installable on Chrome browser, so that the extension can interact with Chrome browser and provides many cool functions via well-documented APIs (https://developer.chrome.com/extensions/api_index.html)

Themes are skins which empowers preference (color tone, wallpaper etc) on the browser platform.

With these fun experiment, modern browser is changing from platform to OS and HTML5 gives web developers more flexibility and ability to build beautiful web apps. I consider these modern browsers are operating system for the Web on top of native operating systems (Windows, Mac, Linux etc).

Sunday, December 2, 2012

Select HTML5 Video/Audio Player

There are many HTML5 Video and audio players which support native HTML5 audio/video tags with flash/silverlight fallback to support non-modern browsers. Selecting appropriate player among a big list needs more research effort, so finding the right one for your web application depends on your web app requirement and design. Even your web app doesn't need support non-modern browsers, I still suggest to use one HTML5 media player because different browsers support different video/audio codecs.

Web app requirement and design usually include the following points:
1. Do you want a unified UI/API for native HTML5 and flash fallback?
2. Do you need this on iOS (or other mobile browsers)?
3. Do you need the skinnable player?
4. Do you need the player support both video and audio?
5. What kind of license do you accept?

Among the big list and google results, I finally referenced the below 3 links to narrow down my choices
http://praegnanz.de/html5video/
http://html5video.org/wiki/HTML5_Player_Comparison
http://websitesmaderight.com/2011/05/45-html5-media-players-tutorials-and-resources/ 

For Video
video.js (LGPLv3)
SublimeVideo (Service/licensed)
JW Player (Custom)
flowplayer (GPLv3/Commercial)

For Audio
audio.js (MIT)
SoundManager (BSD)

For both Video and Audio
mediaelement.js (GPLv2 & MIT)
jplayer.js (GPL/MIT))
pickle player (licensed/purchase)
jMediaelement(GPL/MIT)
html5media.info (CC BY-NC-ND 3.0)

I want to find a player to support both Video and Audio, license free, working on iOS and with different themes for visual happiness. From above shorter list, I probably go with mediaelement.js (Paul Irish also recommends this player).

Wednesday, November 14, 2012

data(), attr() and prop() APIs

data(key, value) - Store arbitrary data associated with the matched elements.
Due to the way browsers interact with plugins and external code, the .data() method cannot be used on <object> (unless it's a Flash plugin), <applet> or <embed> elements. To retrieve the value's attribute as a string without any attempt to convert it, use the attr() method.

removeData() - Remove a previously-stored piece of data
As of jQuery 1.4.3, calling .removeData() will cause the value of the property being removed to revert to the value of the data attribute of the same name in the DOM, rather than being set to undefined. Removing data from jQuery's internal .data() cache does not effect any HTML5 data- attributes in a document

Data events: 
Besides of jQuery object, we can also use the data() on JavaScript objects, and handle 3 events
 setData
 getData
 changeData

Sample code:

var obj = {};
$(obj).data('name', 'jim');
console.log(obj);
$(obj).bind('setData', function (e, key, value) {
    console.log(key)
}).bind('getData', function (e, key, value) {
    console.log(key)
});
$(obj).data('age', 36);
$(obj).data('name');

attr(key) - Get the value of an attribute for the first element in the set of matched elements.
.attr() should not be used on plain objects, arrays, the window, or the document.
To retrieve and change DOM properties, use the .prop() method.

attr(key, value) - Set one or more attributes for the set of matched elements.

removeAttr() - Remove an attribute from each element in the set of matched elements.

prop(key) - Get the value of a property for the first element in the set of matched elements.

prop(key, value) - Set one or more properties for the set of matched elements.

removeProp() - Remove a property for the set of matched elements.
In general, it is only necessary to remove custom properties that have been set on an object, and not built-in (native) properties. Do not use this method to remove native properties such as checked, disabled, or selected. 
Use .prop() to set these properties to false instead.

Performance wise, prop() is much faster than attr() and data().

The confusing part is when to use each of these APIs. data() is to store arbitrary data in jQuery cache, and it also loads html5 data-attribute. attr() is for HTML attribute, while prop() is for DOM property. One of the reference articles gives a very good explanation the difference between attribute and property, and summarizes with below table. 

DOM Properties vs HTML Attributes
Standard DOM properties and attributes (like id, class/className, href, value etc) are synced, but the values are not always the same. For details, need refer to W3C specs.

Reference:



Wednesday, November 7, 2012

Browser installed plugins

Safari:
Help -> Installed plug-ins
file:///Applications/Safari.app/Contents/Resources/English.lproj/Plug-ins.html

Firefox:
Tools -> Add-ons
about:plugins

Chrome:
chrome://plugins/
about:plugins

IE:
TBD

Opera:
TBD

Friday, November 2, 2012

XMLDocument in javascript

XML was so popular in XHR calls before JSON, and at that time (before jQuery) web developers used native Javascript APIs to convert XML string to XMLDocument (DOMParser) and vice versa (XMLSerializer). The following 2 functions are examples.

function StringtoXML(str) {
    // second parameter mimetype is required
    return (new DOMParser()).parseFromString(str, 'text/xml')
}

function XMLtoString(xmldoc){
    var serialized;
    try {
        serialized = (new XMLSerializer()).serializeToString(xmldoc);
    }
    catch (e) {
        // Internet Explorer has a different approach to serializing XML
        serialized = xmldoc.xml;
    }
    return serialized;
}

This pair is similar to JSON.parse and JSON.stringify for conversion between JSON object and String.

Now that we have jQuery, converting between XMLDocument and String is easier.
jQuery utitlity has 2 methods for XMLDocument
$.isXMLDoc() to test an XML document
$.parseXML() to parse String to XMLDocument

However, jQuery doesn't provide the utility method to convert XMLDocument to String. We can use above native window.XMLSerializer object.

Sometimes if we need manipulate XML data, we can wrap to jQuery object and leverage plenty of jQuery APIs. For instance, if we need change id attribute in XML data, we can use below methods.

$(xml).attr('id', 'new_id')[0].outerHTML
$("<p/>").append($(xml).attr('id', 'new_id')).html()

Friday, October 19, 2012

3 ways to ajax sequentially

One is to chain ajax calls through callbacks (have your Ajax callback go to a handler that starts the next ajax request). This is the simplest implementation but deep call chain will cause maintenance headache due to tightly coupling. It is serial requests and serial responses.

The second method is to have a class to manage a queue of requests, and process them sequentially. The sexy.js does parallel requests and serial responses. The library might be of this solution.

The third way is jQuery Deferred to force async functions to execute sequentially by using its pipe chaining http://api.jquery.com/category/deferred-object/. jQuery 1.5 starts to implement Promise/A spec and provides a bunch of interfaces like when(), done(), fail(), then(), reject(), and resolve() etc.

Wednesday, October 17, 2012

CSS Selectors

http://www.w3.org/TR/css3-selectors/#selectors

Universal selector => *
ID selector => #myid
Class selector => .myclass
Type (element) selector => p
Attribute selector => E[foo^="bar"]Structural pseudo-classes => E:nth-child(n)
User action pseudo-classes => E:hover
Element state pseudo-classes => E:enabled
Negation pseudo-class => E:not(selector)
Pseudo-elements => E::before

Combinators => Descendant (space), Child (>), Adjacent sibling (+) and General sibling (~)

For HTML, case insensitive.

I also have a post about CSS Performance. Selector efficiency is key to performance in jQuery programming, which basically is to select something, take some actions against DOM.

Tuesday, October 16, 2012

3 heights in DOM

scrollHeight
Returns the total height of an element's contents, in pixels. The value contains the height with the padding, but does not include the scrollBar, border, and the margin.

clientHeight
Returns the height of the visible area for an object, in pixels. The value contains the height with the padding, but it does not include the scrollBar, border, and the margin.

offsetHeight
Returns the height of the visible area for an object, in pixels. The value contains the height with the padding, scrollBar, and the border, but does not include the margin.

One use case is to push page footer at the bottom by setting body content height dynamically based on current document height.
http://james.padolsey.com/javascript/get-document-height-cross-browser/ has the details, but the idea is to find the max value of these 3 heights from document.body and document.documentElement.

I use the jquery version from its comment section which is easier.
Math.max($(document).height(), $(window).height(), /* For opera: */ document.documentElement.clientHeight)

The corresponding scrollWidth, clientWidth, offsetWidth have similar concepts.

First build using grunt.js

Gruntjs is so cool, I should try out this excellent Javscript build tool earlier. It has built-in task, APIs, and pluginable framework (see http://gruntjs.com/ for various plugins). Base off node, gruntjs tries to meet extensive Javascript project build requirements. For details, check out https://github.com/gruntjs. This note describes the steps to create grunt.js build script for one of my Javascript projects.

Precondition:

Node and NPM are installed. Verify its installation and version, refer to below commands

node --version
v0.8.7

npm --version
1.1.49

Purpose:

Minify JS
Minify CSS
Optimize images
Compress HTML
Package build

Steps:

Install grunt globally: 
sudo npm install -g grunt

Install plugins locally:
sudo npm install grunt-smushit (to smush images)
sudo npm install grunt-contrib-copy (to copy files/folder)
sudo npm install grunt-contrib-mincss (to minify CSS files)
sudo npm install grunt-htmlcompressor (to compress HTML)
sudo npm install grunt-contrib-clean (to clean up build target)

grunt built-in task "min" is to minify JS using UglifyJS

Generate project scaffolding
grunt init:gruntfile

Create grunt.js to build project

Tuesday, October 9, 2012

CSS display property

This is the best article (as of writing this note) I found from google The CSS Display Property: A Reintroduction To A Familiar Friend, it uses simple words to explain display property.

Most frequently used display values are the followings (there are a bunch of table-values and new CSS3 values based on flex box model or grid model)
  • inline
  • block
  • inline-block
  • list-item
  • none
  • inherit
inline - (Default value) The element is displayed as an inline element (like span, a), horizontally displayed and don’t follow the box model, so it doesn't form a new box.

block - The element is displayed as a block element (like p, div, h1), vertically one after the other following box model, so it is a new box with margin, border, and padding.

inline-box - The element is placed as an inline element (on the same line as adjacent content), but it behaves as a block element. It acts like inline boxes on the outside (being laid out horizontally), but they’re block level boxes on the inside (form a new box with vertical margins and paddings). It is height is calculated using line-height or based on containing block (box).

list-item - The element behaves like block level element with the addition of an extra box (the marker box) used to place a marker.

none - The element will not be displayed at all (removed from DOM, different from visibility)

inherit - The value of the display property will be inherited from the parent element 


Tuesday, October 2, 2012

Inline frame

<iframe> element was first introduced by Microsoft IE in 1997, standardized in HTML 4.0 Transitional, and is allowed in HTML 5. There is still some use cases to use iframe, like website ad, embed multimedia and cross domain web content sharing. Its other similar elements like <frameset>, <frame>, <noframes> are obsolete in HTML 5.

Recently I encountered one use case which might be a reason to use iframe in regard to some cons like browser support, firewall blocking, SEO concerns and so on. These inline frames allow the designer to put frames of other websites in the middle of a current website without a lot of coding efforts. Here is one code example to create iframe and append to DOM.
var iframe = document.createElement('iframe');
iframe.width = '100%';
iframe.height = '100%';
iframe.src = '{url to same origin resource or different web site}';
$('#container_div').append(iframe);
Inject Content into a new IFrame introduces 3 different ways to add concent to iframe
  1. Change the src attribute to an external document URL
  2. Use the DOM’s open(), write(), close() API to inject content
  3. Use the javascript: URI scheme
iframe.src = 'the url to my content';

iframe.contentWindow.document.open('text/html', 'replace');
iframe.contentWindow.document.write(myContent);
iframe.contentWindow.document.close();

iframe.contentWindow.contents = myContent;
iframe.src = 'javascript:window["contents"]';

In most cases, iframe works well to load other web site content, but sometimes browser (Chrome in my test) will throw error "Refused to display document because display forbidden by X-Frame-Options." This happens when there is X-Frame-Options HTTP header sent by target website and prevents displaying that page in an iframe. For more info about this header, check out MDN: The_X-FRAME-OPTIONS_response_header. Google, Yahoo etc set this header either to DENY or SAMEORIGIN to prevent being inlined. In this case, need present some friendly message to website visitors.

Wednesday, September 26, 2012

HTML Email Tips

Recently I start to work on HTML Email template which needs to support popular email clients like gmail, hotmail, yahoo mail, Apple Mail, MS outlook etc. I thought it was easy to build HTML email template (based on what we have on web page), however I was wrong when the first version was out and showed up in web email client. Using Chrome developer tool to investigate the root cause, I realized that writing HTML email is totally different from Web page. Simply converting web site HTML/CSS codes to HTML email will not work as desired for these different email clients.

I did 3 versions and referenced to many useful online resources, then got the HTML email template kind of work across email clients. During the development and test, I summarized the tips to create HTML emails. It is interesting to work on this area, though the technical is not savvy.

Layout:
Use Table instead of Div
Table width should be 550-600px
Specify table and cell width
Avoid using CSS margin, use CSS padding or spacer.gif
Images and other HTML elements should reside in table cell
Specify desired alignment
Specify colspans and rowspans
Don't nest table too deep
Use <br> instead of <p> if possible

Styling:
Inline CSS to each HTML element
Limited CSS support (use CSS to format content, but don’t rely on it for layout)
Put style in the BODY of the email, not in the HEAD
Add proper nested closing tag for each element

A list of inline styles that are pretty well supported:
background-color
border
padding
color
font
font-* (e.g. font-family, font-style, font-size, font-weight font-variant etc.)
letter-spacing
line-height
table-layout
text-* (e.g. text-align, text-decoration, text-indent, text-transform)
border-collapse

Image:
Add style=”display:block” in the image tag
Always give images absolute paths
Always use ALT tags
Always provide size attributes for images.

Content:
Absolute no javscript
No video, flash (use annimated gif if really needed)
No forms (Use link instead)
No background-image, use HTML background attribute
Don't only use images (most email client doesn't show images by default)
Use HTML character escape sequences, such as &reg; for ®

Convention (Recommendation):
View it in browser link
Subscribe and opt out
Track your email
Consider mobile version

References:
http://premailer.dialect.ca/
http://htmlemailboilerplate.com/
https://github.com/mailchimp/Email-Blueprints/tree/master/templates
http://www.campaignmonitor.com/css/
http://www.campaignmonitor.com/testing/


Tuesday, September 25, 2012

Audio and Video in Modern Browsers

For detailed HTML5 audio and video introduction, check out http://html5doctor.com

Currently when I look at these 2 tags support status in modern Web browsers, I have to say <audio> and <video> are not fully supported. The reason is different browsers have different media format support in these 2 new HTML5 elements. In project, developers unusually use audio or video libraries to do the heavy lifting stuff, default to use HTML5 media elements, and fallback to Flash or Siliverlight for non-supported media formats.

I checked caniuse.com and html5-audio-the-state-of-play, then summarized the state-of-media support status in most frequent used web browsers. As of today, the latest Chrome is 22.0.1229.79, latest Firefox is 15.0.1, latest Safari is 6.0, iOS Safari 6.0, latest Opera is 12.02.


Sunday, September 16, 2012

jQuery TreeView Plugin

jQueryUI 1.9 beta release added 3 new widgets (Menu, Tooltip, and Spinner) but still no tree view widget in picture though jQueryUI has the plan http://wiki.jqueryui.com/w/page/12138128/Tree. In the plan wiki page, it recommends 2 plugins:

http://www.jstree.com/
http://bassistance.de/jquery-plugins/jquery-plugin-treeview/

I once tried jquery.dynatree.js which supports checkbox and lazy loading of tree branches. In current project, once again there is tree view requirement (ajax/JSON, checkbox tree, optional sorting, optional lazy load tree branches), so it is better to list out some researched plugins for future reference. (I do hope jQueryUI can support tree widget soon).

jsTree (many features, and plugin friendly to support more functionality like checkbox plugin, JSON data plugin etc)

jQuery plugin: Treeview (not maintained any more, recommend jsTree and look forward to jQueryUI support of tree view)

jquery.dynatree.js (basically meet the tree view requirements my project wants, but not as famous as jsTree, and not actively developed)

jQuery File Tree (configurable, ajax file browser plugin for jQuery)

jQuery TreeView Menu (brings together all the most practical features requested in a Tree Menu into one awesome menu script)

jQuery Tree (jQuery UI widget that you can use to add advanced features to an html tree built using nested unordered lists, derived from jQuery checkboxtree plugin)

jQTreeTable (for tree table UI display)

I will compare jsTree and Dynatree to see which one is better for current project.

Wednesday, September 12, 2012

postMessage Sample Codes

Cross-document messaging has 2 parts: sender and receivers. Sender can be parent window or child window,  and reciever can be child window and parent window. (sibling windows should also work, for browser tab or windows, need further research.) Here we only talk about the main window includes one iframe case for cross-document (cross-domain) messaging.

Sender (main window):
    var win = document.getElementById("iframe").contentWindow;
    win.postMessage(
            'the-sample-message',
            "http://www.target-origin.com"
    );


Sender (iframe window):
    parent.postMessage(msg, 'http://www.target-origin');

Receiver (onmessage event):
    window.onmessage = function(e){
        if ( e.origin !== "http://www.origin.com" ) {
            return;
        }
        // parse and validate e.data

        // processing e.data
    };

Receiver (customized event handler):
     var handleMessage = function(e) {
         if ( e.origin !== "http://www.origin.com" ) {
            return;
         }     

        // parse and validate e.data
        // processing e.data
    };

    if (typeof window.addEventListener != 'undefined') {
        window.addEventListener('message', handleMessage, false);
    } else if (typeof window.attachEvent != 'undefined') {
        window.attachEvent('onmessage', handleMessage);
    }


References
http://www.w3.org/TR/webmessaging/#web-messaging
https://developer.mozilla.org/en-US/docs/DOM/window.postMessage
http://html5demos.com/postmessage2

addEvent utility function (from html5demos.com, good for reference)
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
} else {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
}
})();



Nginx Configuration for WPO

Two key configurations for Web performance optimization (WPO). In the future, we will look at how to tune TCP stack on nginx for better performance.

Turn on Gzip for text files
    gzip  on;
    gzip_comp_level 5;
    gzip_min_length  1000;
    gzip_types application/json text/css application/x-javascript text/javascript;

text/html is always compressed.

Add Expires header to static files
    location / {
        if ($request_uri ~* \.(ico|css|js|gif|jpe?g|png)$) {
                        expires 72h;
                        break;
        }
    }

    # This block will catch static file requests, such as images, css, js
    # The ?: prefix is a 'non-capturing' mark, meaning we do not require
    # the pattern to be captured into $1 which should help improve performance
    location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
        # Some basic cache-control for static files to be sent to the browser
        expires max;
        add_header Pragma public;
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    }

    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        expires max;
        break;
    }

Tuesday, September 11, 2012

iframe Communication

iFrame is used on web page to mashup content from same or different domains, same domain looks straightforward, but same-origin-policy prevents direct communication between iframe(s) or parent window if the origins are different.

Same domain:

1. child iframe calls parent window JS function:
window.parent.functionName()

2. parent window calls iframe JS function:
document.getElementById('frameName').contentWindow.functionName()
Other alternatives for above JS code 
window.frames['frameName'].contentWindow.functionName();

var el = document.getElementById('frameName');
if(el.contentWindow) {
    el.contentWindow.functionName();
}
else if(el.contentDocument) {
    //el.contentDocument.functionName();
    el.contentDocument.defaultView.functionName();
}


Cross domain:
HTML5 Web Messaging http://dev.w3.org/html5/postmsg/#web-messaging defines cross document messaging to address this issue, and as of writing, it is supported in most browsers (except for IE7 and below) for iFrame-to-parent-window communication (IE has not implemented cross window/tab messaging yet). The standard API is window.postMessage(message, targetOrigin [,transfer]).

However if we need support old browsers for cross domain messaging, we need look at other hacks or solutions.
  1. Hashchange of iframe or parent window. For instance, parent window change iframe window's fragment (hashchange), and iframe polling the change (or onhashchange event) to get passed fragment identifier
  2. hidden proxy iframe, hashchange based
  3. hidden proxy iframe, resize event based (see https://github.com/ternarylabs/porthole/)
  4. Flash (some library uses flash fallback)
Libraries using postMessage with fallbacks
Client to server cross domain:
  1. proxy server
  2. JSONP
  3. CORS (Cross origin resource sharing)
Reference
http://softwareas.com/cross-domain-communication-with-iframes
http://stackoverflow.com/questions/6309674/wrapping-postmessage-in-jquery


Wednesday, August 29, 2012

Manipulate Element in jQuery

Here are some frequently used functions in jQuery to handle DOM elements
  1. empty() removes all child elements and other child nodes (such as text nodes) from each element in the matched set, leaving the selector element empty
  2. remove() removes matched elements and child nodes, deletes all jQuery data and events associated with the removed elements
  3. detach() behaves exactly like remove(), except that it doesn't delete the jQuery data and events associated with the removed elements (for later use)
  4. unwrap() function removes the parent of an element (or the parents of a set of elements) from the DOM
  5. replaceWith() lets you replace an element, or set of elements, with new content.
  6. replaceAll() does the same job as replaceWith(), but you pass in the elements that you want to replace
  7. Adding content at the start of an element (or elements) with prepend() and prependTo()
  8. Adding content at the end of an element (or elements) with append() and appendTo()
  9. Adding content before an element (or elements) with before() and insertBefore()
  10. Adding content after an element (or elements) with after() and insertAfter() 
  11. Wrapping content around an element (or elements), or around an element's contents, with wrap(), wrapAll() and wrapInner()

Thursday, August 23, 2012

jQuery mobile swipe event double firing

When I import jquery mobile latest js library and bind some div to swipeleft or swiperight event, I receive double events for every swipe. This is very frustrated as I need do some action on each swipe. After some google, there are couple of solutions.

Solution 1:
Change jquery mobile source code - add return false in $.event.special.swipe

Solution 2:
Use the on() method with event.stopImmediatePropagation() to stop the double bubble
$(function(){   
    $('somediv').on('swipeleft swiperight',function(e, data){
              e.stopImmediatePropagation();
    });
});

Solution 3:
Bind the swipe event to documen
$(document).on('swipeleft',function(e, data){
        e.preventDefault();
});

Solution 4:
Find other libraries which has no such an issue like jquery.touchSwipe.js

I selected #4 solution because I want a lightweight js library for just swipe/touch events (btw, jquery mobile provides custom build), and I don't want HTML5 pushstate (which is enabled by default in jquery mobile)

Tuesday, August 21, 2012

Debug Mobile Web

Recently I start to develop mobile web, so summarize the debug methods I have explored. Apart from traditional annoying alert and verbose console.log, on desktop I prefer to Chrome developer tool (cmd+shift+I) which is so developer friendly to debug web site. (Safari has developer tool, Firefox has firebug, Opera has dragonfly, IE has F9). Fortunately on mobile web, we also can get similar tools and methodologies to help mobile web development.

Weinre
http://people.apache.org/~pmuellr/weinre-docs/latest/Home.html
It's a debugger for web pages, like FireBug (for FireFox) and Web Inspector (for WebKit-based browsers), except it's designed to work remotely, and in particular, to allow you debug web pages on a mobile device such as a phone.

It has debug server, debug client and debug target.
Adobe® Shadow
http://labs.adobe.com/technologies/shadow/
Shadow is a new inspection and preview tool that allows front-end web developers and designers to work faster and more efficiently by streamlining the preview process, making it easier to customize websites for mobile devices.

As Flash is dropped in iOS, it seems that Adobe is putting more effort to HTML5 and mobile web now (There is a free upcoming event Create the web tour in San Francisco, Sept 2012), and Adobe is creating many good resources and tools for the prominent Web.

iWebInspector
http://www.iwebinspector.com
iWebInspector is a free tool to debug, profile and inspect web applications running on iOS Simulator (iPhone or iPad). @firt is a true expert in Mobile Web, I had his 'Programming the Mobile Web' book with his signature from last year's Velocity conference at Santa Clara. He also created the excellent http://mobilehtml5.org/

Chrome
Chrome settings - Override User Agent/Override device metrics
Safari
Enable Safari's developer tools, then set Safari's UserAgent to Safari iOS

Bookmarklets
I know there are a bunch of bookmarklets to help mobile Web debug, but I have not explored them yet, will update this post when I get chance to try them out.



Saturday, August 18, 2012

Non-multipart file upload

The well-known swfupload ()http://demo.swfupload.org/Documentation/ uses multipart/form-data to post parameters and file binary data. I could not find an option to turn off multipart to stream file content to server which doesn't support multipart/form-data content-type.

However, after some research, there are two options for non-multipart file upload.

One is jQuery-File-Upload (https://github.com/blueimp/jQuery-File-Upload/wiki/Options) which provides an option 'multipart: false' to turn off multipart upload.
Official documentation:
multipart

By default, XHR file uploads are sent as multipart/form-data.
The iframe transport is always using multipart/form-data.
If this option is set to false, the file content is streamed to the server url instead of sending a RFC 2388 multipart message for XMLHttpRequest file uploads.
Non-multipart uploads are also referred to as HTTP PUT file upload.

Note: Additional form data is ignored when the multipart option is set to false.
Non-multipart uploads (multipart: false) are broken in Safari 5.1 - see issue #700.

Type: boolean
Default: true


The other is plupload (http://www.plupload.com/documentation.php) which also provides an option 'multipart: false' to upload file using direct binary streams.
Official documentation:
multipart

Boolean state if the files should be uploaded using mutlipart instead of direct binary streams. Doesn't work on WebKit using the HTML 5 runtime.

Tuesday, July 31, 2012

Install pngcrush on mac

Steps to install pngcrush:
1.  (precondition for compile pngcrush source code) Installed Xcode, and installed Command Line Tools from Xcode -> Preferences -> Downloads -> Components -> Command Line Tools

2.  Download pngcrush latest version
http://sourceforge.net/projects/pmt/files/pngcrush/

3.  Extract the downloaded package and run "make"

4.  Move or copy pngcrush to one $PATH folder
sudo cp pngcrush /usr/sbin/

5.  Try out
pngcrush -reduce -brute original-image.png new-image.png

Quick notes about image optimization:
When we talk about image optimization for web performance, we usually consider use pngcrush to optimize PNG file, and use Jpegtrans to optimize JPEG file. Usually we automate this in web build. I once wrote a post regarding this topic.

On mac, there is an app called ImageOptim which supports many cool tools.

https://www.xebew.com/xebinders/#join/BlGnxLjLT6f7cOiJgcpCbTC

Detect Retina Display using Javascript

New retina display macbook pro asks web developers to detect retina display using Javascript, so that web server can serve high resolution images for better visual experience on retina display. Today I did some quick test on different browsers and found Safari/Chrome already supports retina display though Chrome doesn't provide window.retina interface to Javascript developers. I believe Firefox will soon add this support in such a browser war.

Firefox 14.0.1
window.retina => undefined
window.devicePixelRatio => undefined

Chrome 21.0.1180.57
window.devicePixelRatio => 2
window.retina => undefined

Safari 6.0 (8536.25)
window.retina => true
window.devicePixelRatio => 2

Based on above experimental result, I suggest to use below Javascript to detect retina display and do corresponding logic (like loading high resolution images). See pseudo codes below.

var retina = (window.retina || window.devicePixelRatio > 1);
if (retina) {
//retina display
//load high resolution picture
$(img).src = 'high-res.jpg';
}
else {
//non-retina display
//load low resolution picture
$(img).src = 'high-res.jpg';
}

Wednesday, July 25, 2012

Macbook Pro crashed

All of a sudden, my new Macbook Pro started to crash quite often, sometimes one crash every minute, and then crash around 15 minutes. I started my "fix" using different ideas.

First, I tried to recall what kind of changes I had before the crash happens, and consider "dropbox bug when its 2G storage limit is reached", so I quit the app, delete the app, and reboot system. However, crash still happens after few hours.

Second, after some search on google, some people suggest to delete system caches. I had a try to delete most system caches from various cache folders

~/Library/Caches
/Library/Caches
/System/Library/Caches
/private/var/root/Library/Caches
However, this clean up didn't save the crash.

Third, I looked the System Diagnostic Reports from Console application, and found most crashes with below information. It shows that it is Mac OS X system error.


Process:         WindowServer [1458]
Path:            /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/WindowServer
Identifier:      WindowServer
Version:         ??? (???)
Code Type:       X86-64 (Native)
Parent Process:  launchd [1]
Date/Time:       2012-07-25 15:20:17.888 -0700
OS Version:      Mac OS X 10.7.4 (11E2620)
Report Version:  9
Crashed Thread:  0  Dispatch queue: com.apple.main-thread
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00007fff00000010




After reading some discussions on apple support site, I tried to disable "Automatic graphics switching" from Apple -> System Preferences -> Energy Saver. After I disable the option for both batter/adapter, so far so good. I am not sure if this configuration change can solve crash issue.

Last, Mountain Lion is released today, so I can upgrade Lion to see if the crash goes aways with latest Mac OS. There are a lot of cool features in Mountain Lion, but I do hope the crash issue is resolved as well.

Tuesday, July 17, 2012

Sublime Text 2

This is an awesome text editor.

Install Sublime Package Control which is a full-featured package manager that allows for easy discovery, installation, upgrading and removal of packages from various sources. Includes an automatic upgrader to keep your packages up to date.

Lots of plugins http://wbond.net/sublime_packages/community

Customize User Settings:
Copy default settings to User settings (which will not be overridden when upgrade Sublime Text 2)
Sublime Text 2 -> Preferences -> Settings - Default
Sublime Text 2 -> Preferences -> Settings - User

I turned on the following settings to avoid SVN difference caused by extra spaces
"translate_tabs_to_spaces": true,
"trim_trailing_white_space_on_save": true,
"save_on_focus_lost": true,

Frequently used key sets:
cmd+shift+p

Monday, June 18, 2012

CSS Preprocessors (Sass, LESS, Stylus)

Background of this post
On May 31st, @verekia gave a talk at SFHTML5 meetup about Deep dive into CSS Preprocessors. I heard of Sass and LESS for quite some time, but could not check them out to understand their syntax, features and flows.Our current project also plans to use LESS in v2.0 for CSS coding. So what is CSS preprocessor, why need CSS preprocessor and what are the main difference among these three great tools?

Fortunately after quick google, I found this great article answering all my questions.
http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less-vs-stylus-a-preprocessor-shootout/

What is CSS Preprocessor?
Preprocessors produce CSS that works in all browsers. They don't enhance CSS, but improve your CSS development workflow. They are tools for better CSS development and maintenance. Sass, LESS, and Stylus are the most popular Preprocessors. They are all great.

Why need CSS Preprocessor?
There are many reasons (use cases) for using CSS preprocessors. For large scale web site development, for modular CSS code structure, for efficient CSS coding,  vendor prefixes, 3D Text, Columns (math + variables for div widths) and so on.

Definitions (copied from official website)
Sass is an extension of CSS that adds power and elegance to the basic language. It allows you to use variables, nested rules, mixins, inline imports, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized, and get small stylesheets up and running quickly, particularly with the help of the Compass style library.

LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. LESS runs on both the client-side (Chrome, Safari, Firefox) and server-side, with Node.js and Rhino.

Stylus, Expressive, dynamic, robust CSS

What are the differences among Sass, LESS & Stylus?
Language
Sass is written in Ruby
Less and Stylus are written in JS


Syntax
Sass and LESS both use the standard CSS syntax.
The syntax for Stylus is much more verbose, accepts other variations

Variables

$mainColor: #0982c1; - Sass
@mainColor: #0982c1; - LESS
mainColor = #0982c1 - Stylus

Nesting
All three preprocessors have the same syntax for nesting selectors
Don't nest too much (4 levels max)

Mixin
Mixins allow the reuse of properties throughout stylesheet.
@mixin mixinA(), @include mixinA() - Sass
.mixinA() - LESS (there is a dot in the front of mixinA)
mixinA() - Stylus

Function

Functions are a similar construct, only they are typically meant to perform an operation and return a value. All three preprocessors have function and built-in color functions. (see below for more info)
Functions like lighten() return a value
Mixins don't return anything but output CSS

Inheritance
Sass & Style @extend .block
LESS Use mixin, no real inheritance as of today

Importing
@import "file.{type}"; - Sass, LESS & Stylus

Color Functions
lighten(color, 10%); /* returns a color 10% lighter than 'color' */
darken(color, 10%);  /* returns a color 10% darker than 'color' */
saturate(color, 10%);   /* returns a color 10% more saturated than 'color' */
desaturate(color, 10%); /* returns a color 10% less saturated than 'color' */
and more functions

Operations

Doing math in CSS is quite useful, and now fully possible from all three preprocessors
body {
  margin: (14px/2);
  top: 50px + 100px;
  right: 100px - 50px;
  left: 10 * 10;
}

Comments
When compiling with a CSS preprocessor, any double-slash comment gets removed (e.g. //comment) and any slash-asterisk comment stays (e.g. /* comment */). So after compiling, we need minify CSS.

What tools are for CSS Preprocessors?

There are a bunch of tools and editors to support CSS preprocessors. Different platforms (Windows, Mac OS, Linux) may have different availability. Here are some options, better to check out their website. Codekit, LiveReload, Less.app, Compass.app, Scout, Crunchapp, SimpLess. From google search result, Codekit, Campass seems to be more popular.

Sass: Sass + Compass + FireSass
LESS: there is no similar Compass for LESS, but twitter bootstrap uses LESS
Stylus: Nib + Stylus


Side notes
OOCSS is heavy for DOM but efficient in terms of CSS file size
LESS client is for development purpose only, never use it in production
Recommended blog for Sass: The Sass Way

Tuesday, June 5, 2012

中美创业感悟 by Dr. Datong Chen

第一次在湾区听成功人士的创业感悟,而且是中文的。这个周一晚上,在InnoSpring 公司(类似国内的孵化器) ,陈大同博士介绍了他在美国和中国先后创业的个人感悟和宝贵经验。此前不了解陈博士,尽管当年在国内的时候听说过展讯公司。在近2个小时的介绍中,他剖析了2次成功创业的历程、经验和心得。可能就像他说得那样,没有被成功和荣誉捧杀的他,创业中的艰辛、挫折、挑战、机遇、激动、成功,从他口中出来,没有激情昂扬,只是低调叙述。葛优说的淡定,就是说得这个境界吧。

那什么是创业呢?在回家的路上,反复琢磨他演讲中一些印象深刻的话。我从字面意思上理解,创业应该是创新+企业。湾区说的startup就是创业,少数几个人为了共同的目标信念开个公司,做些有意义的事情。陈博士说的”不安分“是创业的催化剂,当你看到未来10年的生活时,应该感到彷徨和危机,当初他离开国家半导体,就是不想一直做半导体工艺,而是想创新,做半导体设计。“被创业”其实也是他内心的想法,Follow your heart,做有挑战,有风险,有创意的事情,是创业者的特征。一直做程序员的人我,不能完全体会他所有的话,但有些印象深的还是罗列出来供以后参考。

不安分 (有冲动)- 在OmmiVision前,他还介绍了新岛的故事,时刻思考着,寻求改变。
不满足 (有想法)- 2个公司都上市了,没有退休享乐,而是去做风投,帮助新一代的追梦者创业。(优秀的运动员退役后会做教练员,优秀的创业者成功后会做投资人)
不信邪 (爱挑战)- 不懂设计,自学设计,不知co-founder而做co-founder, 不了解3G,偏做3G
用最新的技术做最新的产品,没有见到成功的
对市场机遇的把握非常重要
预测一年后的市场比较容易,三年后的就很难了
分析家对新产品的预测总是太乐观了,实际需要的时间是预期的两倍
唐僧是优秀的CEO
做80%用户接受的产品,太完美会错过市场机遇
挂羊头卖狗肉-应对市场需求和风投期望
世界经济向中国转移,中国市场潜力无穷
创业是折寿的实验,Co-founder的生活跟常人不一样
创业失败被抹杀,创业成功被捧杀
烧尽在黎明前的黑暗中(资本风险)
做个蓝海企业,不要红海企业
大企业靠品牌和收购,小企业靠创新和速度

创业的故事,能够讲出来的只有百分之一,因为创业大约百分之九十的时间是用来开会,做研究等繁琐的事情,剩下的百分之十, 又有百分之九是不能说的故事,真正讲出来而且大家又感兴趣听的,就剩百分之一了。这是他的开场白。在他的叙述中,也感到了这点,但其中的百分之一也有不少可以让人琢磨的了。

Stay hungry, stay foolish! 他用乔布斯的话结束了他的演讲。

Scrum Fundamentals for Teams

Today I joined one day training about "Scrum Fundamentals for Teams". Throughout the sessions and exercises, I got some general idea about Agile and Scrum from delivery team perspective. The learning course included the following areas

Principles of Agile
Agile - uncovering better ways of developing software by doing it and helping others do it. There are 12 principes behind the Agile manifesto.

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

Agile & Scrum Vocabulary
User stories - lightweight requirements structure focusing on stakeholders and value (who, what, why)
Acceptance Criteria - agreements of functional expectations between PO and delivery team (DT), represents external quality
Definition of Done - description of the work that is accomplished by the team for each story, represents internal quality
Points - a relative estimate of product backlog items
Velocity - the measure of work from product backlog accepted by PO each sprint
Impediments - blocking problem preventing team achieving higher performance
Sprint - a timebox a.k.a an iteration
Sprint Goal - business value based desc of each sprint goal

Scrum Framework
Scrum is a framework, extremely simple, part of Agile umbrella, based on self-organizing, cross functional teams iterative & incremental delivery.

Scrum Roles
Product owner (PO) - vision, roadmap, prioritize backlog, acceptance criteria
Delivery Team (DT), a.k.a. Development Team
ScrumMaster - servant leader, removes impediment
Functional manager - support scrum team following scrum framework and each role's responsibility
   
Scaling Scrum
Scrum of scrums
Scaling product ownership (chief PO, product line owners, PO)
Scaling teams (component teams, feature teams, hybrid mode)
Distributed teams (best practices)

Preparing Product Backlog
User stories
Acceptance Criteria
Grooming meetings
Estimate and sizing

Key takeaways
Don't go agile just because of agile is popular
High performance team is key to success (self-organizing or functional manager arrangement)
Iteration development and continuous integration enables workable software after each Sprint
Prioritize work and deliver potentially shippable product in each Sprint
Daily stand up (daily scrum) meeting is very important for transparency
Definition of Done is very important for achieving Sprint goal (satisfying customer requirements)
2 weeks Sprint is the recommended timebox
Sprint goes planning, iteration, review and retrospective
Make things simple (maximizing product backlog)
Scale scrum for large product

Friday, June 1, 2012

Email Protocols

When sending or receiving emails, email client needs certain protocol to talk to email servers. In general, there are five protocols for incoming and outgoing emails, namely IMAP, POP3, SMTP, MAPI and HTTP.

IMAP (Internet Message Access Protocol), latest version is 4, so also called IMAP4. It is a client/server protocol in which e-mail is received and held for you by your Internet server. It is two way, so changes on client will reflect on server as they are connected (online).

POP (Post Office Protocol), latest version is 3, so also called POP3. It provides a simple, standardized way for users to access mailboxes and download messages to their computers, then act on the downloaded messages without needing to stay connected (online). It is always one way, from server to client.

SMTP (Simple Mail Transfer Protocol) protocol is used by the Mail Transfer Agent (MTA) to deliver your email to the recipient's mail server. The SMTP protocol can only be used to send outgoing emails, not to receive incoming emails.

MAPI (Messaging Application Programming Interface) is Microsoft's proprietary email protocol.  It provides greater functionality than IMAP for Outlook email clients interacting with an Exchange email server. It only works on this combination, not others.

HTTP (Hypertext Transfer Protocol) is the application protocol for web communication, but it can be used for accessing mailbox, a.k.a. web based email. For instance, Exchange server can be accessed by Outlook Web Access (OWA), Hotmail/Gamil etc can be accessed using browsers.

DNS Record Types

A Record - address record, contains a domain to IP address mapping
CNAME - Canonical name record, alias of one name to another canonical domain name. useful for creating multiple subdomains like docs.mysite.com, home.mysite.com, news.mysite.com for different purpose
MX Record - Mail exchange record, direct email to servers (hosts providing MTA services) for a domain
NS Record - Name server record, determines which servers will communicate DNS information for a domain (delegates a DNS zone to use the given authoritative name servers)
TXT Record - contains arbitrary text but can also be used to define machine readable text.

For details and complete record type list, look at wikipedia List_of_DNS_record_types



Thursday, May 31, 2012

"Node Up and Running" reading notes

This book is an introductory usage guide to Node.js. It has two parts: one is practical "up and running" part with three chapters, the other is reference part with API, Data access, external modules etc five chapters.

In the first part, it gives quick introduction about Node.js, and how to install, how to build a chat server and twitter, also explains event loop, how to build robust node applications (patterns, error handling, and using multiple processors). Following the examples or code snippet, it is very easy to get node.js up and running. Also reader can get an introductory idea about what is node.js, how does it work, and what does it can do.

In the second part, it deep dives core APIs, helper APIs, Data Access, external modules, extending node. Event, http, I/O related APIs are core to build a web application using server side javascript. DNS, Crypto, and processes related help APIs are regularly useful for writing applications. In chapter 6, the books goes through a bunch of data stores from CouchDB, Redis, MongoDB, MySQL, PostgreSQL and also RabbitMQ. The last two chapters explore node modules, including popular Express (MVC framework), and Socket.IO (websocket), as well as extending node by building modules or creating packages.

nodejs.org has below definition:
Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

Node.js provides an unique opportunity for server side javascript to build scalable web or network applications, using one language on both client and server sides. High performance and high scalability application is the design goal of node, and its active community and extensive modules make programming javascript on server side very promising and attractive. After we deep understand Nodes' event-loop architecture, non-blocking I/O and event-driven model, using established design patterns, building node.js application will be a fun journey.

Next step, try out more node.js codes, and read Node.js in Action book.

CSS position property

The CSS position property takes 5 values.

    position: absolute
An absolute positioned element is positioned relative to the first parent element that has a position other than static. If no such element is found, the containing block is <html>. It is removed from normal flow. Sometimes we float columns with clear, instead of using relative position and absolute position.

    position: relative
A relative positioned element is positioned relative to its normal flow, using top, right, bottom, and right. It also it establishes a context for position:absolute. It still occupies that original space in the normal flow.

    position: fixed
An element with fixed position is positioned in relation to the browser window. It is removed from normal flow as absolute positioned element. It is common to see fixed position for twitter-like header, though IE6 needs some hack.

    position: static
This is the default value if no CSS position specified. The element is not positioned, and is part of the normal flow of the page.

    position: inherit
The element uses the position of its parent. The value from parent element position can be one of static, relative, absolute and fixed.