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.