Table of Contents
This is my first hands on in HTML5. One day I thought about making an application which is simple and fancy looking as well. I had not worked earlier in HTML5, but once I saw the new features and tags in HTML5, I decided to make something new in core HTML. The biggest advantage in using HTML5 is that it is light weighted, platform independent and best for mobile applications like Iphone, Android (For Win 7 mobile, it’s not supported because Microsoft is still experimenting with HTML5 and has not yet introduced HTML5 in mobile). Enough about my thoughts, let's moves on to the application. This application is based on Login form, but it is not a simple authentication form.
In this article, we'll build a innovative login form, where the user drops a “webid” file in the login form to authenticate. The file contains an image and some information about the card holder. It uses a great feature of HTML5, WCF and feature called WebId
.
The most essential requirement to run this application is HTML5 supported browser.
Browser: Firefox 3.6.3, Google Chrome 5.0, Apple Safari 4.05, Opera 10.53
As a beginner, you can learn the following features:
- HTML5, CSS3, WebKit
- Ajax call to WCF service using JavaScript
- JSON Operation in JavaScript.
I used this term (fancy) because I will tell you in simple terms how you can make a form look attractive.
As in figure of signup form, I divide the form in 3 sections:
- User detail
- Address detail
- Image Upload
All sections are pretty simple except image upload section where I did not give any upload button. So how I can upload image? So I used the feature of drag and drop of HTML5 where you have to just drag and drop image in box. But here I applied a constraint along with it. You can’t drag and drop image of more than 10 KB size. Since this is simple demo application, I was not going deep into it to resize image of any size, so I just put the constraint.
As you can see in the signup form rounded corner box, this is very simple CSS for webkit in HTML5:
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
-khtml-border-radius: 5px;
border-radius: 5px;
You can give gradient effect using webkit
at background in one line.
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#526ACE), to(#526ACE));
And you can browse more details in CSS from my code in the attachment.
Especially I wanted to give more details about this feature because it is more interesting for lazy people who don’t want to navigate an image from desktop location and then upload it. I saved 5-6 seconds by using drag and drop feature of HTML5.
Let's have a look at how I can accomplish this task.
<fieldset>
<legend>Image Load</legend>
<ol>
<li><legend>Drag and Drop your Image here<legend>
<div id="holder">
</div>
<div id="status">
</div>
<script>
var y = null;
var holder = document.getElementById('holder'),
state = document.getElementById('status');
if (typeof window.FileReader === 'undefined') {
state.className = 'fail';
} else {
}
holder.ondragover = function()
{ this.className = 'hover'; return false; };
holder.ondragend = function()
{ this.className = ''; return false; };
holder.ondrop = function(e) {
this.className = '';
e.preventDefault();
var size = e.dataTransfer.files[0].size;
if (size > 10000) {
alert("Your image size is greater than
10 kb please Shrink image size");
window.location.reload(true);
}
else {
var file = e.dataTransfer.files[0],
reader = new FileReader();
reader.onload = function(event) {
holder.style.background =
'url(' + event.target.result + ') no-repeat center';
y = 'url(' + event.target.result + ') no-repeat center';
};
reader.readAsDataURL(file);
state.className = 'success';
state.innerHTML = 'Image SuccessFully Uploaded';
return false;
}
};
</script></li>
</ol>
</fieldset>
Although this code is self explanatory, I want to give some details on drag and drop feature. As you can see, I used div
as a place in the form for drag and drop.
In the JavaScript, we are:
- Searching for the drop target in the DOM using
document.getElementByID
. - When drag over event is fired (when the user drags the element over another), it will trigger the CSS class.
- Bind the drop event, and within there, grab some data about what was dropped.
- Now read the
stream
by reader and it will generate event.target.result
that will help us to get an image in base 64 format which we further used as in webid
.
For more details on new tags, please move to resources.
That is enough for fancy form decoration and JavaScript. Now we will move to Ajax calling WCF service.
Before describing snippet of Ajax call, I would like to give you a few details on WCF service at the server end. The service exposed as a REST URI in Post
method. I want to send data as post because data would be too large. I used response format in JSON because it is easy to use in Ajax call. As this is a demo application, I did not use WCF in a professional way and just use as rooky.
Simple one method Signup User:
[OperationContract]
[WebInvoke(Method = "*",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "SignUpUser")]
string SignUpUser(string name, string email,string language, string phoneno,
string gender, string country, string image);
Implementation of the SignUpUser
is very straight forward. I just make a webid
format just as a JSON Format and send it to the appropriate mail. For making JSON string
, I used inbuilt .NET serializer.
JavaScriptSerializer oSerializer = new JavaScriptSerializer();
string sJSON = oSerializer.Serialize(jsonWebIdList);
Web ID Format
We should create a file that we can drop on the form. It will be a text file with the extension “webid
”. The content is a JSON object containing all the data we need. One part of the file, named userdata
, lists things as name
, age
, etc. Remember that you shouldn’t trust the data in the file. It should only be used as feedback to the user on the login screen.
{
"filetype": "webid",
"signed":1234567890,
"userdata": {
"id": 1,
"name":"XYZ",
"gender": "Male",
"birthdate":19610804,
"phone":"1234567890",
"country":"us",
"language":"en_US",
"image": ""
},
"keys": {
"Null"
}
}
Now I call signup service from JavaScript that will look like this:
var baseUrl = "http://localhost:54976/RestServiceImpl.svc/";
function AjaxRequest(baseurl, type, callbackResponse, parameterString) {
this.BaseURL = baseurl;
this.Type = type;
this.Callback = callbackResponse;
this.createXmlRequestObject();
this.ParemeterString = parameterString;
}
AjaxRequest.prototype.createXmlRequestObject = function() {
if (window.ActiveXObject) {
try {
this.xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
this.xmlHttp = false;
}
}
else {
try {
this.xmlHttp = new XMLHttpRequest()
} catch (f) {
this.xmlHttp = false;
}
}
if (!this.xmlHttp) {
alert('there was an error creating the xmlhttp object');
} else {
}
}
AjaxRequest.prototype.MakeRequest = function() {
try {
if (this.xmlHttp.readyState === 4 || this.xmlHttp.readyState === 0) {
this.xmlHttp.open(this.Type, this.BaseURL, false);
var that = this;
this.xmlHttp.onreadystatechange = function() {
try {
alert(that.xmlHttp.readyState);
if (that.xmlHttp.readyState == 4) {
alert(that.xmlHttp.status);
if (that.xmlHttp.status == 200) {
var xmldoc;
if (window.ActiveXObject) {
xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.async = "false";
that.Callback(that.xmlHttp.responseText);
}
else {
that.Callback(that.xmlHttp.responseText);
}
}
}
}
catch (e)
{ alert(e) }
}
switch (this.Type) {
case "GET":
this.xmlHttp.send(this.BaseURL);
break;
case "POST":
this.xmlHttp.setRequestHeader("Content-type", "application/json");
this.xmlHttp.send(this.ParemeterString)
}
}
else {
setTimeout('GetAllAppsService', 5000);
}
} catch (e) {
alert(e);
}
}
As you can see from the above code function, AjaxRequest
creates XMLHttpRequest()
object which further calls method AjaxRequest.prototype.MakeRequest
. I used JavaScript in object oriented so that it can be used anywhere in calls easily. What you need to do is just make an object of AjaxRequest
and call the function MakeRequest
. For more details on how to use JavaScript as OOPS, please follow the trick from here.
You can also get some help form this article here.
Now call the Ajax request to WCF service just like:
AuthenticateLogin.prototype.SendDetailsToServer = function(parameters, localId) {
var url = baseUrl + "SignUpUser";
var parameterString = "{";
for (var i = 0; i < parameters.length; i++) {
parameterString = parameterString + '"'
+ parameters[i][0] + '":"'
+ parameters[i][1] + '" ,';
}
parameterString = parameterString.slice(0, parameterString.length - 1);
parameterString = parameterString + "}";
var ajaxRequestObject = new AjaxRequest(url, "POST", function(responseText) {
var jsonobj = eval('(' + responseText + ')');
var result = jsonobj.SignUpUserResult;
if (result == "Successful") {
alert("SuccessfullyMail sent and you will redirect to login Page");
window.location = "http://localhost:54976/UI/latestLogin.htm";
}
else {
alert("Message sending Fail! Please try again");
window.location.reload(true);
}
}, parameterString);
ajaxRequestObject.TempItemID = localId;
ajaxRequestObject.MakeRequest();
}
One thing I would like to stay focused on is parameterString
. I customized Body
request in JSON Format because Ajax request header is in JSON format. So it will only accept JSON string
in body.
this.xmlHttp.setRequestHeader("Content-type", "application/json");
this.xmlHttp.send(this.ParemeterString)
Here, function (responseText
) is used as a callback function which will call once response is handed over by the Ajax request call. ResponseText
is the result state when response sends back from the server in readystate
4 with status 200.
Now call:
function getDataFromthroughClass() {
var objSync = new AuthenticateLogin();
var name = document.getElementById("name").value;
var email = document.getElementById("email").value;
var phone = document.getElementById("phone").value;
var language = document.getElementById("language").value;
var gender = document.getElementById("gender").value;
var country = document.getElementById("country").value;
objSync.SendDetailsToServer(new Array(
new Array("name", name),
new Array("email", email),
new Array("language", language),
new Array("phoneno", phone),
new Array("gender", gender),
new Array("country", country),
new Array("image", y)));
}
This section is pretty interesting and something different which I got from mattiasdanielsson. He gives a nice way to use web id as an authentication by using the drag and drop feature of HTML5.
What we used in login form when the user wants to authenticate, he drops a file (i.e. “xyz.webid”) in the form, which is then read and parsed by JavaScript as JSON. Using jQuery, the users data (name
, gender
, etc.) is displayed in the drop zone, providing visual feedback to the user. If the file is parsed without error, an input is shown where the user enters his four-digit PIN number. The JavaScript then uses the PIN together with the “auth
” string
in the dropped file to create the key sent to the server... In this demo application, I don't use PIN authentication from server.
var objData;
$(document).ready(function() {
var $droptarget = $('#idBox'), $idCardSrc = $('#idCardSrc'),
$idBoxBg = $('#idBoxBg'),
$pinBox = $('#pinBox'), $pinInput = $('input', $pinBox);
$droptarget.bind('dragenter', function(e) {
e.stopPropagation();
e.preventDefault();
$droptarget.addClass('drophover');
$idBoxBg.text('Drop it now');
return false;
});
$droptarget.bind('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
$droptarget.removeClass('drophover');
$idBoxBg.text('Drop ID file here');
return false;
});
$droptarget.bind('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
});
document.getElementById('idBox').addEventListener('drop', function(e) {
e.stopPropagation();
e.preventDefault();
For drag and drop of webid
, we are required to add event handlers to all four events, and use both stopPropagation
and preventDefault
on them. Otherwise, your browser will just display the dropped file, and never fire the drop
event. Also note that jQuery’s bind()
method is used with the first three handlers, but not the fourth. Since jQuery doesn’t support the Event.dataTransfer
object, we have to bind the drop event using native JavaScript.
I hope you will enjoy this different authentication login window by the magic of HTML5. As I stated from the outset, we can enhance this login authentication in a more logical way for very secure sites by the following method:
- You can match base 64 image for validation.
- Pin could be hashed in
webid
or just drop this pin in mail along with attachment of webid
. - Encrypt
webid
(In this demo application, I did not used encryption.)
That's all about the application. For more details, please use the discussion panel.
- 22nd December, 2010: Initial version
- 22nd March, 2011: Updated article