Is HTML5 a serious tool? – investigating the tech part 2

Okay, since last time, I’ve changed the javascript somewhat to include recording the ‘mode’ of the browser – this is particularly significant to Internet explorer. I’ve also wrapped the code in a library that can be easily inserted into any page, and here is a link to it: Link to ‘browserStats’ library

I requires jQuery to work. If you want to see it in a real page, look in the home page of http://www.alimar.co.uk I won’t pad this out with the full source, but the line most significant to use is:

$.post("/BrowserStats", { BrowserName: browserName, FullVersion: fullVersion, MajorVersion : majorVersion, ApplicationName: navigator.appName, UserAgent: navigator.userAgent, Engine: engine, DetailsCounter: DetailsCounter });

This means all the metrics I’ve collected in javascript are being fired off to a landing page called ‘/BrowserStats’. It’s just a listing page because I tend to write in MVC these days, so it’s really going to a call to the index page in a directory ‘/BrowserStats’.  If you wanted to do this in a more conventional way, you could call it using a convention such as:

$.post("/BrowserStats.aspx?Browsername=" + browserName _ "&FullVersion=" + <etcetera>);

In the landing page, I then processed the details by writing them to an SQL Database. Here’s my code, so you need to modify it to suit your scripting and data storage environment.

My page for picking up the details, parameterizing them, and then inserting them into a database table via a stored procedure is as follows:

Landing page script (C# code):


int detailsCounter = 0;
string browserName = "";
string fullVersion = "";
string majorVersion = "";
string applicationName = "";
string userAgent = "";
string mode = "";


NameValueCollection frm = HttpContext.Request.Form;


browserName = frm["BrowserName"].ToString();
fullVersion = frm["FullVersion"].ToString();
majorVersion = frm["MajorVersion"];
applicationName = frm["ApplicationName"];
userAgent = frm["UserAgent"];
mode = frm["engine"];


try
{
detailsCounter = Convert.ToInt32(frm["DetailsCounter"]);
}
catch { }


SqlParameter param1 = new SqlParameter("BrowserName", browserName);
SqlParameter param2 = new SqlParameter("FullVersion", fullVersion);
SqlParameter param3 = new SqlParameter("majorVersion", majorVersion);
SqlParameter param4 = new SqlParameter("ApplicationName", applicationName);
SqlParameter param5 = new SqlParameter("UserAgent", userAgent);
SqlParameter param6 = new SqlParameter("DetailsCounter", detailsCounter);
SqlParameter param7 = new SqlParameter("mode", mode);


Utilities.RunSPNoResults("usp_StoreBrowserStats", param1, param2, param3,param4,param5,param6, param7);

 

So you can see I’m taking the form details, converting it to variables, and passing it into a stored procedure.  That includes the ‘detailsCounter’ I mentioned last time. This variable contains a single number that holds the true/false values of each of the tests.

To see how this works, I give the table setup code and the stored procedure call that fills in a row in the table with our details:

CREATE TABLE [dbo].[BrowserCapabilities](
[id] [int] IDENTITY(1,1) NOT NULL,
[SessionStorage] [bit] NOT NULL,
[LocalStorage] [bit] NOT NULL,
[Audio] [bit] NOT NULL,
[AudioMP3] [bit] NOT NULL,
[AudioWAV] [bit] NOT NULL,
[Video] [bit] NOT NULL,
[Canvas] [bit] NOT NULL,
[FileAPI] [bit] NOT NULL,
[Geolocation] [bit] NOT NULL,
[OfflineWebApps] [bit] NOT NULL,
[IndexedDB] [bit] NOT NULL,
[WebSockets] [bit] NOT NULL,
[WebSQL] [bit] NOT NULL,
[WebWorkers] [bit] NOT NULL,
[BrowserName] [varchar](255) NOT NULL,
[mode] [varchar](20) NULL,
[FullVersion] [varchar](255) NOT NULL,
[MajorVersion] [varchar](255) NOT NULL,
[ApplicationName] [varchar](255) NOT NULL,
[UserAgent] [varchar](max) NOT NULL,
[DateEntered] [datetime] NOT NULL
) ON [PRIMARY]

And the stored procedure is:

procedure [dbo].[usp_StoreBrowserStats]

@BrowserName varchar(255),
@FullVersion varchar(255),
@MajorVersion varchar(255),
@ApplicationName varchar(255),
@UserAgent varchar(255),
@DetailsCounter int,
@mode varchar(20)
as

begin


set nocount on;


Declare @SessionStorage bit
Declare @LocalStorage [bit]
Declare @Audio [bit]
Declare @AudioMP3 [bit]
Declare @AudioWAV [bit]
Declare @Video [bit]
Declare @Canvas [bit]
Declare @FileAPI [bit]
Declare @Geolocation [bit]
Declare @OfflineWebApps [bit]
Declare @IndexedDB [bit]
Declare @WebSockets [bit]
Declare @WebSQL [bit]
Declare @WebWorkers [bit]

select @SessionStorage = 0,
@LocalStorage = 0,
@Audio = 0,
@AudioMP3 = 0,
@AudioWAV = 0,
@Video = 0,
@Canvas = 0,
@FileAPI = 0,
@Geolocation = 0,
@OfflineWebApps = 0,
@IndexedDB = 0,
@WebSockets = 0,
@WebSQL = 0,
@WebWorkers = 0

if (@DetailsCounter>=8192 )
BEGIN
select @WebWorkers = 1
set @DetailsCounter = @DetailsCounter - 8192
END


if (@DetailsCounter>=4096 )
BEGIN
select @WebSQL = 1
set @DetailsCounter = @DetailsCounter - 4096
END

if (@DetailsCounter>=2048 )
BEGIN
select @WebSockets = 1
set @DetailsCounter = @DetailsCounter - 2048
END

if (@DetailsCounter>=1024 )
BEGIN
select @IndexedDB = 1
set @DetailsCounter = @DetailsCounter - 1024
END

if (@DetailsCounter>=512 )
BEGIN
select @OfflineWebApps = 1
set @DetailsCounter = @DetailsCounter - 512
END

if (@DetailsCounter>=256 )
BEGIN
select @Geolocation = 1
set @DetailsCounter = @DetailsCounter - 256
END

if (@DetailsCounter>=128 )
BEGIN
select @FileAPI = 1
set @DetailsCounter = @DetailsCounter - 128
END

if (@DetailsCounter>=64 )
BEGIN
select @Video = 1
set @DetailsCounter = @DetailsCounter - 64
END

if (@DetailsCounter>=32 )
BEGIN
select @Canvas = 1
set @DetailsCounter = @DetailsCounter - 32
END

if (@DetailsCounter>=16 )
BEGIN
select @AudioWAV = 1
set @DetailsCounter = @DetailsCounter - 16
END

if (@DetailsCounter>=8 )
BEGIN
select @AudioMP3 = 1
set @DetailsCounter = @DetailsCounter -8
END

if (@DetailsCounter>=4 )
BEGIN
select @Audio = 1
set @DetailsCounter = @DetailsCounter -4
END

if (@DetailsCounter>=2 )
BEGIN
select @LocalStorage = 1
set @DetailsCounter = @DetailsCounter -2
END

if (@DetailsCounter>=1 )
BEGIN
select @SessionStorage = 1
set @DetailsCounter = @DetailsCounter -1
END


insert into BrowserCapabilities
(
[BrowserName]
,[mode]
,[FullVersion]
,[MajorVersion]
,[ApplicationName]
,[UserAgent]
,[SessionStorage]
,[LocalStorage]
,[Audio]
,[AudioMP3]
,[AudioWAV]
,[Video]
,[Canvas]
,[FileAPI]
,[Geolocation]
,[OfflineWebApps]
,[IndexedDB]
,[WebSockets]
,[WebSQL]
,[WebWorkers]
)
values
(
@BrowserName,
@mode,
@FullVersion,
@MajorVersion,
@ApplicationName,
@UserAgent,
@SessionStorage,
@LocalStorage,
@Audio,
@AudioMP3,
@AudioWAV,
@Video,
@Canvas,
@FileAPI,
@Geolocation,
@OfflineWebApps,
@IndexedDB,
@WebSockets,
@WebSQL,
@WebWorkers
)

end

In this, you can see how I reconstruct the original values for each true/false from the large number ‘detailsCounter’.

You can of course modify it to suit, and you might prefer to have 1 parameter = 1 true/false and make it easier to follow. Your call.

Okay, by setting up the library to post to a certain page, then using this page to then store the details in a database table, I have a working mechanism to collect easily-read stats about my user base machines/browsers, which will help me to decide which, if any, html5-specific abilities I can exploit for future webapp development in a serious way.

Next time, I hope to explore the world of offline cached apps and some of the issues around that.

cheers
Mark

Leave a Reply