Activate your free membership today | Log-in

Monday, May 5th, 2008

HTML Parser in JavaScript

Category: HTML, JavaScript

John must have had some downtime on Sunday afternoon, as he implemented an HTML parser in JavaScript. The library, that you can play with via this demo, lets you attack HTML in a few ways:

A SAX-style API

Handles tag, text, and comments with callbacks. For example, let's say you wanted to implement a simple HTML to XML serialization scheme - you could do so using the following:

JAVASCRIPT:
  1.  
  2. var results = "";
  3.  
  4. HTMLParser("<p id=test>hello <i>world", {
  5.   start: function( tag, attrs, unary ) {
  6.     results += "<" + tag;
  7.  
  8.     for ( var i = 0; i <attrs.length; i++ )
  9.       results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
  10.  
  11.     results += (unary ? "/" : "") + ">";
  12.   },
  13.   end: function( tag ) {
  14.     results += "";
  15.   },
  16.   chars: function( text ) {
  17.     results += text;
  18.   },
  19.   comment: function( text ) {
  20.     results += "<!--" + text + "-->";
  21.   }
  22. });
  23.  
  24. results == '<p id="test">hello <i>world</i></p>"

XML Serializer

Now, there's no need to worry about implementing the above, since it's included directly in the library, as well. Just feed in HTML and it spits back an XML string.

JAVASCRIPT:
  1.  
  2. var results = HTMLtoXML("<p>Data: <input disabled/>")
  3. results == "</p><p>Data: <input disabled="disabled"/></p>"
  4.  

DOM Builder

If you're using the HTML parser to inject into an existing DOM document (or within an existing DOM element) then htmlparser.js provides a simple method for handling that:

JAVASCRIPT:
  1.  
  2. // The following is appended into the document body
  3. HTMLtoDOM("<p>Hello <b>World", document)
  4.  
  5. // The follow is appended into the specified element
  6. HTMLtoDOM("<p>Hello <b>World", document.getElementById("test"))
  7.  

DOM Document Creator

This is a more-advanced version of the DOM builder - it includes logic for handling the overall structure of a web page, returning a new DOM document.

A couple points are enforced by this method:

  • There will always be a html, head, body, and title element.
  • There will only be one html, head, body, and title element (if the user specifies more, then will be moved to the appropriate locations and merged).
  • link and base elements are forced into the head.

You would use the method like so:

JAVASCRIPT:
  1.  
  2. var dom = HTMLtoDOM("<p>Data: <input disabled/>");
  3. dom.getElementsByTagName("body").length == 1
  4. dom.getElementsByTagName("p").length == 1
  5.  

One place that you could use this API would be on the server-side. For example, using Aptana Jaxer. Although, you could also interface directly to Java, or just use the Mozilla utilities directly.

Posted by Dion Almaer at 10:51 am
6 Comments

+++--
3 rating from 21 votes

Wednesday, April 23rd, 2008

Embed your data- in HTML 5

Category: HTML, Dojo, Unobtrusive JS, Standards

Simon Willison pointed out the part of the HTML 5 spec that discusses a way to add attributes to HTML elements for your own needs via data-.

For example, a spaceship for a game:

HTML:
  1.  
  2. <div class="spaceship" data-id="92432"
  3.      data-weapons="laser 2" data-shields="50%"
  4.      data-x="30" data-y="10" data-z="90">
  5.  <button class="fire"
  6.          onclick="spaceships[this.parentNode.dataset.id].fire()">
  7.   Fire
  8.  </button>
  9. </div>
  10.  

Every HTML element may have any number of attributes starting with the string "data-" specified, with any value.

These are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.

The dataset DOM attribute provides convenient accessors for all the data-* attributes on an element. On getting, the dataset DOM attribute must return a DOMStringMap object, associated with the following three algorithms, which expose these attributes on their element:

Simon points out that "this will be incredibly useful for unobtrusive JavaScript where there’s no sensible place to store configuration data as HTML content. It will also mean Dojo has an approved method for adding custom attributes to declaratively instantiate Dojo widgets."

Posted by Dion Almaer at 7:55 am
12 Comments

++++-
4.5 rating from 31 votes

Monday, February 11th, 2008

Cross Window Messaging with HTML 5 postMessage

Category: HTML, JavaScript, Browsers

John Resig has written a Cross-Window Messaging sample using Firefox 3, which implements the current postMessage API in HTML 5. Opera 9 implements a slightly older version, and a new release will fix that of course:

This particular API adds a new method to every window (including the current window, popups, iframes, and frames) that allows you to send textual messages from your current window to any other - regardless of any cross-domain policies that might exist.

Specifically, you're given a new window.postMessage("string") method that generates a message DOM event on the document of the receiving document. This event object contains the message as a property: event.data which the receiving document can use however they see fit.

His example has a sender:

HTML:
  1.  
  2. <iframe src="http://dev.jquery.com/~john/message/" id="iframe"></iframe>
  3. <form id="form">
  4.   <input type="text" id="msg" value="Message to send"/>
  5.   <input type="submit"/>
  6. </form>
  7. window.onload = function(){
  8.         var win = document.getElementById("iframe").contentWindow;
  9.         document.getElementById("form").onsubmit = function(e){
  10.                 win.postMessage( document.getElementById("msg").value );
  11.                 e.preventDefault();
  12.         };
  13. };
  14. </script>
  15.  

and a receiver:

HTML:
  1.  
  2.  
  3. <b>This iframe is located on dev.jquery.com</b>
  4. <div id="test">Send me a message!</div>
  5. document.addEventListener("message", function(e){
  6.         document.getElementById("test").textContent =
  7.                 e.domain + " said: " + e.data;
  8. }, false);
  9. </script>
  10.  

He also touches on the security issues:

  1. If you're expecting a message from a specific domain, set of domains, or even a specific url, please remember to verify the .domain or .uri properties as they come in, otherwise another page will be bound to spoof this event for malicious purposes.
  2. Just because a string is coming in, as a message, doesn't mean that it's completely safe. Note that in the example, above, I inject the string using .textContent, this is intentional. If I were to inject it using .innerHTML, and the message contained a script tag, it would execute immediately upon injection. This is a critical point: You'll need to be sure to purify all your incoming messages before they are used and injected into the DOM (or sent to the server). This is the same that you would do on the server-side of your application, be sure to take the same precautions here, as well.

Having a standard, blessed, way to talk using this message based system is going to be great for Web developers.

Posted by Dion Almaer at 6:20 am
2 Comments

++++-
4.7 rating from 17 votes

Monday, January 28th, 2008

Less maintenance code tutorials with Ajax Code Display

Category: HTML, JavaScript, Examples, Unobtrusive JS, jQuery

One of my main annoyances with writing code tutorials is that you need to maintain code in several locations: the code itself and the examples in the tutorial document. This is not really a problem when you can use a scripting language or print out the tutorials from a CMS, but when you just want people to get an HTML document you're in trouble. As I am right now writing a lot of articles I didn't want to waste my time and thought about using Ajax to load the code I am documenting into the HTML on the fly. The result looks something like this:

Screenshot of the Ajax Code Display in action

All you need to do is to add jQuery, the script and a class of "codeexample" to a link in the document you want to display. The script creates a PRE element with the code inside, replaces all the special characters, tabs with spaces and adds line numbers. For example:

HTML:
  1.  
  2. <p><a href="ordered.html" class="codeexample">ordered.html</a></p>
  3.  

If you only want to show certain lines (which you'll have to do if you want to explain some code step-by-step) you can define the lines as a list including ranges. Say you want to display line 5, 10 and 12 to 21, then you'd add:

HTML:
  1.  
  2. <p><a href="ordered.html" class="codeexample lines[5,10,12-21]">ordered.html</a></p>
  3.  

You can highlight lines of code in the same manner, say you want like 18 to 20 in bold:

HTML:
  1.  
  2. <p><a href="ordered.html" class="codeexample lines[5,10,12-21] highlight[18-20]">ordered.html</a></p>
  3.  

Last but not least you can make the link clickable to show an IFRAME with the rendered output. Clicking the link again will remove the iframe. For this, just add a class called "dodisplay":

HTML:
  1.  
  2. <p><a href="ordered.html" class="codeexample dodisplay highlight[10,12,14-15]">ordered.html (click to show output)</a></p>
  3.  

The script is creative commons, and hopefully you'll find some extras to add. Enjoy.

Posted by Chris Heilmann at 11:18 am
6 Comments

++++-
4.5 rating from 18 votes

Thursday, January 24th, 2008

Getting HTML 5 styles in IE 7+

Category: HTML, JavaScript, IE

Btw, if you want CSS rules to apply to unknown elements in IE, you just have to do document.createElement(elementName). This somehow lets the CSS engine know that elements with that name exist.

This was uttered by Sjoerd Visscher innocently on a Sam Ruby thread, and it sent ripples of "huh? really? How come I never know that!" through all of the experts.

This fact means that you the following will show up as red in IE 7:

HTML:
  1.  
  2.  
  3. <style>blah { color: red; }</style>
  4. <script>document.createElement("blah")</script>
  5. </head>
  6. <blah>Hello!</blah>
  7. </body>
  8. </html>
  9.  

This is an example from John Resig as he discusses a HTML 5 shiv. You can see how a JavaScript shim can "implement" some of HTML 5 for us.

We have also gone down this route for some of the HTML 5 spec, and you can indeed do a lot with JavaScript. There are a couple of places where you kinda have to be in the browser to do the right thing.... but these are few and far between.

Sjoerd Visscher just blogged about this and told us how he found it out (back in 2002-ish!):

As far as I can remember we found out about this when we converted the first rendering of the XSL output from a lot of createElement calls to one innerHTML change for performance. This caused our custom elements to no longer be affected by CSS.

Posted by Dion Almaer at 8:46 am
2 Comments

++++-
4.1 rating from 15 votes

Wednesday, January 23rd, 2008

HTML 5 Public Working Draft Released

Category: HTML

While the community argued over X-UA-Compatible or X-IE-VERSION-FREEZE, depending on which side of the fence you sit, the W3C published two new and important documents:

Moments ago the joint effort of the W3C HTML WG and WHATWG resulted in publication of two documents in the W3C Technical Report space: HTML 5 and HTML 5 differences from HTML 4. I think I can safely say that the WHATWG community is very happy with the W3C publishing HTML 5 as a First Public Working Draft. Many thanks to all involved!

It is great to see this actually getting out there. It is very fun indeed to look at the new elements and think about how you would use the likes of <dialog>, <command>, <meter>, and finally being able to do things like input type="datetime|datetime-local|date|month|week|time|number|range|email|url".

It feels like semantics are being added in. The generality of div class="whatever" is all well and good, but for the very common situations, I am looking forward to using type="email" and having the browser take care of validation, and using my address book to pick through.

Posted by Dion Almaer at 9:00 am
10 Comments

++++-
4 rating from 27 votes

Friday, December 7th, 2007

Taking a peak at HTML 5

Category: HTML

Lachlan Hunt has taken some time to walk us through some of the HTML 5 features that relate to new markup.

Work on HTML 5, which commenced in 2004, is currently being carried out in
a joint effort between the
W3C HTML
WG
and
the WHATWG.
Many key players are participating in the W3C effort including representatives
from the four major browser vendors: Apple, Mozilla, Opera, and Microsoft;
and a range of other organizations and individuals with many diverse interests
and expertise.

Note that the
specification
is still a work in progress and quite a long
way from completion. As such, it is possible that any feature discussed in
this article may change in the future. This article is intended to provide
a brief introduction to some of the major features as they are in the current
draft.

Take a look at the structure of HTML docs to come. No more div-hell:

Bloggers will be able to use the new article tag:

HTML:
  1.  
  2. <article id="comment-2">
  3.   <header>
  4.     <h4><a href="#comment-2" rel="bookmark">Comment #2</a>
  5.         by <a href="http://example.com/">Jack O'Niell</a></h4>
  6.     <p><time datetime="2007-08-29T13:58Z">August 29th, 2007 at 13:58</time>
  7.   </p></header>
  8.   <p>That's another great article!</p>
  9. </article>
  10.  

And in general, Lachlan walks through how the pieces work together, including the video and audio tags.

Posted by Dion Almaer at 5:57 am
21 Comments

++++-
4.3 rating from 36 votes

Tuesday, November 13th, 2007

HTML5 Media Support: video and audio tags and scriptability

Category: HTML, JavaScript, Safari

WebKit keeps on trucking and has added support for the HTML 5 media tags such as <video> and <audio>.

You can add video to a page as easily as:

HTML:
  1.  
  2. <video src="sample.mov" autoplay></video>
  3.  

That is a lot cleaner than the mess of embed/object/JavaScript wrappers that we have today. Also, there is nice scripting support so you can play/pause a video:

HTML:
  1.  
  2. function playPause() {
  3.   var myVideo = document.getElementsByTagName('video')[0];
  4.   if (myVideo.paused)
  5.     myVideo.play();
  6.   else
  7.     myVideo.pause();
  8. }
  9. </script>
  10. <input type=button onclick="playPause()" value="Play/Pause"/>
  11.  

You can also tie into events:

JAVASCRIPT:
  1.  
  2. myVideo.addEventListener('ended', function () {
  3.   alert('video playback finished')
  4. } );
  5.  

and programatically do your thing:

JAVASCRIPT:
  1.  
  2. new Audio("song.mp3").play();
  3.  

One key issue has always been the codec game and royalties to mpeg.

Posted by Dion Almaer at 7:46 am
14 Comments

++++-
4.4 rating from 38 votes

Wednesday, October 24th, 2007

HTML5 Wrapper for Gears Database Component

Category: HTML, Gears

Dimitri Glazkov took a look at the HTML 5 SQL Storage API which WebKit just implemented and put together a Gears wrapper.

As an example he has Stickies running on Firefox with Gears.

The bridge is very simple indeed. Just take a peek at the code.

The major note here is that the current draft HTML 5 spec has the SQL API as an asynchronous one, whereas Gears has a synchronous API. In my experience, people prefer synchronous here, and Adobe AIR has a new synchronous API that they just released with the latest beta. I would love to see the HTML 5 spec contain a synchronous version too.

Posted by Dion Almaer at 8:49 am
3 Comments

+++--
3 rating from 14 votes

Friday, October 19th, 2007

Relative URLs as //ajaxian.com

Category: HTML, Tip

I had never thought to use relative URLs that are just relative to the protocol scheme as Ned Batchelder explains in his post on Http-https transitions and relative URLs.

HTML:
  1.  
  2. <img src='//fast.cdn.net/pix/smiley.jpg' />
  3.  

Who knew.

Posted by Dion Almaer at 11:00 am
6 Comments

+----
1.8 rating from 123 votes

Wednesday, August 22nd, 2007

Is the iPhone the IE4 of 2007? Sheesh

Category: HTML