HOWTO: Saving bookmarks to del.icio.us

Now that we know how to build a simple form and help the user with their data entry, our next step is to do something useful with their input. We'll now extend our simple two field form to save the data the user has entered--a URL and a description--to the del.icio.us social bookmarking system.

If you're not familiar with del.icio.us then you'll find a link below to a description, along with instructions for obtaining an account that you can use with this tutorial. If you already have an account, then go right ahead and add the submission details.

(If you want to get the completed source code, it's available here.)

Tutorial reviewed 2006-12-06, by MB.

Overview of del.icio.us

If you haven't used del.icio.us before, it's an online link manager that allows you to save links to useful things on the web, along with a description (so you can remember what the link was about) and some tags (to help you group them). The great thing is that unlike the set of favourites that are stored by your browser and will only work with that specific browser, you can get to your del.icio.us links from anywhere.

(For some, the most interesting thing about del.icio.us is that all of your bookmarks are public. In other words, other people can see your links, and you can see theirs--what has been called social bookmarking.)

del.icio.us not only provides an extremely useful service, but it also has a non-browser based interface to that service; this type of arrangement is often called an API, and it means that we can build our own link manager using whatever tools we want, as long as we post the right values to the del.icio.us servers.

Since everyone posts to the same URLs, the del.icio.us API needs some way of telling which store to place the data in. It does this by requiring you to authenticate. This is handled for us by XForms, but if you want to follow on with this example, you'll need to create a del.icio.us account.

Getting a del.icio.us Account

If you don't already have one, you can obtain an account by going to the del.icio.us registration page.

Saving links to del.icio.us

To save links to del.icio.us we need to make an HTTP GET request to the following URL:

https://api.del.icio.us/v1/posts/add

The minimum parameters required are the URL of the link to be added, and a description. For example:

https://api.del.icio.us/v1/posts/add?url=http://skimstone.x-port.net&description=The+skimstone+site.

Other parameters can be added, and they include more detailed notes about the link, a space-separated list of tags, a timestamp, a flag to indicate whether to replace any pre-existing information (if there is any) and a flag to indicate whether to keep the link private.

Details of other commands that can be used with posts are at http://del.icio.us/help/api/posts.

Specifying submission requests

The del.icio.us API supports all sorts of methods for adding, deleting and retrieving your links. The particular method that we are interested in for the moment is add, which allows us to post new links to the store.

Although called an API, the actual interaction we have with del.icio.us is via simple HTTP requests. To add a link to the del.icio.us store for example, we need to send the correct information to the following URL:

http://del.icio.us/api/posts/add

The specific parameters del.icio.us needs from us to store a link, are:

  • url: the URL of the item;
  • description: a description of the item.

XForms will automatically create parameters in the request using the names that we use in the controls, so we made sure earlier to set the names in our input controls to be the same as for the del.icio.us add method:

<xf:input ref="url">
  <xf:label>URL:</xf:label>
</xf:input>
<xf:input ref="description">
  <xf:label>Description:</xf:label>
</xf:input>

All we have to do now is define the end-point for the request--where we want this data sent to. For this we use the XForms submission element, which is part of the XForms model. (The model provides us with a lot of features beyond just submitting data, and we'll see more of these later.)

To set up the request, insert the following model and submission elements into the head element in your form:

    </style>
    <xf:model>
      <xf:submission id="sub-add-link"
	action="http://del.icio.us/api/posts/add" method="get"
      />
    </xf:model>
  </head>

This gives us a request that will send the values in our two controls to del.icio.us, but we still need some way to kick off the submission.

The Submit Control

We created a submission that will send the data the user has entered to del.icio.us, and we gave it an id value of sub-add-link. We can now create a submit button that refers to this named submission, and when the user clicks on it, the data in the form will be sent to del.icio.us, as follows:

    <xf:submit submission="sub-add-link">
      <xf:label>Save</xf:label>
    </xf:submit>
  </body>
</html>

When you reload your form you'll notice that the submit button has been added, but it looks a little odd:

Screenshot of the del.icio.us form...but with a very wide submit button!

This is because the text in the submit button comes from a label just like any other form control, and we defined a CSS rule such that all labels should be 12em wide:

  xf\:label
  {
    width            : 12em;
    vertical-align   : middle;
    margin-right     : 0.2em;
  }

We can easily fix this by changing our CSS rule to be more specific; we'll make it apply only to labels that are children of input controls:

  xf\:input xf\:label
  {
    width            : 12em;
    vertical-align   : middle;
    margin-right     : 0.2em;
  }

Adding images to labels

Let's improve our button a little, and add the del.icio.us logo. Edit the label on the submit element to include an image tag:

    <xf:submit submission="sub-add-link">
      <xf:label>
        <img src="http://del.icio.us/static/img/delicious.gif" alt="" />
        Save
      </xf:label>
    </xf:submit>

Save and refresh, and you should see a much nicer looking button:

Screenshot of the del.icio.us form with the del.icio.us logo on the submit button

We can now move on to test everything.

Testing our Form by Saving a Bookmark

To test the form, get a URL for a document that you want to save for later. You could use a link to this tutorial:

http://www.formsPlayer.com/introduction-to-xforms

Enter this into the URL field, along with a brief description--something like:

An introduction to creating web applications with XForms.

Your form should now look like this, and be ready to send:

Screenshot of the del.icio.us form with data ready for saving.

When you press Save you'll be asked to log in. If you have used del.icio.us before, then you may already be logged in, but if not you will get a prompt similar to this:

Screenshot of the del.icio.us log-in prompt.

Once you've entered your information, you will see that the form is replaced with a simple success message to indicate that your link has been saved:

Screenshot of the del.icio.us success reply.

This is exactly how HTML forms work--the current page is replaced with a new one from the server--and is the default behaviour in XForms. However, we can do far more interesting things with submission, as we'll see later.

In the meantime, if you want to assure yourself that this worked, open your del.icio.us page in a new browser. You can find your page by making a URL from your login name and the del.icio.us home-page. For example, my page is:

http://del.icio.us/mark.birbeck

If you're happy that your link was saved, we can move on to add some more features to the form.

Required Values

Many of the forms that we fill in on the web are part of processes that require very specific data. It may be our credit card details or the time of the return flight, but whatever it is, nearly every form we fill in will have values that are required for some operation to complete successfully.

HTML forms don't allow us to specify which form controls must be completed, so there are generally two approaches that are taken. The first is to let the server check for the values after the user has completed the form, and the second is to add some script to the form to check all the required data is present, and prevent sending the data if it isn't.

Of course any significant process on a server is going to have to check the values anyway, but if we don't check the values in the web browser we will have made an unnecessary round-trip to the server, and provided our users with a poor experience.

However, although the alternative of using script improves the user experience, it ultimately suffers from the same problem that we keep coming back to; it relies on a technique that is non-standard, and available only to programmers.

XForms solves this problem by making this functionality available to mark-up authors via a simple attribute that indicates that some particular piece of data is required. The attribute is called required and it sits in the model, on an element called bind.

We'll illustrate the use of this property by indicating in our form that the URL and Description controls must be filled in (i.e., the items called url and description are required data). Before we show how to add these rules, try pressing Save with either of the two controls empty, and you'll see that del.icio.us objects:

Screenshot of the del.icio.us error message.

So, in order to prevent the submission if either URL or Description are empty, update the XForms model as follows:

    <xf:model>
      <xf:submission id="sub-add-link"
       action="http://del.icio.us/api/posts/add" method="get"
      />
      <xf:bind nodeset="url" required="true()" />
      <xf:bind nodeset="description" required="true()" />
    </xf:model>

Once you have added the above mark-up to your form, save and reload, and then try pressing the Save button without filling any data in. As long as one or other of the URL or Title controls are empty, nothing will happen, and you will never be able to post to del.icio.us.

Unfortunately, now if there is an error, nothing happens. In the next section we'll see how to tell our users that something has gone wrong.

Messages

Using the required property we have now been able to prevent any data being sent to del.icio.us if one or other of the obligatory fields is missing. However, as things stand the user of our form would be none the wiser as to what has gone wrong, and may even just keep pressing the Save button.

In HTML, the usual way to provide feedback to the user is to call the alert() function in script. This doesn't give us very rich messages though, so XForms solves this--in just the same ways as it did with hint and help which we discussed before--by providing the message element.

Let's see what a message that tells the user that they haven't entered enough information for the form to proceed, might look like:

<xf:message level="modal">
  Please ensure that you have entered both a
  URL <em>and</em> a description.
</xf:message>

The level attribute indicates what type of message we want, and in this case we're using a modal message, which halts processing until the user acknowledges it.

But when does this message get displayed to the user? As it stands, never. This is because the message element is one of a number of XForms handlers which will do a specific task, but will only do so when instructed to. However, we know when we want this action to be performed, and that is when there is an error on submission of the data; so to ensure that our message action is carried out we need to register for the notification that will be issued when a submission error occurs.

Registering for Events

It's extremely important in both Ajax and desktop applications to know how the submission of data is progressing. In XForms, information is provided to us both when the submission begins, and again when it ends.

The way in which all notifications happen in XForms is via events. A process will dispatch an event to any listener that registered for it, and this will in turn execute whatever actions have been marked up.

In the example we've been looking at we want to register to be notified if ever the xforms-submit-error event occurs on the submission labelled sub-add-link. The action we want to execute when this event does occur is to show a message. That may all sound very complicated, but in fact the mark-up to do this is as straightforward as adding the message handler as a child of the submission element:

    <xf:submission id="sub-add-link"
       action="http://del.icio.us/api/posts/add" method="get"
    >
      <xf:message level="modal" ev:event="xforms-submit-error">
        Please ensure that you have entered both a
        URL <em>and</em> a title.
      </xf:message>
    </xf:submission>

Making the message action a child of submission ensures that we are registered on the correct element, but we still need to say what event we are registered for, since there are many possible notifications. That's the purpose of the ev:event attribute, which specifies the event we're interested in--in this case xforms-submit-error.

One more thing to complete the mark-up is that ev:event is actually from a different language to XForms. We therefore need to ensure that the namespace for this language is at the top of our document:

<html
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ev="http://www.w3.org/2001/xml-events"
 xmlns:xf="http://www.w3.org/2002/xforms"
>
  .
  .
  .

Update your form to include this namespace definition and the changes to the submission element described above, and then reload. Now if you try to post to del.icio.us without any values in the URL or Description fields you should get something like this:

Screenshot of the error message telling the user that they need to provide the required fields

The Textarea Control

The XForms textarea control is used when the amount of text you want your users to enter is quite large, and you want to give them space to compose and manipulate their content. Typical uses would be content management systems, updating blogs, adding comments to a forum and so on. The control itself is used in the same way as the input control, so you can make use of features like hint and help.

In addition to the required fields url and description, the add method in the del.icio.us API has a number of optional parameters. Once of these is called extended, and allows the user to enter a much fuller description of the link.

Let's add a textarea for this, although we'll call it Description, and change the name of our current Description control to Title (it seems easier to understand than extended):

    <xf:input ref="description">
      <xf:label>Title:</xf:label>
      <xf:hint>Enter a <strong>title</strong> for the link</xf:hint>
    </xf:input>
    <xf:textarea ref="extended">
      <xf:label>Description:</xf:label>
      <xf:hint>Enter a <strong>description</strong> for the link</xf:hint>
      <xf:help>
        As well as providing a title for your link, del.icio.us
        allows you to add a full description.
      </xf:help>
    </xf:textarea>

(Note that we've also removed the help text from the description field, since 'Title' seems clear enough now.)

To fit in with the styling that we've been using--one control per row, a dotted line for the bottom border, etc.--you'll also need to add a CSS rule for textarea to the rules for input and output:

        xf\:input,
        xf\:textarea,
        xf\:output
        {
          .
          .
          .

Similarly, we'll need a rule for textarea labels:

        xf\:input xf\:label,
        xf\:textarea xf\:label
        {
          .
          .
          .

and finally, one to set the data-entry area of the textarea:

        .input-value,
        .textarea-value
        {
          .
          .
          .

If you reload your form, it should now look something like this:

Screenshot of the del.icio.us form with an xf:textarea control

Hiding and Revealing Controls

In our del.icio.us form we could make life easier for our users if we didn't show the Title control until the URL field was completed, and similarly we didn't show the Description control until both the URL and Title were filled in. We could also use the same rules to hide the submit button until there was enough data present to make submission possible.

This is possible in XForms by defining rules that say when a control should be relevant or not; it might be that certain fields are only relevant if someone is self-employed or the property they want to buy is a flat. By defining such rules, the controls on the form are revealed in stages as the user fills data in, making errors less likely, and improving the user experience. Let's see how this is done.

Specifying Relevance Rules

We saw earlier how we can use simple rules to indicate that some data values are required, which allowed us to prevent submission unless the values were present:

    <xf:model>
      .
      .
      .
      <xf:bind nodeset="url" required="true()" />
      <xf:bind nodeset="description" required="true()" />
    </xf:model>

A similar technique is used to say when a form control is relevant or not. For example, if the user indicates that they only want to buy a single train ticket, a rule can be set that stops the return date control from being shown.

To make the relevance of the description field dependent on the presence of a value in the URL item, add the following rule to the bind statements:

      <xf:bind nodeset="url" required="true()" />
      <xf:bind nodeset="description" required="true()" relevant="../url != ''" />
    </xf:model>

This simply says that the item description is only relevant if some data has been entered in the item url--i.e., url is not equal to the empty string.

Note the "../" in front of the reference to url; just as it does when changing directories on your disk-drive, ".." means 'go up a level'. We need to do this because the expressions used in @relevant and @required are calculated relative to the value inside @nodeset; since url sits on the same level as description, then to get to it we must go 'up' from description and then come back down again to get to url.

(We'll go into expressions in more detail in a later tutorial, but the long and the short of it is that if we just used the expression url without "../" then we would be making a reference to some data that was underneath the item description, rather than to data at the same level.)

The rule for extended is slightly longer, since we'll make that depend on both the url and description items having data:

      <xf:bind nodeset="url" required="true()" />
      <xf:bind nodeset="description" required="true()" relevant="../url != ''" />
      <xf:bind nodeset="extended" relevant="../url != '' and ../description != ''" />
    </xf:model>

XForms also allows us to tell our submit button to adopt the relevance properties of some named item. This is useful, since without this we wouldn't be able to show and hide buttons in the same way that we do other controls.

The rule we just created for extended--showing and hiding based on whether url and description have data in them--is ideal for the button that sends the data to del.icio.us, and we can use it as follows:

    <xf:submit submission="sub-add-link" ref="extended">
      <xf:label>Search</xf:label>
    </xf:submit>

Now the button will receive all of the same 'special' properties that the Extended control gets.

Styling Relevant and Non-relevant Controls

The result of the relevance rules that we've created is not actually to show and hide the controls, but rather to set a CSS pseudo-class on the controls. The pseudo-classes are :disabled and :enabled.

To hide all of our form controls when they are non-relevant (when their CSS pseudo-class is :disabled) we don't actually need to do anything, since the default CSS rule is:

  .pc-disabled
  {
    display          : none;
  }

Since this is formsPlayer's default we don't need to specify it in our stylesheets, but we're not limited just to showing and hiding controls, and we can use any CSS features. For example, if we would like to apply a yellow fade animation to controls as they become relevant, we can add the following to the list of style rules:

      .pc-enabled
      {
        -event-xforms-enabled : fx-Effect-Highlight();
      }
    </style>

Testing the controls

If you save and refresh your form, you will now see this:

Screenshot of del.icio.us form with only URL field enabled.

Now, to see how relevance works, enter something in the URL control. If you don't have anything convenient, the URL for this handbook is:

http://skimstone.x-port.net/introduction-to-xforms

After you tab away from the control you should see the Title field become available, and it has a yellow background to draw attention to the appearance of the new control:

Screenshot of del.icio.us form with the title field enabled, with fading yellow background.

The yellow background quickly fades away:

Screenshot of del.icio.us form with the title field enabled.

Now add a title. If you are saving a bookmark for this handbook, then the title is:

An introduction to creating web applications with XForms.

This time, after you tab away both the Description control and the Save button should become visible:

Screenshot of del.icio.us form with the description field enabled.

If you're saving a bookmark to this tutorial, your previous entry will be updated. Paste the following to the Description field:

XForms is an exciting new language from the W3C that
can be used to create anything from simple forms to complex Web
2.0 applications. XForms are dynamic, cross-platform, accessible,
script-free...and 100% standard.

This handbook covers everything you need to know to get started
with XForms.

Your form should now look something like this, and you can go ahead and save the link:

Screenshot of del.icio.us form with the submit button enabled.

The Date Control

Another piece of information that del.icio.us can store for us is a date value. We'll add a control for this to our form.

The first thing we need to do is add a new input control after the Description field, and before the Save button:

    </xf:textarea>
    <xf:input ref="dt">
      <xf:label>Date:</xf:label>
      <xf:hint>Enter a date to store with this link</xf:hint>
    </xf:input>
    <xf:submit submission="sub-add-link" ref="extended">

However, if you save and refresh you won't see anything remotely date-related--all you'll get is an ordinary input control. But to get a control that is geared towards accepting dates--a calendar widget--we don't change the control, but the data.

XForms makes extensive use of a model-view-controller (MVC) architecture. There's a lot written on the subject of MVC, and to be honest there's also a lot of disagreement as to the details. But for our purposes the main thing to understand is that it is a 'good thing' if the user interface changes the way it behaves depending on the data it is showing.

XForms does exactly this--if the item referenced by an input control is a date then we get a calendar widget, and if it is a boolean we get a check box. We don't need to change the controls--we just use a normal input--and everything else is done for us. This makes our applications cleaner and easier to maintain.

To indicate that dt is a date, place the following at the end of your current list of bind statements:

      <xf:bind nodeset="extended" relevant="../url != '' and ../description != ''" />
      <xf:bind nodeset="dt" type="xs:date" />
    </xf:model>

The type attribute is used to indicate the type of the data, and since the W3C's XML Schema specification already has definitions for data types like numbers and dates, XForms makes use of it. However, since it is prefixed with xsd we need to ensure that the namespace mapping is at the top of our document:

<html
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ev="http://www.w3.org/2001/xml-events"
 xmlns:xf="http://www.w3.org/2002/xforms"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  .
  .
  .

If you make these three changes--add the namespace declaration, the bind statement and the additional input control--and then save and reload the form, you will have something like this:

Screenshot of del.icio.us form with a calendar control

Note that the Date control is visible because we haven't added a relevant rule to hide it, yet. When you've had a good look at the calendar widget and seen what it can do, make a copy of the relevant rule for extended, and use it for the dt node:

      <xf:bind nodeset="extended"
        relevant="../url != '' and ../description != ''" />
      <xf:bind nodeset="dt" type="xs:date" relevant="../url != '' and ../description != ''" />
    </xf:model>

Once data is entered in the URL and Title fields, the other controls will be revealed:

Screenshot of del.icio.us form with a calendar control, after URL and title are entered.

The Select1 control

XForms provides two separate controls for selecting items from a list. The first is select, which presents a list to the user and allows them to choose as many items as they like, whilst the second is select1 which limits the user to one selection.

The del.icio.us add method has an optional parameter called replace which indicates whether the data being submitted should overwrite any existing data. If the value is anything but no then the data will be overwritten. We can provide the user with a way to set this value by using a select1 control.

The select1 control has all of the same features that an input has--such as hint, help, and so on--but in addition supports the item element to provide choices that the user is able to select from. For the del.icio.us form we need two choices, "yes" and "no".

The following mark-up gives us a select1 with these two choices, and a hint to help the user. Add it to your form, just before the submit button:

    </xf:input>
    <xf:select1 ref="replace">
      <xf:label>Replace:</xf:label>
      <xf:hint>
        Set this to <em>no</em> to prevent
        del.icio.us from overwriting a previous entry
        for the same link, if one exists.
      </xf:hint>
      <xf:item>
        <xf:label>Yes</xf:label>
        <xf:value>yes</xf:value>
      </xf:item>
      <xf:item>
        <xf:label>No</xf:label>
        <xf:value>no</xf:value>
      </xf:item>
    </xf:select1>
    <xf:submit submission="sub-add-link" ref="extended">

You'll also need to add the same relevance rule that we use for extended and dt, so that the control is hidden until a URL and a title have been entered:

      <xf:bind nodeset="extended" relevant="../url != '' and ../description != ''" />
      <xf:bind nodeset="dt" relevant="../url != '' and ../description != ''" />
      <xf:bind nodeset="replace" relevant="../url != '' and ../description != ''" />
      <xf:bind nodeset="dt" type="xsd:date" />
    </xf:model>

And finally, to get the formatting right, you'll also want to add to the CSS rules:

        xf\:input,
        xf\:select1,
        xf\:textarea,
        xf\:output
        {
          .
          .
          .
        }

        .input-value,
        .select1-value,
        .textarea-value
        {
          .
          .
          .
        }

        xf\:input xf\:label,
        xf\:select1 xf\:label,
        xf\:textarea xf\:label
        {
          .
          .
          .
        }

If you save the form and then refresh it in the browser, your form should look something like this:

Screenshot of del.icio.us form with a drop-box

The appearance attribute

The default display of the select1 that we just added was a drop-box. Howevever, often when there are only a couple of choices we would rather have them displayed as radio buttons. This is easily done in formsPlayer by adding the appearance attribute and giving it a value of full:

    <xf:select1 ref="replace" appearance="full">
      <xf:label>Replace:</xf:label>
      .
      .
      .
    </xf:select1>

Just to be clear, this attribute doesn't mean 'please give me radio buttons'--instead it informs an XForms processor that the author would like as many of the choices in the list to be available to the user as possible. Of course, how that actually pans out and gets implemented will be different on different systems; the effect of this on a voice-based XForms processor will be different to the effect on a GUI-based one, and different again to a mobile phone.

But the idea is that there is at least some similarity in the way this is implemented, and the author is in effect providing a 'hint' to the processor about what they would like to happen. In the case of formsPlayer, when appearance is set to full on a select1 then all of the options in the list are made available via radio buttons:

Screenshot of del.icio.us form with radio buttons

Setting Initial Values

Recall that the replace item is used to tell the del.icio.us servers whether it should overwrite any previous entry for the link we are submitting. We created a couple of radio buttons to allow us to set this value, but if you ran the form, or looked carefully at the screenshot, you might have noticed that none of the radio buttons had an initial value.

As it happens this is fine for del.icio.us, since it doesn't actually need this value--replace is only significant if it is present and set to "no". Still, so that we have something that we can use to illustrate the points, we'll pretend that the value of replace is important, and that we need to set a default value of "yes".

To set the value of an item in XForms, we use an action handler, called setvalue. (You met 'action handlers' before, when we looked at message.) The handler takes the ref attribute to indicate what item should have its value set, and the content of the element indicates the value that the item will be set to. In our case we want to set the value of replace to "yes", so we'll do this:

<xf:setvalue ref="replace">yes</xf:setvalue>

As with the message handler, this action won't actually do anything until it gets a signal. In the message example the 'signal' we chose to register for was the notification event that is given whenever there is a submission error. For our setvalue we'll also register for a notification event, and this time it's xforms-ready which is fired by an XForms processor once initialisation is complete. Place the following mark-up just before the closing tag of the model element:

      <xf:bind nodeset="dt" type="xsd:date" />
      <xf:setvalue ev:event="xforms-ready" ref="replace">yes</xf:setvalue>
    </xf:model>

Once again, save and reload and your form, and notice that the Replace control is initialised to "Yes".

The Select control

Whilst the select1 control allows the user to choose one option from amongst many, the select control allows multiple options to be picked. We'll illustrate the use of this control by providing a way for users to indicate the subject of the link. To begin with we'll assume that any links we save are about XForms, skiing or both:

  </xf:textarea>
  <xf:select ref="tags" appearance="full">
    <xf:label>Tags:</xf:label>
    <xf:hint>Enter some <em>tags</em> for the link</xf:hint>
    <xf:item>
      <xf:label>XForms</xf:label>
      <xf:value>xforms</xf:value>
    </xf:item>
    <xf:item>
      <xf:label>Skiing</xf:label>
      <xf:value>skiing</xf:value>
    </xf:item>
  </xf:select>
  <xf:input ref="dt">

As with the other controls we'll only allow the user to enter data into this one when a URL and title have been provided:

  <xf:bind nodeset="extended" relevant="../url != '' and ../description != ''" />
  <xf:bind nodeset="tags" relevant="../url != '' and ../description != ''" />
  <xf:bind nodeset="dt" type="xs:date" relevant="../url != '' and ../description != ''" />

Finally, we need to update the CSS rules:

        xf\:input,
        xf\:select,
        xf\:select1,
        xf\:textarea,
        xf\:output
        {
          .
          .
          .
        }

        .input-value,
        .select-value,
        .select1-value,
        .textarea-value
        {
          .
          .
          .
        }

        xf\:input xf\:label,
        xf\:select xf\:label,
        xf\:select1 xf\:label,
        xf\:textarea xf\:label
        {
          .
          .
          .
        }

Save the form, refresh your browser, and then enter a URL and a title, and when the hidden controls are revealed you should see two check-boxes for adding tags.