An Exploration of HTML 5


HTML 5 Fist
Photo from justinsomnia
Original t-shirt version

 

At the Confoo.ca conference in Montreal, Quebec, Mark Pilgrim of Google gave an impressive keynote providing an overview of the current state of HTML 5. The information in this post was inspired by his comphehensive talk. Are you wondering what is currently available in HTML 5 and if you can start using it? Take a look at ishtml5readyyet.com or ishtml5ready.com to get your answer.

 

If you take a look at ishtml5ready.com in a browser that supports HTML 5 you’ll see that HTML 5 is somewhat ready. That is, some browsers provide some current support for HTML 5. But that shouldn’t stop us from playing around with it right?

 

HTML5 is a container term used to describe a technology bundle that makes up the new standard. What HTML 5 really encapsulates is HTML 5, CSS 3, and JavaScript all thrown together into the pleasantly marketeering term that is HTML 5. Did you look at those links above in Internet Explorer? Well I’m afraid you’re out of luck for the time being. The A-grade browsers that are currently supporting some of the features of HTML 5 include Safari, Chrome, Firefox and Opera. Still want to use HTML 5 in IE? If you simply put the term “HTML5 elements in IE” (linked directly to Yahoo! Search because I know you all use it right?) into your favorite search engine you’ll get a nice wrapper on how to do this.

 

Let’s explore a few of the great improvements coming in HTML 5:

 

Grouping Tags
There are a number of new tags available for all of your tag grouping needs. <hgroup> is used for defining logical groups of tags or sections on your page, <nav> is present to define navigation systems – great for search engines to easily define your site structure. Tags such as <section>, <article> and <aside> can be used for data grouping. Properly using these tags can help you easily define the sections and most important content of your page. This helps search engine crawlers pick up the structure of your website.

 

Form Elements and Attributes
Forms have received quite a nice overhaul in HTML 5 with new features and methods for defining what data truly is. Let’s take a look at these changes:

  • Sliders: Creating a simple slider within a form is as simple as defining <input type=”range” …> – no more JavaScript needed.
  • Auto Focus: If you need to autofocus the user directly on a part of your form when they first come to your site (plea: please don’t) then the autofocus parameter of an input field is ready to do the dirty work. Simply use the format <input autofocus …> and you’re ready to go. This standardizes the approach so that websites no longer have to use a level of JavaScript interaction to accomplish the same task.
  • Placeholder Text: In an input field, it’s sometimes neccessary to guide your users to input the values you expect, using the value attribute (e.g., add mm/dd/yyyy for them to define a date). This usually involves adding a click event with JavaScript such as this.value = “” to purge the input when the user clicks on it. Then you need some alternate logic to put the placeholder back when the focus is no longer on the input and the user didn’t type anything. This is where the placeholder attribute comes in. Using the form of <input placeholder=”some text” …> the input box will take care of this for you. You have a populated value of “some text.” When the user clicks on the input it disappears, then reappears when the user clicks off of the input and there is no text. Simple yet brilliant. (Currently works in 2 browsers.)
  • Calendar Picker: Prior to HTML 5, calendar pickers in forms were non-standard and usually involved some fairly hefty JavaScript components or libraries to build the functionality. In HTML 5, we have a new input type called datetime, used in the form of <input type=”datetime” …>. This generates a standard input form for the user. When a user clicks on it, it pops up a calendar picker widget automatically. Less code is always a win.
  • Multiple File Uploader: Extending upon the file type of an input field, a new “multiple” property implementation allows you to specify multiple files for upload and takes the form of <input type=’file’ multiple …>. When selecting multiple files, you should display “N files” in the input box, instead of the single filename. (Currently works only in Safari.)
  • Yet More Input Types: There are even more input types that you can logically define. type=”email” and type=”url” are definitions you can explore to define the data that users will input into your forms.

 

Simply put, forms make sense now. No need to heavily augment a form with layers of visualization and JavaScript just to allow data to be defined as it should be in the first place, or to allow base levels of functionality that everyone uses anyway. If you want to see what your current browser supports, take a look at www.miketaylr.com/code/input-type-attr.html.

 

Accessibility
HTML 5 has not forgotten about improving web accessibility. ARIA (Accessibly Rich Internet Applications) defines methods for building websites and web applications in a way that make them more accessible to people wth disabilities. One way HTML 5 endeavors to improve ARIA capabilities is through the use of the role=’group’ attribute, which will allow screenreaders to properly define group content. For a more comprehensive look at common ARIA attributes, take a look at dev.w3.org/html5/markup/aria/aria.html or search for “ARIA accessibility” in your favorite search engine.

 

Web Fonts
From the time I first started developing web applications I knew that font support was a joke and never functioned as it should have (great idea – bad implementation). Well, this fact is no longer true, I am happy to say. Web fonts finally work, allowing you to define your own font faces, even if all browsers have different implementations. For more information, take a look at Paul Irish’s post: Bulletproof @font-face syntax.

 

Video and Audio
HTML 5 video tag screenshot from YouTube
Video is now scriptable, folks. With the new <video> tag, you’ll be able to include a video player, implementing ogv & mp4 formats. You can now use DOM scripting to control video – mute, forward, stop – all through the DOM. The <audio> tag is there as well, to include audio files easily. If you want to see the video tag in action, go to youtube.com/html5 to opt in to HTML 5 standards beta. YouTube will not use the Flash player when video tag support is available in the browser and uses the HTML 5 video player instead. The video tag may be styled in exactly the same way as you would see with the standard Flash video players out there.

 

Freeform Drawing with Canvas
Have you ever wanted a blank canvas where you could programmatically draw anything within a website or web application? Well there are a number of server-side languages that do this – but have you ever wanted to do this through scripting (with a little bit of embedded JavaScript)? Well that’s where the <canvas> tag comes in. There are many canvas demos available for you to see exactly what can be done with the canvas tag by typing in “HTML5 canvas demos” in your favorite search engine. The code for creating a canvas and working with it is also very simple:

 

 

Using JavaScript, you can draw on the canvas:

 

 

More Information and Links
We’ve just scratched the surface of HTML 5 and all of the new functionality. There are some great resources available if you want to explore even further:

 

A big thanks to Mark Pilgrim for his talk at Confoo. I look forward to seeing the standard expanded and adopted by all the browsers out there.

 

- Jonathan LeBlanc

  • Share/Bookmark


Selecting a record with the next closest date using SQL


I have been recently working on a trip planner application where I have had to display the next trip that a user has coming up. This involved having to make a comparison between the starting date of the trip and the current date to find the trip that met this criteria. I thought I would share the basic query of how you can do this should anyone need to do accomplish a similar task.

 

Given the Following:
- My table name is trip_list
- The starting date of the trip (which we will compare) is named date_from
- The dates stored into the date_from field are stored in the format of dd-mm-yyyy

SELECT * FROM trip_list WHERE trip_list.date_from =
(SELECT MIN(trip_list.date_from) FROM trip_list WHERE
trip_list.date_from >= DATE_FORMAT(NOW(),'%d-%m-%Y'))

What I am doing here is selecting all columns in the table where the starting date is equal to the lowest date that is after the current date. At the end of the query I format the output of the current date to be dd-mm-yyyy for comparison since this is an application for the Australia / New Zealand region and that’s their date structure.

 

That’s all there is to it.

 

- Jonathan LeBlanc

  • Share/Bookmark


Fetching Viewer Social Data with OpenSocial 0.8


Profile information within a social network (e.g. MySpace, Orkut, YAP, Hi5) is something that users take painstaking amounts of time to input so that they can tell their friends and the world who they are. If a developer is building an application on one of these same platforms, that same profile detail is a gold mine of information that can be obtained to customize and personalize an application. Why would you ever ask a user to input their name, interests or gender if they already have this information freely available on their profile? Having the user re-enter this information is just asking for the user to drop off of your application. Using the knowledge wealth will both decrease user drop rates and make your applicatio more appealing to the masses.

 

Within a container that supports the OpenSocial 0.8 JavaScript specification, fetching the profile information of a person can be accomplished and customized with several steps.


The first thing we do is call newDataRequest to set up a new information request object within OpenSocial. Once this has been done we create our parameter list which will define what type of information we want to access within the information request. In our case here, we specify that we would like to capture “PeopleRequestFields”, namely a user’s “PROFILE_DETAILS”, and of those profile details we want to return the name and the thumbnail_url to their profile image. We can add in a whole series of profile information here, depending on what the container supports within the profile information specification. We then add to our request a newFetchPersonRequest and specify that we want the “VIEWER” profile (this could also be OWNER) and then input the params we set up to define what data we want from the viewer. Then we just name that request as “viewer_profile” so that we can access it later and send the request. The request function takes the name of the callback function as a parameter.


When the request completes and gets to our callback function, our data is returned to us with the profile information of the viewer presuming that everything completed correctly. In the callback we can call get on the returned data, inputting the name of the request, and then call getData on that. If we want a finer granularity of control over the data that is returned, we can then call the getField function with the information that we want (in this case the viewer name).

 

That’s all there is to it – with a few calls you now have all the information you need to personalize your application to every users that uses it.

 

Jonathan LeBlanc

  • Share/Bookmark


Working with a good (so far) WYSIWYG HTML editor


I’m sitting here hacking away at this custom visual HTML editor that I put together through some extensible JavaScript libraries – all the while the system is becomming more complex and…I must admit…I let it get a little out of control. In an effort to build as quickly as possible I broke some of my own rules and built this thing in a way that isn’t condusive for debugging or integrating new features.

 

So it’s a good thing I didn’t dump too much time into this project right? :) . Now I’m broadening my research a little bit and seeing what else may be out there on the interwebs that would be a good solution. What I just found and configured is FCKEditor (http://www.fckeditor.net/)…and I was hoping that it was available in PHP because that’s what I am currently building in. Well, kudos to this team because this is available in a bunch of languages – well done indeed. Configuration took no time at all and it seems to have excellent UTF8 support. UTF8 support…something that should be fairly trivial right? Well, it’s not something that many developers take into account when putting something together.

 

I’m not going to tout this tool as the be all end all of this project just yet, but I’ll explore it a bit more and see where it takes me. I’ll still need some custom file upload and file loading tools but I have those already thanks to the awesomeness of YUI. I’ll post more if this thing does everything I need of it.

 

- Jonathan LeBlanc

  • Share/Bookmark


Helpful YQL Queries


While I’ve been working with the Yahoo! Query Language, there are several queries that I have put together for different tasks which I wished to share.  These queries showcase some of the screen scraping and external file aggregation abilities of the platform.  All of these queries may be tested on the YQL console to see the output results. Below are a few of these queries:

 

Digg story headlines – Captures all page headlines

 

Flickr get photos in a set – Get number of photos

 

Flickr – Get photos on page 1 (60 per page)

 

Flickr – Get photos on page 2

 

Twitter – Get recent user tweets

 

Timezone from lat/lon – Get timezone data based on lat/lon

 

Flickr Connection Friend’s Photos – Capture photos for locations of user’s connections

 

Maps by Placemaker URL – Returns maps for all places found at a URL

 

- Jonathan LeBlanc

  • Share/Bookmark


Coupling YUI and YQL to build JavaScript Widgets


One of the tasks that I have been working on lately has been to create front-end JavaScript visualizations of YQL query results. What I ended up doing was creating a generic JavaScript include that uses YUI for some of the data parsing. Using this method, I set up a system where a developer could just include this JavaScript file, set up a few configuration variables and then a nice visualization widget would be displayed.

 

You can see a sample of the widget by going here: http://www.liquidmediatech.com/php_widget/yql_php_widget.html

 

Here’s what the full configuration for the widget looks like:

<!-- widget file include -->
<script type="text/javascript" src="yql_php_widget.js"></script>

<style>
div#badgeContainer{ padding:0 5px; font:bold 14px arial,helvetica,sans-serif; color:#f0f0f0; }
div#badgeContainer img{ float:left; margin-right:8px; margin-top:3px; border:0; }
div#badgeContainer span{ font-weight:normal; font-size:12px; }
div#badgeContainer a{ text-decoration:none; color:#f0f0f0; }
div#badgeContainer a:hover{ text-decoration:underline; }
div#widgetContainer{ background-color:#474747; width:300px; padding:5px 0; }
div#widgetContainer div.iconBox{ width:17px; height:16px; float:left; }
div#widgetContainer div.widgetRow{ padding:5px; background-color:#509cd1; border:1px solid #8fc5eb; margin:5px; overflow:hidden; }
div#widgetContainer div.widgetRow, div#widgetContainer div.widgetRow a{ color:#f0f0f0; font:11px arial,helvetica,sans-serif; }
div#widgetContainer div.widgetRow a{ font-weight:bold; }
</style>

<div id="widgetContainer"></div>

<script type="text/javascript">
var config = {'badge':true, 'num_results':10, 'debug':true};
var format = '<div class="widgetRow"><a href="{link}" target="_blank"><div style="background-color:#fff;border:2px solid #8fc5eb;width:20px;height:20px;float:left;margin-right:4px;"><img src="{loc_iconURL}" width="16" height="16" style="border:0;padding:2px;" /></div></a> <a href="{link}" target="_blank">{loc_longForm}</a><br />' + '{lastUpdated}</div>';
var yqlQuery = 'select lastUpdated, link, loc_iconURL, loc_longForm, profile_nickname, profile_profileUrl, publishedTime from social.updates where guid=me | sort(field="lastUpdated") | reverse()';
var insertEl = 'widgetContainer';
yqlWidget.push(yqlQuery, config, format, insertEl);
yqlWidget.render();
</script>

I have full documentation and the code base to set up this example on my github account at http://github.com/jonleblanc/yql-utilities/tree/master.

 

For a more in depth explanation of what was built out with this tool take a look at my post on the YUI blog at http://www.yuiblog.com/blog/2009/06/17/yui-and-yql/

 

- Jonathan LeBlanc

  • Share/Bookmark


YAP: Capturing Node X/Y Coordinates and Adding Mouse Events Using Caja Safe JavaScript


One of the requests that has come up while working with JavaScript on the Yahoo! Application Platform is: How do you assign an event to a DOM node which then captures the X/Y coordinates of that node under caja?

 

I put together a sample that will display how to assign a mouseover and mouseout event to a DOM node which will call functions to display a tool tip to the immediate right of the node. To do this we need to capture the x/y coordinates and width of that node to calculate the positioning offset. First we create the CSS and HTML for the nodes that will act as our event and tool tip containers.

 

<style type="text/css">
div#tooltip{ position:absolute; top:0; left:0; width:100px;
    height:40px; display:none; }
div#padNode{ position:relative; margin:50px; }
div#myContainer{ border: 1px solid #000000; padding: 10px;
    position: absolute; top: 50px; left: 50px;
    width: 200px; }
</style>

<div id="tooltip"></div>
<div id="padNode">
    <div id="myContainer">Container</div>
</div>

There are a few items to note about the above HTML:

  1. The tooltip container is an absolute positioned node that starts out hidden. The tooltip is placed at a root location so that the offset can be properly applied. We don’t want to embed this node within a positioned / floated container because that will affect our positioning offset location.
  2. The “myContainer” div is placed within a relative container with a margin – this is done to simulate embedded positioned nodes on a page.

Now, let’s look at the JavaScript:

<script type="text/javascript">
//assign mouse over handler to container
var myDiv = document.getElementById('myContainer');
if (myDiv.addEventListener) {
    myDiv.addEventListener('mouseover', overCallback, false);
    myDiv.addEventListener('mouseout', outCallback, false);
} else if (myDiv.attachEvent) {
    myDiv.attachEvent('mouseover', overCallback);
    myDiv.attachEvent('mouseout', outCallback);
}

//callback for mouseover - sender is the triggering event
function overCallback(sender){
    var target;

    //capture the object that the mouse over event was from
    if (window.event) {
        target = window.event.srcElement;
    } else if (sender) {
        target = sender.target;
    } else { return; }

    //get the top and left x / y coords of the target
    var nodeTop = target.offsetTop;
    var nodeLeft = target.offsetLeft;

    //if the node is within a parent container, loop through each parent
    //and add their height / width offsets to the top / left
    var nodeParent = target.offsetParent;
    if (nodeParent != target) {
        while (nodeParent) {
            nodeLeft += nodeParent.offsetLeft;
            nodeTop += nodeParent.offsetTop;
            nodeParent = nodeParent.offsetParent;
        }
    }

    //set tooltip data and display
    var tooltip = document.getElementById('tooltip');
    tooltip.innerHTML = "This is a tooltip";
    tooltip.style.display = "block";

    //set the tooltip top positioning to the same as the target node
    tooltip.style.top = nodeTop + "px";

    //set the tooltip left positioning to the end of the target node
    //(left location + width of the container)
    tooltip.style.left = (nodeLeft + target.offsetWidth) + "px";
}

//callback for mouseout
function outCallback(sender){
    //hide the tooltip
    document.getElementById('tooltip').style.display = "none";
}
</script>

Going from top to bottom, here’s what everything does:

 

Attaching Events
The first bit of code will check if addEventListener or attachEvent are available methods (basically checking if you are using IE or every other browser known to man). This block will then set up two events: The mouseover event on the “myContainer” node will call the function “overCallback” and the mouseout event on the node will call the function “outCallback”.

 

The MouseOver callback
In the function “overCallback” we have a few things going on. The function takes in one parameter, the event that was enacted on the node (so our mouseover event). Using this event we determine the node that the event was performed on. This will be valuable if you have multiple nodes all calling the same mouseover function. Next we capture the x/y (or top/left) offsets of the node from its current container (so the number of pixels from the 0,0 location of the “padNode” div.

 

But wait…the “padNode” div has a 50px margin from the 0,0 location of the overall container…so won’t the offsets be off by 50px? Yes, yes they will.

 

This leads us to our next block of code. While there is still a parent node to calculate we add the parent to child offset to our overall offset values. Basically what we’re doing here is looping through every container that the “myContainer” div is located within to get the “true offset” from the 0,0 position of the container itself.

 

Finally, we capture the tooltip node, set its content and display it. We then set the “top” pixel CSS offset of the tooltip to our calculated top offset. After that we set the “left” pixel CSS offset of the tooltip to our calculated left offset plus the width of the “myContainer” node so that it will display to the immediate right.

 

The MouseOut callback
There isn’t much to the mouseout callback…all we have to do is hide the tooltip container.

 

There you have it…we attach events to a node which then capture the true x/y position of that node to display a tool tip.

 

– Jonathan LeBlanc

  • Share/Bookmark


Automatically Updating the Small View for All Users in a YAP Application


In my last post I provided code to update the small view for an application on the Yahoo! Application Platform. The only current dropzone for these applications is on http://my.yahoo.com. In this tutorial I want to provide a method for developers to automatically update the small view for every user of their application without their interaction. With this script in place, you can run it within a cron job nightly so you can let technology do all the work for you.

 

Here’s a little overview of the application that I tied this functionality to (to see the application in action go to: http://apps.yahoo.com/-Oob7ZC78). I built out a weather application that allows users to set their city and get a simple weather forecast. On the small view I display a 4 day forecast and the current weather for the day. Since most users will only set their city on an infrequent basis and only interact with the small view regularly, I needed a way to update that cached small view on a daily basis. This would normally be done when a user goes to the large view of the application, but that was not acceptable in this case.

 

I have a basic mysql table that contains the GUID of the user to identify them, as well as their city search criteria to rebuild the user views with their selected city criteria. The basic table looks like this:

Table Structure

 

Now let’s take a look over the code that updates the small views based on the table data above. Here are the steps I’m taking:

  • Include the PHP SDK (Yahoo.inc), define your keys and application id, then instantiate a 2-legged OAuth session using new YahooApplication(…)
  • Set your database information, initialize the mysql database connection, set the SQL query and make the query using the mysql_query method
  • Set up the while loop to keep capturing the specific row as long as there are still hows to capture
  • Create your small view HTML using the data from the database – store it to a variable ($html)
  • Set the small view for the user GUID using the created small view HTML. Echo out a status message for some detail.

Let’s take a look at the code for this:

 

<?php
require_once('apis/Yahoo.inc');

//session information
define('API_KEY', 'KEY HERE');
define('SHARED_SECRET', 'KEY HERE');
define('APP_ID', 'APP ID HERE');

//instantiate session
$session = new YahooApplication(API_KEY, SHARED_SECRET, APP_ID);

//db information
$dbhostname = 'YOUR INFO';
$dbusername = 'YOUR INFO';
$dbpassword = 'YOUR INFO';
$dbname = 'YOUR INFO';

//for each user in the database, update the small view
mysql_connect($dbhostname, $dbusername, $dbpassword) OR DIE ('Unable to connect to database. Please try again later.');
mysql_select_db($dbname);
$query = "SELECT * FROM user_store";
$result = mysql_query($query);
while (($row = mysql_fetch_assoc($result)) !== false) {
    if ($row['uid'] && $row['search_type'] && $row['search_value']){
        //***********************************
        //Create HTML for the small view here
        //***********************************

        //set the small view of the current user $row['uid']
        //with the small view HTML stored in $html
        if (!$session->setSmallView($row['uid'], $html)){
            echo "NO SESSION SET FOR {$row['uid']}\n";
        } else {
            echo "SESSION SET FOR {$row['uid']}\n <div style='width:300px'>$html</div>";
        }
    }
}
?>

 

Now that we have the script ready, just set up a cron job to run through this script whenever you want to update the user content and that’s it…you now have an automated script that will keep the small view for all of your users up to date.

 

– Jonathan LeBlanc

  • Share/Bookmark