Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.


  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • DownloadDownload
  • PrintPrint
Share this Page URL
Help

4. HTML5 Hypermedia > Designing the Microblog Media Type

Designing the Microblog Media Type

The aim of this example is to illustrate the process of designing hypermedia types using HTML5 as the base format. Unlike the previous examples, which were based on XML and JSON (both formats devoid of native hypermedia controls), this example starts with a format that already supports basic hypermedia factors.

Starting with HTML5 provides both advantages and drawbacks when designing a hypermedia solution. The good news is the details of document design (which elements are valid, etc.), the specific hypermedia controls, and the method of expressing state transitions are already decided. This means designers do not need to worry about how to define and document much of the hypermedia type. However, with so many details already decided, there is less room for expressing the problem domain in ways clients can easily understand.

This duality of well-defined hypermedia controls and a limit on the options for expressing the problem domain is the key challenge behind working with existing hypermedia types and is, in part, the reason so few new APIs use HTML5 as the base. For many, it seems easier to start from zero using a non-hypermedia type such as XML or JSON and create all of the details from the beginning. But sometimes this option is not available to designers. Instead, designers often must be sure their implementations work well with existing clients (e.g. web browsers) with little or no support from custom scripting or other client-side plug-ins.

Expressing Application Domain Semantics in HTML5

In cases where the design needs to rely on existing hypermedia types like HTML5, a different approach is needed to express domain semantics. Instead of creating new elements (as in XML) or objects (as in JSON), domain semantics must be expressed using existing HTML5 elements (<article>, <section>, <p>, <span>, etc.). Instead of creating new state transition and process flow elements, designers need to use those already available in HTML5 (<form>, <input>, <a>, etc.).

However, it is still important to know the semantic value (the meaning in relation to the problem domain) of each of these already-defined elements. Instead of creating an <email> element or <update-user> transition block, designers need to use existing features of HTML5 to add semantic meaning to the representations. The way to do this is to use key HTML5 attributes to decorate the existing elements. These attributes are:

id

Used to identify a unique data element/block within the representation

name

Used to identify a state transition element (i.e. input) within the representation

class

Used to identify a non-unique data element/block within the representation

rel

Used to identify a non-unique process flow element within the representation

The id attribute can be applied to any element in the document, is a single string value (no spaces allowed), and must be unique in a document:

<span id="invoice-001">...</span>

The name attribute is also a single string value (without spaces). It can be assigned to a limited set of elements (those associated with input), and multiple elements within the same document can share the same value:

<label>Enter first invioce:</label><input name="invoice">...</input>
<label>Enter second invoice:</label><input name="invoice">...</input>

The class attribute can be applied to any element in the document, can appear on several elements within the document, and allows multiple values to be applied as long as they are separated by a space. This makes it possible to mark several document elements with the same value as well as mark the same element with several values:

<span class="important invoice overdue">...</span>
<span class="invoice pending">...</span>

The rel attribute has features of both the class and name attributes. Like the name attribute, a rel can only appear on a limited set of elements (those associated with links) and need not be unique within the document. Also, like the class attribute, the rel supports multiple strings separated by spaces:

<a href="..." rel="invoice">...</a>
<a href="..." rel="invoice overdue">...</a>

Through the proper application of these four attributes to a wide range of existing HTML5 elements, it is possible to adequately express any problem domain details within a hypermedia type design. It is worth noting that each of the above attributes has slightly different rules in HTML5.

Microformat, Microdata, and RDFa

The process of expressing application semantics using the id, name, class, and rel attributes of HTML5 described here is based loosely on the Microformat design principles. Microformat design patterns rely primarily on the class attribute, but also use the id, name, rel, and rev attributes. The author’s method, while similar to Microformats, does not always follow the design patterns used in many published Microformats.

There are additional ways to add semantic information to HTML representations. At the time of this writing, the W3C has a draft specification for Microdata. Microdata consists of a group of items, each with a set of name-value pairs. These items can be nested, too. RDFa is a W3C specification that uses attributes to embed semantic data within markup languages, including the HTML family. As the name suggests, RDFa is a way to apply the principles of the Resource Description Framework to markup via attributes.

The primary aim here is to introduce the reader to the notion of adding semantic details to existing media types. It is beyond the scope of this text to cover these various standards for adding semantic information to documents. Instead these specifications are mentioned here in order to encourage the reader to explore them, and any other related standards, and learn the strengths and shortcomings of each. In the end, which method is used to add application domain semantics to a media type design choice is influenced by the preferences of both the media type author and the community (client and server developers, end users, etc.) for which the media type is created.

Identifying the State Transitions

Just as in other base formats, a key step in implementing a hypermedia design using HTML5 is the process of identifying the needed state transitions. As has already been stated above, this example implements the basic features of a microblogging application. Below is a set of states that need to be represented:

  • The list of users

  • A single user

  • The list of messages

  • A single message

  • The list of possible queries (search users, view the user’s list of followers, etc.)

  • A template for creating a new user

  • A template for updating an existing user

  • A template for following an existing user

  • A template for searching for existing users

  • A template for adding a new message

  • A template for replying to an existing message

  • A template for searching for existing messages

As may be evident to the reader at this point, the above list identifies three unique block types within a representation (users, messages, queries) and seven transition blocks (create user, update user, follow user, search user, add message, reply to a message, and search messages). The unique blocks can be expressed using HTML5’s <div> element and the transition blocks can be expressed using the <form> element. Each of these blocks will have a number of child elements.

Note

The usual error representation has been left out of this design to save time and reduce repetition of the same material. When creating a complete design for production use, you should always include an error representation.

The details of these element blocks can easily be expressed in short HTML5 examples. These examples will serve as reference material when creating the application profile later in this chapter (see The Microblog Application Profile).

State blocks

This example identifies three main types of content that may appear within a representation: users, messages, and queries. These can be expressed as HTML5 <div> elements with unordered lists (<ul>, <li>) and other child elements. Below are examples of each of the three main content blocks.

Users

There are two ways to represent users within this design: as a list of users and as a single user.

The list of users is represented using an HTML5 unordered list:

<!-- representing a list of users -->
<div id="users">
  <ul class="all">
    <li>
      <span class="user-text">User1</span>
      <a rel="user" href="..." title="profile for User1">profile</a>
      <a rel="messages" href="..." title="messages by User1">messages</a>
    </li>
    ...
    <li>
      <span class="user-text">UserN</span>
      <a rel="user" href="..." title="profile for UserN">profile</a>
      <a rel="messages" href="..." title="messages by UserN">messages</a>
    </li>
  </ul>
</div>

A single user is represented in a similar way:

<!-- representing a single user -->
<div id="users">
  <ul class="single">
    <li>
      <img class="user-image" src="..." alt="image of User1"/>
      <a rel="user" href="..." title="profile for User1">
        <span class="user-text">User One</span>
      </a>
      <span class="description">
        I am known to all as User One
      </span>
      <a rel="website" href="..." title="website">
        User1's web site
      </a>
      <a rel="messages" href="..." title="messages by User1">messages</a>
    </li>
  </ul>
</div>

Messages

Messages can also be represented in two ways (as a list and as a single message).

Here is the list representation:

<!-- representing a list of messages -->
<div id="messages">
  <ul class="all">
      <li>
        <span class="message-text">
          this is a message
        </span>
        @
        <a rel="message" href="..." title="message">
          <span class="date-time">
            2011-08-17 04:04:09
          </span>
        </a>
        by
        <a rel="user" href="..." title="User1">
          <span class="user-text">User1</span>
        </a>      
      </li>
      ...
      <li>
        <span class="message-text">
          this is also a message
        </span>
        @
        <a rel="message" href="..." title="message">
          <span class="date-time">
            2011-08-17 04:10:13
          </span>
        </a>
        by
        <a rel="user" href="..." title="UserN">
          <span class="user-text">UserN</span>
        </a>      
      </li>
  </ul>
</div>

And here is the way a single message is represented:

<!-- representing a single message -->
<div id="messages">
  <ul class="single">
    <li>
      <span class="message-text">
        This is a message
      </span>
      <span class="single">@</span>
      <a rel="message" href="..." title="message">
        <span class="date-time">
          2011-08-17 04:04:09
        </span>
      </a>
      <span class="single">by</span>
      <a rel="user" href="..." title="User1">
        <span class="user-text">User1</span>
      </a>
    </li>
  </ul>
</div>

Queries

This design uses a small set of simple queries. These are just links that return the list of messages, users, or the registration page:

<!-- representing the queries list -->
<div id="queries">
  <ul>
    <li><a rel="messages-all index" href="..." title="Home page">Home</a></li>
    <li><a rel="users-all" href="..." title="User List">Users</a></li>
    <li><a rel="register" href="..." title="Register">Register</a></li>
  </ul>
</div>

Note that the first link in the list has two values for the rel attribute.

Transfer blocks

This example identifies seven client-initiated state transfers. Each of them can be expressed as HTML5 <form> elements with <input> child elements. Below are each of the transfer blocks along with the details for each child element.

Create new user

The server will include this block in the representation to allow clients to create a new microblog user:

<!-- state transfer for adding a new user -->
<form method="post" action="..." class="user-add">
  <input type="text" name="name" value="" required="true"/>
  <input type="text" name="email" value="" required="true"/>
  <input type="password" name="password" value="" required="true" />
  <textarea name="description"></textarea>
  <input type="file" name="avatar" value="" />
  <input type="text" name="website" value="" />
  
  <input type="submit" value="Send" />
</form>

Notice that some fields are grouped under the SHOULD keyword and others are under the MAY keyword. These are just comments to indicate which fields “should” be returned by the server and which ones “may” be returned by the server. These annotations will be used later when writing up the documentation.

Update existing user

Once a user has been created, it should be possible to update that user account:

<!-- state transfer for updating an existing user -->
<form method="post" action="..." class="user-update">
  <input type="text" name="name" value="" required="true"/>
  <input type="text" name="email" value="" required="true"/>
  <input type="password" name="password" value="" required="true"/>
  <textarea name="description"></textarea>
  <input type="file" name="avatar" value="" />
  <input type="text" name="website" value="" />
  
  <input type="submit" value="Send" />
</form>

It is likely that update transitions will be prepopulated with existing data. It is also possible that one or more of the <input /> elements will be marked as read-only by the server. These details will be left up to each server implementation to determine.

Follow a user

Following a user is as simple as sending the identifier of the user you wish to follow:

<!-- state transition to follow an existing user -->
<form method="post" action="..." class="user-follow">
  <input type="text" name="user" value="" required="true"/>
  
  <input type="submit" value="Send" />
</form>

You may notice that there is nothing in the above transition to indicate the current user that wants to follow the identity in the user input element. For all of the transition examples shown here, the server is assumed to be able to know (when it is important) the identity of the current (or logged-in) user. This can be done via information in the action URI or via control data (HTTP Headers) such as the Authorization header or the Cookie header (see Current user and state data for details).

Search for users

Here is the transition block for searching for users:

<!-- state transfer for searching users -->
<form method="get" action="..." class="user-search">
  <input type="text" name="search" value="..." required="true"/>
  
  <input type="submit" value="Send" />
</form>

Since this is a search action, the method attribute is set to GET, not POST.

Add a new message

Adding a new message is also a simple state transfer:

<!-- state transfer for adding a message -->
<form method="post" action="..." class="message-post">
  <textarea name="message" requried="true"></textarea>
  
  <input type="submit" value="Send" />
</form>

Reply to an existing message

Replying to an existing message involves sending both the original user identifier and any reply text, which may include the original message text, to the server:

<!-- state transfer for replying to a message -->
<form method="post" action="..." class="message-reply">
  <input type="hidden" name="user" value="..." requried="true"/>
  <textarea name="message"></textarea>
  
  <input type="submit" value="Send" />
</form>

Search for messages

The message search transfer block is almost identical to the one used for user searches:

<!-- state transfer for searching messages -->
<form method="get" action="..." class="message-search">
  <input type="text" name="search" value="..." requried="true"/>
  
  <input type="submit" value="Send" />
</form>

Selecting the Basic Design Elements

Since the point of this chapter is to cover implementation details when using HTML5, the remaining standard design elements have already been decided. However, it is still valuable to go over each of them here.

Using HTML5 as the base format means that the State Transfer style will be ad hoc. HTML5 Forms will be used to make all client-imitated transfers via GET (read-only) or POST (add/update). Even though the ad hoc style is used in HTML5, designers can still establish required and optional inputs in their hypermedia design. In this example, the design uses both.

The domain style of HTML5 is agnostic. The element and attribute names are all independent of any domain semantics. However, as mentioned earlier in this chapter (see Expressing Application Domain Semantics in HTML5), HTML5 supports domain semantic expression using common attribute values (id, name, class). Finally, the Application Flow style for HTML5 is applied via values for the rel attribute on href tags.

Note

Usually hypermedia designs use the rel attribute (or its equivalent in the data format) to mark all state transitions, including ones that require arguments. However, HTML5 does not support the rel attribute on the form element. For this reason, transitions that require arguments (e.g. forms) will be marked with a class attribute instead.

Although HTML5 is a domain-agnostic base format, the built-in state transfer and application flow elements make most of the design details very easy. The only creative work that needs to be done is arranging existing HTML5 elements (article, section, div, p, span, etc.) and decorating them with the necessary attributes (id, name, class, rel).

The application of these attribute decorations is covered in the next section.

The Microblog Application Profile

Since HTML5 is a domain-agnostic media type, all domain-specific information (both the data elements and the transition details) needs to be specified as additional information in each representation. As has already been pointed out earlier in this chapter (see Expressing Application Domain Semantics in HTML5), in HTML5 you can express domain-specific information using a set of attributes (id, name, class, and rel).

Also, this implementation will require users to log in before posting new messages. That means the implementation will need to be able to identify the current logged-in user.

Current user and state data

This example implementation will rely on HTTP’s Authorization header to identify the currently logged-in user. That means this example server will use HTTP Basic Authentication for selected state transitions (Update a User, Follow a User, Add a New Message, and Reply to a Message). It is important to point out that user identification is not specified in the media type design; it is an implementation detail left to servers and clients to work out themselves.

The decision to leave user authentication independent of the media type has a number of advantages. First, this allows clients and servers to negotiate for an appropriate authentication scheme at runtime (the HTTP WWW-Authenticate head is used to advertise supported authentication schemes). Second, leaving it out of the media type means that servers are free to establish and transition details on their own. For example, Open Auth (OAuth) has a set of requirements for interacting with more than one web server in order to complete authentication. Finally, leaving authentication details out of the media type design allows servers to take advantage of whatever means may become available in the future.

ID attribute values

This design relies on three unique identifiers for representations:

messages

Applied to a div tag. The list of messages in this representation. This list may contain only one message.

queries

Applied to a div tag. The list of valid queries in this representation. This is a list of simple queries (represented by the HTML anchor tag).

users

Applied to a div tag. The list of users in this representation. This list may contain only one user.

Class attribute values

There are a number of class attributes that can appear within a representation. Clients should be prepared to recognize the following values:

all

Applied to a UL tag. A list representation. When this element is a descendant of DIV.id="messages" it MAY have one or more LI.class="message" descendant elements. When this element is a descendant of DIV.id="users" it MAY have one or more LI.class="user" descendant elements.

date-time

Applied to a SPAN tag. Contains the UTC date-time the message was posted. When present, it SHOULD be valid per RFC3339.

description

Applied to a SPAN tag. Contains the text description of a user.

friends

Applied to a UL tag. A list representation. When this element is a descendant of DIV.id="messages" it contains the list of messages posted by the designated user’s friends and MAY have one or more LI.class="message" descendant elements. When this element is a descendant of DIV.id="users" it contains the list of users who are the friends of the designated user and MAY have one or more LI.class="user" descendant elements.

followers

Applied to a UL tag. A list representation of all the users from the designated user’s friends list. MAY have one or more LI.class="user" descendant elements.

me

Applied to a UL tag. When this element is a descendant of DIV.id="messages" it contains the list of messages posted by the designated user and MAY have one or more LI.class="message" descendant elements. When this element is a descendant of DIV.id="users" it SHOULD contain a single descendant LI.class="user" with the designated user’s profile.

mentions

Applied to a UL tag. A list representation of all the messages that mention the designated user. It MAY contain one or more LI.class="message" descendant elements.

message

Applied to an LI tag. A representation of a single message. It SHOULD contain the following descendant elements:

SPAN.class="user-text"
A.rel="user"
SPAN.class="message-text"
A.rel="message"

It MAY also contain the following descendant elements:

IMG.class="user-image"
SPAN.class="date-time"
message-post

Applied to a FORM tag. A link template to add a new message to the system by the designated (logged-in) user. The element MUST be set to FORM.method="post" and SHOULD contain a descendant element:

TEXTAREA.name="message"
message-reply

Applied to a FORM tag. A link template to reply to an existing message. The element MUST be set to FORM.method="post" and SHOULD contain the following descendant elements:

INPUT[hidden].name="user" (the author of the original post)
TEXTAREA.name="message"
single

When this element is a descendant of DIV.id="messages" it contains the message selected via a message link. SHOULD have a single LI.class="message" descendant element. When this element is a descendant of DIV.id="users" it contains the user selected via a user link. SHOULD have a single LI.class="user" descendant element.

messages-search

Applied to a FORM tag. A link template to search of all the messages. The element MUST be set to FORM.method="get" and SHOULD contain the following descendant elements:

INPUT[text].name="search"
message-text

Applied to a SPAN tag. The text of a message posted by a user.

search

Applied to a UL tag. A list representation. When this element is a descendant of DIV.id="messages" it contains a list of messages and MAY have one or more LI.class="message" descendant elements. When this element is a descendant of DIV.id="users" it contains a list of users and MAY have one or more LI.class="user" descendant elements.

shares

Applied to a UL tag. A list representation of all the messages posted by the designated user that were shared by other users. It MAY contain one or more LI.class="message" descendant elements.

user

Applied to an LI tag. A representation of a single user. It SHOULD contain the following descendant elements:

SPAN.class="user-text"
A.rel="user"
A.rel="messages"

It MAY also contain the following descendant elements:

SPAN.class="description"
IMG.class="avatar"
A.rel="website"
user-add

Applied to a FORM tag. A link template to create a new user profile. The element MUST be set to FORM.method="post" and SHOULD contain the following descendant elements:

INPUT[text].name="user"
INPUT[text].name="email"
INPUT[password].name="password"

It MAY also contain the following descendant elements:

TEXTAREA.name="description"
INPUT[file].name="avatar"
INPUT[text].name="website"
user-follow

Applied to a FORM tag. A link template to add a user to the designated user’s friend list. The element MUST be set to FORM.method="post" and SHOULD contain the descendant element:

INPUT[text].name="user"
user-image

Applied to an IMG tag. A reference to an image of the designated user.

user-text

Applied to a SPAN tag. The user nickname text.

user-update

Applied to a FORM tag. A link template to update the designated user’s profile. The element MUST be set to FORM.method="post" and SHOULD contain the following descendant elements:

INPUT[hidden].name="user"
INPUT[hidden].name="email"
INPUT[password].name="password"

It MAY also contain the following descendant elements:

TEXTAREA.name="description"
INPUT[file].name="avatar"
INPUT[text].name="website"
users-search

Applied to a FORM tag. A link template to search of all the users. The element MUST be set to FORM.method="get" and SHOULD contain the descendant element:

INPUT[text].name="search"

Name attributes values

HTML5 uses the name attribute to identify a representation element that will be used to supply data to the server during a state transition. Clients should be prepared to supply values for the following state transition elements:

description

Applied to a TEXTAREA element. The description of the user.

email

Applied to an INPUT[text] or INPUT[hidden] element. The email address of a user. When supplied, it SHOULD be valid per RFC5322.

message

Applied to a TEXTAREA element. The message to post (for the designated user).

name

Applied to an INPUT[text] element. The (full) name of a user.

password

Applied to an INPUT[password] element. The password of the user login.

search

Applied to an INPUT[text]. The search value to use when searching messages (when applied to FORM.class="message-search") or when searching users (when applied to FORM.class="users-search").

user

Applied to an INPUT[text] or INPUT[hidden] element. The public nickname of a user.

avatar

Applied to an INPUT[file] element. The image for the user.

website

Applied to an INPUT[text]. The URL of a website associated with the user profile. When supplied, it SHOULD be valid per RFC 3986.

Rel attribute values

This design also identifies a number of possible simple state transitions, or static links, that may appear within representations. These will appear as HTML anchor tags with the following rel attribute values:

index

Applied to an A tag. A reference to the starting URI for the application.

message

Applied to an A tag. A reference to a message representation.

message-post

Applied to an A tag. A reference to the message-post FORM.

message-reply

Applied to an A tag. A reference to the message-reply FORM.

message-share

Applied to an A tag. A reference to the message-share FORM.

messages-all

Applied to an A tag. A reference to a list representation of all the messages in the system.

messages-search

Applied to an A tag. A reference to the messages-search FORM.

user

Applied to an A tag. A reference to a user representation.

user-add

Applied to an A tag. A reference to the user-add FORM.

user-follow

Applied to an A tag. A reference to the user-follow FORM.

user-update

Applied to an A tag. A reference to the user-update FORM.

users-all

Applied to an A tag. A reference to a list representation of all the users in the system.

users-friends

Applied to an A tag. A reference to list representation of the designated user’s friend users.

users-followers

Applied to an A tag. A reference to list representation of the users who follow the designated user.

users-search

Applied to an A tag. A reference to the users-search FORM.

website

Applied to an A tag. A reference to the website associated with a user.