Click here to Skip to main content
12,629,065 members (34,856 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

14.5K views
961 downloads
26 bookmarked
Posted

Beginner's Guide to HTML5 & CSS3 - HTML5 API Grab Bag

, 18 May 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Dancing with HTML5 APIs of Geolocation, Drag and Drop, and Server-Sent Events.

Introduction

The advent of HTML5 has revolutionized the traditional web scene (and sense). In particular, HTML5's mandatory support for incorporating the ever-increasing number of APIs* into browsers has enable web pages to function more and more like desktop applications. This empowerment has brought about new possibilities and opportunities for the next generation of web applications that are more autonomous and can work offline, on multi-platforms, free of third party plug-ins and less reliant on server-side scripting. In the foreseeable future, it is not unimaginable that the web browser will replace our traditional metaphor of desktops on our computers, that of a web-based desktop.

Wow, the future of web landscape looks excitingly promising. However, reaching this stage is not without its challenges. For one thing, the supports of the current browsers must be improved and streamlined. For another, the awareness and education on HTML5 APIs among the web communities must be stepped up. Some would have argued about "the chicken or the egg" causality dilemma. I would argue that both can proceed in parallel.

Over the years, HTML5 specification has added a bag full of APIs that cover a wide spectra of functionality and features that power the future web browsers and mobile devices. In this article, we will dip into the HTML5 API grab bag and draw out 3 of them for discussion and exploration - Geolocation, Drag and Drop, and Server-Sent Events.

*API stands for Application Programming Interface. It is also called library or plug-in. In a nut shell, it is an stand-alone purpose-made software program without a user interface that when referenced to, provides or extends the functionality of a computer application.

Where On Earth?

Everyone of us occupies a location on Earth. This location is specified by a geographic coordinate system of latitude, longitude, and altitude. With the proliferation of location-aware hardware and software, finding one's location on the Earth has never been easier. There are many techniques available to identify the location of a user. A computer browser generally uses WIFI or IP based positioning techniques whereas a mobile browser may use cell triangulation that based on your relative proximity to the different cellular towers operated by the telcos, GPS, A-GPS, or WIFI. Today, location awareness is an ever-growing trend that finds its way into many applications like:

  • Showing one's location on a map especially when you are in an unfamiliar area.
  • Providing turn-by-turn navigation while driving on unfamiliar journey.
  • Find out the points of interest in one's vicinity.
  • Getting the latest weather or news of one's area.
  • Tagging the location of picture.
  • Location tracking of a fleet of delivery trucks.

Thanks to HTML5 Geolocation API, you can now look up your own location on Earth using a browser. It is as easy as a piece of cake. Seeing is believing.

Type the following code on the upper part of Figure 1 using a text editor, save it as "finding_me.html", and launch it on a browser. You should see a web page as shown in Figure 2. This code will work on Firefox and IE, but not on Google Chrome. Chrome does not allowed running Geolocation API from a file:// URI, it will work if you deploy it on a web server like Apache.

Figure 1: finding_me.html

Figure 2: Finding Me Initial Launch

Click on the "Where am I?" button, what do you see?

Figure 3: Seeking Permission to Share Location

A dialog box (Figure 3) pops up seeking permission to share location, click on "Share Location" to grant.

Figure 4: You are found!

Voila, your location is revealed on the screen as shown in Figure 4. Isn't that a piece of code, I mean cake.

How you wish you could show these location readings on a map so that you could view your location visually, right? You wish will come true if you read on...

HTML5 Geolocation

navigator.geolocation

The HTML5 geolocation API has only one object - the navigator.geolocation object. You may liken the navigator.geolocation to a compass on the browser. As browser support for this API is still dubious, it is a de facto practice to check for browser support before proceeding with any geolocation code, just wrap your code inside this if-else template like this:

// Check whether browser supports Geolocation API or not
if (navigator.geolocation) // Supported
{
    // place the geolocation code here
}
else // Not supported
{
    alert("Oop! This browser does not support HTML5 Geolocation.");
}

The navigator.geolocation object exposes 3 methods - getCurrentPosition(), watchPosition(), and clearWatch().

getCurrentPosition()

The getCurrentPosition() method is used to obtain the current location of the user. You have already used this method in its simplest form in Figure 1.

navigator.geolocation.getCurrentPosition(getPosition);

Recall in Figure 3 where a dialog has popped up seeking your permission to share your location with the web page. This is what happens whenever the getCurrentPosition() method is called. Users are given the choice to opt-in in order to allow the method to proceed to retrieve your current position. In other words, your privacy is well-respected and protected.

The getCurrentPosition() method takes 3 parameters:

  • The first parameter is a callback function to be called when the call to getCurrentPosition() method is successful. The callback function will be called with a position object passed from the getCurrentPosition() method. This position object consists of 2 properties: coords and timestamp.

    In Figure 1, the callback function is "getPosition(position)" which takes a position object parameter and outputs the latitude and longitude through the coords property of this parameter. This is illustrated in the code below:
    function getPosition(position)
    {
        document.getElementById("location").innerHTML =
            "Latitude: " + position.coords.latitude + "<br>" +
            "Longitude: " + position.coords.longitude;    
    }
    Table 1:Position Object
    Property Description
    coords.latitude

    The coords.latitude property returns the latitude of the user's current position in decimal degrees.

    coords.longitude The coords.longitude property returns the longitude of the user's current position in decimal degrees.
    coords.altitude The coords.altitude property returns the height of the user's current position in meters above the sea level. It will returns null if this information is not available.
    coords.accuracy The coords.accuracy property returns the accuracy level of the latitude and longitude coordinates in meters.
    coords.altitudeAccuracy

    The coords.altitudeAccuracy property returns the accuracy level of the altitude in meters.

    coords.heading The coords.heading property returns the direction of travel of the location-aware device in degrees, where 0° starts from the north and counting clockwise. It will returns null if this information is not available.
    coords.speed The coords.speed property returns the speed of the location-aware device in meters per second. It will returns null if this information is not available.
    timestamp The timestamp property returns the time when the position object was acquired.

  • The second parameter is an optional error handling callback function to be invoked when the call to getCurrentPosition() method encounters any one of the following circumstances:
    • Request timed out
    • Location information not available
    • User has denied permission to share the location information

    The callback function will be invoked with an position error object parameter passed from the getCurrentPosition() method. This position error object consists of one property - code. This code property takes one of 3 values corresponding to the error types as shown in Table 2.

    Table 2: Location Error Codes
    Property Description
    TIMEOUT

    Request for location information exceeds the timeout property set in the position options object (discussed later).

    POSITION_UNAVAILABLE The position of the location-aware device cannot be determined.
    PERMISSION_DENIED User has denied permission to share the location information.

    You will add a second callback function called "catchError(error)" to the script as highlighted In Figure 5:

    Figure 5: catchError() Function

    Next, attach this function as the second parameter to the getCurrentPosition() method like this:
    navigator.geolocation.getCurrentPosition(getPosition, catchError);
    Save and launch it on a (Firefox) browser, unplug your network cable (or turn off the wireless switch) to simulate the "no network connection" situation, grant the permission for sharing location information (Figure 3), and then click on the "Where am I?" button. What do you see?

    Figure 6: Simulating an Error Situation

    You should see a message box pops up saying "Location information is not available." (Figure 6). If you look back to the code in the catchError() function, you would notice that this is the error message specified under the error.POSITION_UNAVAILABLE code. The cause is obviously due to the network cable being unplugged. The catchError() function was invoked by the getCurrentPosition() method as it is not able to obtained any location information due to the broken network connection. (You may recover the network connection to your computer.)

    Although this error handling parameter is optional, you should always include it as part of the geolocation code. This is one of the best practices to allow the program to fail gracefully as well as to keep the users informed of any run-time errors.

  • The third parameter is an optional position options object that can be used to fine tune the position object returned by the getCurrentPosition() method programmatically. It has 3 properties as shown in Table 3.

    Table 3: Position Options Properties
    Property Description
    timeout

    The timeout property denotes the number of milliseconds an application will wait for a position information to become available. The default value is infinity.

    maximumAge The maximumAge property denotes the number of milliseconds an application can keep using the cached (previously obtained) location data before trying to obtain new location data. A zero value indicates that the application must not use the cached location data while infinity value indicates that the cached location data must be used by the application. The default value is zero.
    enableHighAccuracy The enableHighAccuracy property denotes the condition of true or false. If it is true, the application will try to provide the most accurate position. However, this would result in slower response time and higher power consumption. The default value is false.

    You will define a position options object called "positionOptions" and add it as the third parameter to the getCurrentPosition() method as highlighted in Figure 7:

    Figure 7: Position Options Object

    In designing your location-aware application, you should choose the degree of accuracy as well as the retention period of old location data that are most appropriate for the purpose of the application by setting the enableHighAccuracy and the maximumAge properties of the position options object accordingly. For example, if your application is mainly for finding points of interest in your vicinity, you probably do not need high accuracy and the location information do not have to be updated so often. On the other hand, if your application is to provide turn by turn navigation direction for driver, then high accuracy and constant update of location become necessary.

The getCurrentPosition() method is most suitable for obtaining a one-off location information. However, for finding location information that is changing continuously, such as the turn by turn navigation that I mentioned above, you will have to call the getCurrentPosition() method repeatedly which is obviously very cumbersome and inefficient. Fret not! HTML5 Geolocation API has provided another method to handle this kind of situation - watchPosition().

watchPosition()

The watchPosition() method is almost identical to the getCurrentPosition() method. They both return the current location information and have the same method signature - one success callback function, one error callback function, and one position options object. The only difference lies in that the getCurrentPosition() method only returns location information once upon activation such as a button click, whereas The watchPosition() method will continue to obtain location information every time the location of the user's device changes after the initial activation.

The watchPosition() method returns a watch ID that can be used to stop the watchPositon method() when it is no longer needed, such as when the car that uses it for navigation has arrived at the destination.

clearWatch()

The clearWatch() method takes the watch ID of a watchPosition() method as parameter and stop the execution of that watchPosition() method.

Watching Me

As the watchPosition() method is similar to the getCurrentPosition() method, if you are familiar with the later, creating the watchPosition() method will be much easier - it is mostly a matter of, believe it or not, "copy and paste".

Open finding_me.html in a text editor, save it as "watching_me.html". Then, in watching_me.html,

  • Change the "getCurrentPosition" text to "watchPosition".
  • Declare a variable called watchID below the <script> tag.
    <script> 
    var watchID; 
  • Store the watch ID returned from the watchPosition() method to a variable watchID.
    watchID = navigator.geolocation.watchPosition(getPosition, catchError, positionOptions);

That's all that you need to create a web page that constantly monitors and updates the user's current location.

However, to stop the monitoring and updating at some point in time, you will add another piece of code and a button to deactivate it. In the <script> section of watching_me.html, create a function called "stopWatch()" that calls the clearWatch() method by passing it the watchID of the watchPostion() method:

function stopWatch() 
{
    navigator.geolocation.clearWatch(watchID);
}

Lastly, replace the HTML code in the <body> of watching_me.html with:

<body>
<h1>Watching Me</h1>
<button onclick="getLocation()">Start Watching</button>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<button onclick="stopWatch()">Stop Watching</button>
<p id="location"></p>
</body>

Save and launch watching_me.html on a WIFI connected laptop (Firefox) browser, click the "Start Watching" button, grant the permission to share location, then move around with the laptop. What do you see?

Figure 8: You are being watched!

You should see your position being updated on the browser at a regular interval as you move. (Figure 8)

Watching on Map

Let's put the watch on a map as shown in Figure 9.

Figure 9: You are on the map!

The is the code for constructing the watch map in Figure 9. The file is called "watching_on_map.html" and is available for download.

<!DOCTYPE html>
<html>
<head>
<title>Watching on Map</title>
<style>
html,body {
    height: 100%;
    margin: 0;
    padding: 0;
}
#map-holder {
    height: 350px;
    width: 500px;
}
</style>
<script
    src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script

The logic of the code works as follows:

  • When the page is first loaded, the onload event will be triggered and calls the getLocation() function which in turn calls the getCurrentPosition() method of the navigator.geolocation object to obtain the user's current location.
  • If the getCurrentPosition() method is successful, it will trigger the callback function getPosition() passing it the position object.
  • What the getPosition() function does is to render a Google Map that is centered on the user's location shown as marker.
  • Clicking the "Start Watching" button will call the watchLocation() function which in turn calls the watchPosition() method of the navigator.geolocation object to obtain the user's current location at a regular interval.
  • If the watchPosition() method is successful, it will trigger the callback function getPosition() passing it the position object.
  • What the getPosition() function does has been described above.
  • Clicking the "Stop Watching" button will stop the watch activity.

If you move around with your WIFI connected laptop while keeping this web page opened, you should see your location being updated on the browser regularly as you move. Have fun!

We are done with the HTML5 Geolocation API. Let's take a breather before we continue.

HTML5 Drag and Drop

We are all too familiar with the drag and drop of files, folder, and icons on our computer desktop. Drag and drop is a powerful and yet taken-for-granted user interface functionality of any desktop applications. With the help of pointing devices like mouse, drag and drop makes copying, insertion, and deletion of files and objects on your desktop a breeze. On the contrary, to achieve the same drag and drop on browsers, complex client-side scripting like JavaScript or third-party libraries like jQuery is required. This was the main reason that deterred the use of drag and drop in the many traditional web pages that we have seen so far. However, this is expected to change with the introduction of HTML5 Drag and Drop API which brings native support to the browser making it much easier to code. See for yourself how drag and drop in HTML5 works by completing a dumping exercise that follows.

Download and extract html5dragndrop.zip to your computer, you should find a file called "html5dragndrop.html". Open it on a browser and you would see a web page as shown in Figure 10. You mission is to drag and drop the "Dump Me" trash into the dustbin.

Figure 10: html5dragndrop.html on Browser

Open the html5dragndrop.html using a text editor and you would see the code as shown in Figure 11. You will add the code to to drag and drop the "Dump Me" trash to the "Dustbin".

Figure 11: html5dragndrop.html in Plain Code

3, 2, 1, Drag...

draggable="true"

To make an element draggable, set its draggable attribute to true. Here, the draggable element is the <div id="trash">, you will enable it like this:

<div id="trash" draggable="true" >

ondragstart="dragStart(event)"

Next, you have to specify what should happen when the element is dragged by setting its ondragstart attribute to an event handler (function) that handles it. Here, the event handler is called dragStart. You may change to any other name. Add this attribute like this:

<div id="trash" draggable="true" ondragstart="dragStart(event)">

dragStart(event)

The dragStart event handler is actually a JavaScript function that is registered with the ondragstart attribute of a draggable element (mentioned above). It is called when the user starts dragging the element and is passed a dragEvent object (named as event here) as parameter. Add the dragStart function in the <script> section as shown:

<script>
function dragStart(event) 
{
   event.dataTransfer.setData("Text", event.target.id);
   document.getElementById("status").innerHTML = "Drag Start";
}
</script

The dragStart function essentially sets the data type and the value of the dragged data through the dataTransfer.setData() method (discussed later) of the dragEvent object. I have added one more line to output the status of the drag event on the browser.

Save the code and refresh it on the browser, can you drag the trash now?

Figure 12: html5dragndrop.html

Yes, you can and the status is read "Drag Start". However, it cannot be dropped anywhere! (Figure 12) You will have to add the code for dropping the element.

ondragover="dragOver(event)"

To make an element accept dropped object, set the ondragover attribute of this droppable element to an event handler that handles it. Here, the event handler is called dragOver. You may change to any other name. Here, the droppable element is the <div id="dustbin">, so you add this code:

<div id="dustbin" ondragover="dragOver(event)">

dragOver(event)

The dragOver function is registered with the ondragover attribute of a droppable element. It is called when a dragged element is moved over the droppable element and is passed an Event object (named as event here) as parameter. Note that the browser default handling of a drag over event is to NOT allowed a drop. So, to allow a drop, we have to override this default behavior by calling event.preventDefault(). Add the dragOver function in the <script> section as shown:

function dragOver(event) 
{
    event.preventDefault();
    document.getElementById("status").innerHTML = "Drag Over";
}

ondrop="drop(event)"

Once you have set the element to accept drop, you have to specify what should happen when an element is dropped onto it by setting its ondrop attribute to an event handler that handles it. Here, the event handler is called drop. You may change to any other name. Add this attribute like this:

<div id="dustbin" ondragover="dragOver(event)" ondrop="drop(event)">

drop(event)

The drop function is registered with the ondrop attribute of a droppable element. It is called when a dragged element is being dropped onto the droppable element at the end of a drag and is passed a dragEvent object as parameter. Add the drop function in the <script> section as shown:

function drop(event) 
{
    event.preventDefault();
    var data = event.dataTransfer.getData("Text");
    event.target.appendChild(document.getElementById(data));
    document.getElementById(data).innerHTML="I'm dumped";
    document.getElementById("status").innerHTML = "Dropped";
}

The drop function essentially calls the dataTransfer.getData() method of the dragEvent object to retrieve the dragged data that was set by dataTransfer.setData() method of the dragStart function by passing it the data type as parameter, i.e. "Text" in this case. The subsequent code simply drops (append) the dragged data (<div id="trash">) in the drop zone, i.e. <div id="dustbin">. Note that the browser default handling of a drop event is to open a link to some URL. We can override this default behavior by calling event.preventDefault().

You should be able to drag the trash and drop it into the dustbin now. (Figure 13) Observe the change of status during the different stages of the drag and drop operation.

Figure 13: Mission Accomplished

Drag and Drop Events

A total of 7 events are being fired at different stages of a drag and drop operation, you have already met some of them in your first drag and drop exercise above. These events can be monitored and captured through event listeners attached to the draggable elements or the droppable elements. For example, the event listener for drag start event (named as dragstart) is ondragstart. Each event listener will be assigned a function to perform when the event arises, such as the dragStart() function is being assigned to ondragstart event listener.

I have put together these events and their corresponding listeners in Table 4. Code snippets are also included. Note that the upper 3 rows are events and listeners for draggable elements, whereas the rest are for droppable elements. You should try out the code by adding them to the html5dragndrop.html and test it out on a browser. That is homework for you. ;P

Table 4: Drag and Drop Events and Event Listeners
Event Listener Description / Code Snippet
dragstart ondragstart

The dragstart event is triggered when the user starts dragging the dragged element and is captured by ondragstart listener.

The dragStart function essentially sets the data type and the value of the dragged data through the dataTransfer.setData() method of the Event object.

<div id="trash" draggable="true" ondragstart="dragStart(event)">
function dragStart(event) 
{
  event.dataTransfer.setData("Text", event.target.id);
  document.getElementById("status").innerHTML = "Drag Start";
}
drag ondrag

The drag event is triggered everytime the element is being dragged and is captured by ondrag listener.

<div id="trash" draggable="true" ondragstart="dragStart(event)" ondrag="drag(event)">
function drag(event) 
{
  document.getElementById("status").innerHTML = "Dragging...";
}
dragend ondragend

The dragend event is triggered when the user releases the mouse button while dragging an element.

<div id="trash" draggable="true" ondragstart="dragStart(event)" ondragend="dragEnd(event)">
function dragEnd(event) 
{
   document.getElementById("status").innerHTML = "Drag End";
}
dragenter ondragenter

The dragenter event is triggered when the mouse is first moved over the droppable element while a drag is occuring and is captured by ondragenter listener. Note that the browser default handling of a dragenter event is to NOT allowed a drop. So, to allow a drop, we have to override this default behavior by calling event.preventDefault().

<div id="dustbin" ondragover="dragOver(event)" ondrop="drop(event)" ondragenter="dragEnter(event)">
function dragEnter(event) 
{
   event.preventDefault();
   document.getElementById("status").innerHTML = "Drag Enter";
}
dragover ondragover

The dragover event is triggered when the mouse is moved over the droppable element while a drag is occuring and is captured by ondragover listener. Often, the operation that triggers this listener is the same as that for dragenter event.

Note that the browser default handling of a dragover event is to NOT allowed a drop. So, to allow a drop, we have to override this default behavior by calling event.preventDefault().

<div id="dustbin" ondragover="dragOver(event)" ondrop="drop(event)" ondragenter="dragEnter(event)">
function dragOver(event) 
{
   event.preventDefault();
   document.getElementById("status").innerHTML = "Drag Over";
}
dragleave ondragleave

The dragleave event is triggered when the draggable element left the droppable zone and is captured by ondragleave listener.

<div id="dustbin" ondragover="dragOver(event)" ondrop="drop(event)" ondragleave="dragLeave(event)">
function dragLeave(event) 
{
   document.getElementById("status").innerHTML = "Drag Leave";
}
drop ondrop

The drop event is triggered when the draggable element is being dropped onto the droppable element at the end of a drag and is captured by ondrop listener.

The drop function essentially calls the dataTransfer.getData() method of the dragEvent object to retrieve the dragged data that was set by dataTransfer.setData() method of the dragStart function by passing it the data type as parameter. The subsequent code will do the necessary operation to the dragged data, such as appending the it to some HTML element.

Note that the browser default handling of a drop event is to open a link to some URL. We can override this default behavior by calling event.preventDefault().

<div id="dustbin" ondragover="dragOver(event)" ondrop="drop(event)">
function drop(event) 
{
   event.preventDefault();
   var data = event.dataTransfer.getData("Text");
   event.target.appendChild(document.getElementById(data));
   document.getElementById(data).innerHTML="I'm dumped";
   document.getElementById("status").innerHTML = "Dropped";
}

DataTransfer Object

The functions for all the drag and drop events accept an Event parameter that has a dataTransfer property. The event.dataTransfer returns a DataTransfer object that holds the data that is being dragged during a drag and drop operation. This data can be retrieved and set via the various properties and methods associated with the DataTransfer object as explained in Tables 5 and 6.

Table 5: dataTransfer Properties
Property Description / Code Snippet
dropEffect

The dropEffect property specifies one of the 4 possible values for drop effect of the dragenter and dragover events and should always be one of the possible value set by effectAllowed.

The 4 possible values are:

  • copy: A copy of the dragged item is made at the new location.
  • move: The dragged item is moved to a new location.
  • link: A link is established to the dragged item at the new location.
  • none: The item can not be dropped.
function dragEnter(event) 
{
  event.dataTransfer.dropEffect = 'move';
}
effectAllowed

The effectAllowed property specifies the effects that are allowed for a drag by setting it in the dragstart event.

The possible values are:

  • copy: A copy of the dragged item may be made at the new location.
  • move: The dragged item may be moved to a new location.
  • link: A link may be established the dragged item at the new location.
  • copyLink: A copy or link operation is permitted.
  • copyMove: A copy or move operation is permitted.
  • linkMove: A link or move operation is permitted.
  • all: All operations are permitted.
  • none: The item can not be dropped.
  • uninitialized: This is the default value when no effect is set, which is equivalent to all.
function dragStart(event) 
{
  event.dataTransfer.effectAllowed = 'move';
}
types

The types property returns the list of formats that are set in the dragstart event.

files

The files property returns the list of files being dragged, if any.


Table 6: dataTransfer Methods
Method Description / Code Snippet
clearData()

The clearData() method takes a type as parameter and removes the data associated with the type. The type parameter is optional. If the type is omitted, all data is removed.

event.dataTransfer.clearData('Text');
setData()

The setData() method sets the data for a given type. The first parameter is the type and the second parameter the data.

event.dataTransfer.setData("Text", event.target.id);
getData()

The getData() method takes a type as parameter and retrieves the data for the type, or an empty string if data for that type does not exist or the dataTransfer object contains no data.

var data = event.dataTransfer.getData("Text");
setDragImage()

The setDragImage() method is used to set a custom image to be used during the dragging process. If this is not set, the default image is created from the source that is being dragged.

The setDragImage() method takes 3 parameters:

  • Image source
  • x coordinate offset into the image where the mouse cursor should be
  • y coordinate offset into the image where the mouse cursor should be

For example, to center the image, set the x and y coordinate offset values to half of the width and height of the image respectively.

function dragStart(event)
{   
    event.dataTransfer.setDragImage(document.getElementById('imageid'),50,50);
}
addElement()

The addElement() method is used to set a data source for the drag and drop operation. The default data source is the draggable element itself.

Drag and Drop Prizes

Let's wrap up the HTML5 Drag and Drop API by creating a simple web application for dragging and dropping prizes into the correct place. If a prize goes to the wrong place, it will not be allowed to drop there.

Figure 14: Drag and Drop Prizes

The is the code for constructing the Drag and Drop Prizes in Figure 14. The file is called "drag_n_drop_prizes.html" and is available for download.

<!DOCTYPE HTML>
<html>
<head>
<title>Drag and Drop Prizes</title>
<style>
.prizestand, .prizes {
    overflow: hidden;
    text-align:center;
}
#weeklyprize, #grandprize, #prizepack, #nexus7 {
    float: left;
    margin:10px;
    width: 400px;
    height: 250px;
    border: 5px solid red
}
#weeklyprize {
    padding: 5px;
    border: 5px solid red
}
#grandprize {
    padding: 5px;
    border: 5px solid red
}
#prizepack {
    padding: 8px;
    border: 1px solid blue
}
#nexus7 {
    padding:8px;
    border: 1px solid blue
}
</style>
<script>
function dragOver(event)
{
    event.preventDefault();
}
function dragStart(event)
{   
    event.dataTransfer.setData(event.target.id, event.target.id);
}
function drop(event)
{
    event.preventDefault();
    if ( event.dataTransfer.types.contains("drag1") && event.target.id=="grandprize")
    {
        var data=event.dataTransfer.getData("drag1");
        event.target.innerHTML="";
        event.target.appendChild(document.getElementById(data));
    }
    else if (event.dataTransfer.types.contains("drag2") && event.target.id=="weeklyprize")
    {
        var data=event.dataTransfer.getData("drag2");
        event.target.innerHTML="";
        event.target.appendChild(document.getElementById(data));    
    }
}
</script>
</head>
<body>
<div class="prizestand">
    <div id="grandprize" ondrop="drop(event)" ondragover="dragOver(event)"><h2>Grand Prize</h2></div>
    <div id="weeklyprize" ondrop="drop(event)" ondragover="dragOver(event)"><h2>Weekly Prize</h2></div>
</div>
<br>
<div class="prizes">
    <div id="prizepack"><img id="drag2" src="CodeProject_Prize_Pack1.png" draggable="true" ondragstart="dragStart(event)" width="325" height="206"></div>
    <div id="nexus7"><img id="drag1" src="Nexus7_Prize.png" draggable="true" ondragstart="dragStart(event)" width="325" height="206"></div>
</div>
</body>
</html>

I will elaborate on the logic for determining whether to accept or reject a prize image.

  • First, in the dragStart() function, I have assigned the element id of the prize image to be the data type value of the dataTransfer.setData() method (e.g. event.dataTransfer.setData(event.target.id, event.target.id)), i.e. the data type for "Nexus7_Prize.png" is "drag1" and that for "CodeProject_Prize_Pack1.png" "drag2".
  • Note that the ids of the droppable elements for "drag1" and "drag2" have been set as "grandprize" and "weeklyprize" respectively.
  • Then, in the drop() function, the code will look up for the data type of the dragged element (e.g. event.dataTransfer.types.contains("drag1")) and the droppable element (e.g. event.target.id=="grandprize") to determine whether the drop is allowed.

We are done with the HTML5 Drag and Drop API. Let's take another breather before embarking on the last venture - HTML5 Server-Sent Events.

HTML5 Server-Sent Events

The traditional model of communication between a user and a website is that of a user's initiated request-response type. The user will initiate the request through a browser and await response from the web server. To check for any update on a particular web page, the user will have to hit the refresh/reload button on the browser to send a new request to the web server. In other words, the client has to continuously poll the server for any updates. This is not very useful if the information is changing constantly and unpredictably and being able to access its latest update is pivotal for decision making, such as stock price updates, news feeds, weather forecasting, etc.

Here come HTML5 Server-Send Events (SSE) to the rescue! HTML5 SSE enables the server to send (push) information to the client when new information is available, eliminating the need for continuous polling. This has enabled websites to offer push services to their clients without the needs for any third-party plug-ins.

Server Clock

You will create a simple web application that receives continuous live update of time information from a web server using HTML5 SSE as shown in Figure 15.

Figure 15: Server Clock

The web application will consists of:

  • A HTML page that opens a persistent connection between the browser and a server-side script on a web server, receives and displays the time information provided by the server-side script.
  • A server-side script that acts as a web service that streams time information to the HTML page on the browser continuously and asynchronously. I have used PHP for the server-side script for this exercise, you may use any other scripts like PERL or Python. To test the web appilcation, you will have to deploy it on a web server, such as an Apache. You can find out how to do it by reading my article Beginner's Guide to HTML5 & CSS3 - Server Side Story which provides a bridging introduction to server-side scripting using PHP and Apache.

Let's do it. Create a folder named "html5sse". Inside this folder, you will save the HTML page and the PHP server-side script that you are going to create.

First, the HTML page:

  • Open a text file using a text editor, save it as "client.html", and enter the following code:
    <!DOCTYPE html>
    <html>
    <body style="text-align:center;">
    <h2>Greeting from HTML5 Server-Sent Events</h2>
    <div id="time"></div>
    <div id="greeting"></div>
    <script>
    if(typeof(EventSource)!=="undefined") // Browser supports SSE
    {
        var source=new EventSource("sse_server.php");
        source.onmessage=function(event)
          {
            var feed = event.data.split(",");
              document.getElementById("time").innerHTML = feed[0];
              document.getElementById("greeting").innerHTML = feed[1];
          };
    }
    else // Browser does not support SSE
    {
        alert("Oop! This browser does not support HTML5 Server-Sent Events");;
    }
    </script>
    </body>
    </html>
    What the code does is:
    • Check whether your browser supports SSE or not (if(typeof(EventSource)!=="undefined"){...}).
    • Create a new EventSource object that takes the URL of the server-side script as parameter (var source=new EventSource("sse_server.php")).
    • Register an event listener EventSource.onmessage to look up for server message (source.onmessage=function(event){...}).
    • Whenever a new message is received, the onmessage event will fire and the corresponding function (function(event){...}) will retrieve the message from the data property of the event parameter that it receives (event.data). The rest of the function just separates the message received into greeting and time parts for display in the respective HTML elements, the result of which is shown in Figure 15.

Next, the PHP server-side script:

  • Open a text file using a text editor, save it as "sse_server.php", and enter the following code:
    <?php
    // Change this to your time zone
    date_default_timezone_set ("asia/singapore");
    
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    
    $time = date("l j  F Y h:i:s A");
    if (date("A") == "AM")
        $greeting = "Good morning";
    else
        $greeting = "Good afternoon";
    
    $feed .= $time.",".$greeting;
    
    echo "data:  $feed\n\n";
    ?>
    What the code does is:
    • The SSE related code consists of only 3 lines:
      • header('Content-Type: text/event-stream') : Sets the "Content-Type" header to "text/event-stream".
      • header('Cache-Control: no-cache'): Specifies that the page should not be cached.
      • echo "data: $feed\n\n": Outputs the data (stored in variable $feed), the data must be preceded by data: and ends with \n\n. This data will be received by the EventSource.onmessage over at the client.html page.
    • The rest of PHP code will simple parse and concatenate the time and the greeting based on the time of the day into a variable called $feed.

To test this web application, you have to place the html5sse folder inside the web root of an Apache server, start the Apache server, type this in the address of any browser "http://localhost/html5sse/client.html", and hit the Enter key, you should see a running clock on the browser as shown in Figure 15. You will find out how to do this after reading my article Beginner's Guide to HTML5 & CSS3 - Server Side Story which provides a bridging introduction to server-side scripting using PHP and Apache.

You have used the onmessage event listener of the EventSource object to look up for server messages. The EventSource object has 2 more listeners:

  • onopen: Occurs when a connection to the server is successful opened.
  • onerror: Occurs when an error is encountered.

Out of the Bag

Glad to see you at the finishing line. You have explored 3 HTML5 APIs with hands-on exercises, i.e. Geolocation, Drag and Drop, and Server-Sent Events. However, they are just the tip of the iceberg. With each passing years, more and more new APIs are added into the HTML5 API grab bag. These APIs have given unprecedented power and automony to our most frequently used piece of software - the web browsers. It is not unimaginable that the web browsers may one day prevails over the traditional desktop on our computers. As to how soon this will happen, we will have to wait and see. Till then...

Reference

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Peter Leow
Instructor / Trainer
Singapore Singapore
Stop by my website at http://www.peterleowblog.com/

Check out my publications at http://www.amazon.com/author/peterleow

Follow me on twitter at https://twitter.com/peterleowblog

“Live as if you were to die tomorrow. Learn as if you were to live forever.”
― Mahatma Gandhi

子曰:"三人行,必有我师焉;择其善者而从之,其不善者而改之."

You may also be interested in...

Comments and Discussions

 
Questionmy 10 vote Pin
Member 1206830211-Nov-16 10:05
memberMember 1206830211-Nov-16 10:05 
GeneralNice Pin
soul10815-Oct-15 6:48
membersoul10815-Oct-15 6:48 
GeneralMy vote of 5 Pin
Adrian Pasik9-Dec-14 4:31
memberAdrian Pasik9-Dec-14 4:31 
GeneralMy vote of 5 Pin
newton.saber8-Sep-14 10:57
membernewton.saber8-Sep-14 10:57 
GeneralRe: My vote of 5 Pin
Peter Leow8-Sep-14 18:23
professionalPeter Leow8-Sep-14 18:23 
QuestionGeolocation Pin
Mary Jane Rutkowski27-May-14 9:24
memberMary Jane Rutkowski27-May-14 9:24 
AnswerRe: Geolocation Pin
Peter Leow27-May-14 15:21
professionalPeter Leow27-May-14 15:21 
GeneralAnother good article Pin
James Jensen20-May-14 6:56
professionalJames Jensen20-May-14 6:56 
GeneralRe: Another good article Pin
Peter Leow20-May-14 16:33
professionalPeter Leow20-May-14 16:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 18 May 2014
Article Copyright 2014 by Peter Leow
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid