October 8, 2011

HTML5 APIs

HTML5 introduces lots of new and exciting things for web authors, among these are new APIs. Here are some of them.

An API to interact with the application cache, which is a set of cached resources.

You can do window.applicationCache to get the ApplicationCache object that applies to the active document of that window. More on application caches here.

DataTransfer API
The DataTransfer objects are used to expose the drag data store that underlies a drag-and-drop operation. More on drag and drop here.

Command API
A command is the abstraction behind menu items, buttons, and links. They are defined to have facets (label, hint, icon, etc.) and are exposed on elements using this API.

As of this writing, there is no proper definition to this. But we can assume it'll extend our client-side validation tool arsenal.

The History objects provide a representation of the pages in the session history of browsing contexts.

For example, you can go back (window.history.back()) and forward (window.history.forward()). More on session history here.

An API to interact with the <audio> and <video> elements.

You can do things like play (controller.play()) and pause (controller.pause()). More on media elements here.

Text Track API
An API to interact with the <audio> and <video> associated text tracks, like subtitles or captions.

You can get a media element and get a track from it like media.textTracks[0] (for the first one).
textTrack element has it's own API which can return things like the language, readyState, mode, etc. More on media elements here.

APIs for the text field selections
The input and textarea text elements define an API for handling their selection.

You can select everything in a text field with the select() function, or use selectionStart and selectionEnd to get the currently selected text.

By the way, this is not it. There are, of course, other interfaces and current elements that are being extended with new properties and functions.

Related specifications
Now I present to you:
  • Specs that were originally in the HTML5 spec, but were later moved out into their own.
  • Specs worked on by the Web Apps Working Group (in charge of HTML5).
  • Other related/interesting specs.

Canvas 2D Context
Defines the 2D Context for the HTML <canvas> element.

Clipboard API and events
Describes APIs for clipboard operations such as copy, cut and paste in web applications.

Editing APIs
Defines commands to edit HTML documents programmatically.

File API
This specification provides an API for representing file objects in web applications, as well as programmatically selecting them and accessing their data.

File API: Directories and System
This specification defines an API to navigate file system hierarchies.

File API: Writer
This specification defines an API for writing to files from web applications.

Defines two mechanisms for communicating between browsing contexts in HTML documents.

Indexed Database API
Formerly WebSimpleDB API, this document defines APIs for a database of records holding simple values and hierarchical objects.

Server-Sent Events
This specification defines an API for opening an HTTP connection for receiving push notifications from a server in the form of DOM events.

The Web Sockets API
This specification defines an API that enables Web pages to use the WebSocket protocol for two-way communication with a remote host.

Web Storage
This specification defines an API for persistent data storage of key-value pair data in Web clients.

Web Workers
This specification defines an API that allows Web application authors to spawn background workers running scripts in parallel to their main page. This allows for thread-like operation with message-passing as the coordination mechanism.

Enhances the XMLHttpRequest object with new features, such as cross-origin requests, progress events, and the handling of byte streams for both sending and receiving.


And, again, these are not it. There are other working groups in the W3C besides the Web Apps one, each one with specifications they're working on. It's crazy, I know, but hopefully this will give you an idea of what's coming. I strongly recommend you to research more about it and experiment.

Thanks for reading and let me know your comments.

September 11, 2011

CSS Selectors

Have you ever wondered:
  • How many selectors does CSS have?
  • Which selectors come from which version of CSS?
  • How does each selector work?

Me too! so here's what I found out with an example for each one.

CSS 1
E → an element of type E
div

/* selects any div element in the document */
E F → an F element descendant of an E element
div p

/* selects any p element that is a descendant of a div element */
E.warning → an E element whose class is "warning"
.banner

/* selects any element whose class is "banner" */
E#myid → an E element with ID equal to "myid".
#footer

/* selects an element with ID equal to "footer" */
E:link → an E element being the source anchor of a hyperlink of which the target is not yet visited
a:link

/* selects any unvisited a element */
E:visited → an E element being the source anchor of a hyperlink of which the target is already visited
a:visited

/* selects any visited a element */
E:active → an E element currently being selected
a:active

/* selects any a element currently being selected */
E:first-line → the first formatted line of an E element
p:first-line

/* selects the first formatted line of any p element */
E:first-letter → the first formatted letter of an E element
p:first-letter

/* selects the first formatted letter for any p element */
E, F → an element of type E and an element of type F
label, span

/* not really a selector, it's a way of grouping them */
According to the CSS 1 spec: "Anchor pseudo-classes have no effect on elements other than 'A'".

Also, CSS 1 and CSS 2.1 use a single colon to refer to the first-line pseudo-class (:first-line) but CSS 3 uses two colons (::first-line).

CSS 2.1
Includes all previous ones and adds these in:

* → any element
*

/* selects any element */
E > F → an F element child of an E element
div > p

/* selects any p elements that are direct children of a div element */
E:first-child → an E element, first child of its parent
p:first-child

/* selects a p element, the first child of its parent */
E:hover → an E element when it's hovered over
a:hover

/* selects any a element when it's hovered over */
E:focus → an E element while it has the focus
input:focus

/* selects any input element while it has the focus */
E:lang(fr) → an element of type E in language "fr"
*:lang(fr)

/* selects any element which language matches french*/
E[foo] → an E element with a "foo" attribute
img[title]

/* selects any img element with a title attribute */
E + F → an F element immediately preceded by an E element
div + span

/* selects any span element immediately preceded by a sibling div element */
E[foo="bar"] → an E element whose "foo" attribute value is exactly equal to "bar"
p[class="example"]

/* selects any p element whose class attribute is exactly equal to "example" */
E[foo~="bar"] → an E element whose "foo" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar"
a[title~="copyright"]

/* selects any a element whose title attribute value is a list of
whitespace-separated values, one of which is exactly equal to "copyright" */
E[foo|="en"] → an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en"
*[lang|="en"]

/* selects any element whose lang attribute has a hyphen-separated list of
values beginning (from the left) with "en" */

CSS 3
Includes all previous ones and adds these in:

E[foo^="bar"] → an E element whose "foo" attribute value begins exactly with the string "bar"
object[type^="image/"]

/* selects any object element whose type attribute value begins with "image/" */
E[foo$="bar"] → an E element whose "foo" attribute value ends exactly with the string "bar"
a[href$=".html"]

/* selects any a element whose href attribute value ends with ".html" */
E[foo*="bar"] → an E element whose "foo" attribute value contains the substring "bar"
p[title*="hello"]

/* selects any p element whose title attribute value contains the
substring "hello" */
E:root → an E element, root of the document
:root

/* selects the root of the document, i.e. the HTML element */
E:nth-child(n) → an E element, the n-th child of its parent
tr:nth-child(0n+3)

/* selects any tr element that is the third child of its parent */
E:nth-last-child(n) → an E element, the n-th child of its parent, counting from the last one
tr:nth-last-child(-n+2)

/* selects any tr element that is one of the two last rows of an HTML table */
E:nth-of-type(n) → an E element, the n-th sibling of its type
p:nth-of-type(odd)

/* selects any p element with odd position */
E:nth-last-of-type(n) → an E element, the n-th sibling of its type, counting from the last one
p:nth-of-type(even)

/* selects any p element with even position, starting from the last */
E:last-child → an E element, last child of its parent
ol > li:last-child

/* selects any li element which is a last child of an ol element */
E:first-of-type → an E element, first sibling of its type
dt:first-of-type

/* selects any dt element that is the first sibling of its type */
E:last-of-type → an E element, last sibling of its type
td:last-of-type

/* selects any td element that is the last sibling of its type */
E:only-child → an E element, only child of its parent
tr:only-child

/* selects any tr element that is an only child */
E:only-of-type → an E element, only sibling of its type
p:only-of-type

/* selects any p element which is the only of its type in a parent */
E:empty → an E element that has no children (including text nodes)
div:empty

/* selects any empty div element */
E:target → an E element being the target of the referring URI
p:target

/* selects any p element that is the target element of the referring URI */
E:enabled → a user interface element E which is enabled
input:enabled

/* selects any input element that is in a enabled state */
E:disabled → a user interface element E which is disabled
input:disabled

/* selects any input element that is in a disabled state */
E:checked → a user interface element E which is checked
input:checked

/* selects any input element that is selected or is toggled "on" */
E:not(s) → an E element that does not match simple selector s
button:not([disabled])

/* selects all button elements that are not disabled*/
E ~ F → an F element preceded by an E element
div ~ p

/* selects any p element that is a sibling to any div element */

Sources:
Cascading Style Sheets, level 1
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1)
Selectors Level 3

August 12, 2011

jQuery.type

In my last post I wrote about how to detect a JavaScript array, so I thought it would be a good idea to see how jQuery does it.

Here's the jQuery.isArray() method (in 1.6.2):
isArray: Array.isArray || function( obj ) {
    return jQuery.type(obj) === "array";
}
It uses the native Array.isArray() method if it exists, if not it will find out the type of whatever is passed in using the jQuery.type() method and see if that equals the string "array".

But come on, that's not much of a learning experience not to mention it makes for a pretty short blog post.

So instead, I looked into the jQuery.type() method to see how that works.

jQuery.type()
It looks something like this:
...
// Save a reference to some core methods
toString = Object.prototype.toString
...
// [[Class]] -> type pairs
class2type = {};
...
type: function( obj ) {
    return obj == null ?
        String( obj ) :
        class2type[ toString.call(obj) ] || "object";
}
...
// Populate the class2type map
jQuery.each(
    "Boolean Number String Function Array Date RegExp Object".split(" "),
    function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
})
(Distant pieces of code are separated with three dots.)

Breaking it down
  • Line 3 - A reference to the toString() method of Object
  • Line 6 - An internal object (map) that will contain all types as strings.
  • Line 15-19 - For each member in the array we're passing in, we'll create a property in the object and set its value to the name of the array member in lowercase.
  • Line 8-12 - The method will check if the argument passed in is null or undefined, if so, it will return the string "null" or "undefined" (by calling the String constructor without the new keyword, which is allowed for some constructors). If it's something else, we'll call the toString() method on the argument and look to see if the class2type object has a value for it, if not, we'll just return the string "object".

To give you a better overall picture, here's how the class2type object would look after page load:
var class2type = {
    "[object Array]": "array",
    "[object Boolean]": "boolean",
    "[object Date]": "date",
    "[object Function]": "function",
    "[object Number]": "number",
    "[object Object]": "object",
    "[object RegExp]": "regexp",
    "[object String]": "string"
};

Epiphany
That's why we call the toString() method of Object when we're looking for the property name. Remember how this method returns this sort of "[object Constructor]" string pattern?

So, if we did jQuery.type("hello") we'd actually be doing something like class2type["[object String]"], which would return the corresponding value "string"

And that's how the jQuery.type() method works.

It's not that complicated when you have an "Epiphany" section, huh?

Sources:
jQuery.type() - jQuery API Documentation
jQuery 1.6.2 Source Code