Tag Archives: HTML5

PhoneGap: Saving Arrays in Local Storage

One of a handful of local storage options for PhoneGap applications is the localStorage solution which is actually part of the W3C specs. It provides access to a W3C Storage interface since we are just dealing with HTML5 in PhoneGap. This is a good option for storing simple strings but what if we want to store more complex data structures but don’t want to be bothered with a SQLite database for our application? It’s actually possible to do this via some JSON trickery!

In this example, we will first initialize our Array object to hold all the data:

var gatheredPosts = new Array();

We can then create complex data structures and push these into our array for immediate use in the application – and to back up via local storage options for later. Here’s some dummy code which demonstrates this:

// let's imagine these "posts" come from a remote data call which has just returned
for (var i = 0; i < posts.length; i++) {
    gatheredPosts.push({title:posts[i].title, url:posts[i].url, content:posts[i].content});
}

At this point, we could attempt to write the array to local storage via the normal method... but this will not work with complex objects like arrays out of the box - and will fail to write the appropriate data:

window.localStorage.setItem("cachedPosts", gatheredPosts);

What we need to do to be able to save and retrieve complex array data is to extend the Storage prototype with new methods which will stringify our array data into JSON and also parse the stringified data into a new data object for retrieval. It's a lot simpler than it sounds. Just include these definitions in your JavaScript:

Storage.prototype.setArray = function(key, obj) {
    return this.setItem(key, JSON.stringify(obj))
}
Storage.prototype.getArray = function(key) {
    return JSON.parse(this.getItem(key))
}

We can now use these new methods to properly store and retrieve our array structures!

Here we see array storage:

window.localStorage.setArray("cachedPosts", gatheredPosts);

And array retrieval:

gatheredPosts = window.localStorage.getArray("cachedPosts");

Not a bad solution :)

Absinthe Dilution Faerie 2.0

Absinthe Dilution Faerie

Absinthe Dilution Faerie version 2.0 is now available for free via Google Play!

“Absinthe Dilution Faerie” is a small application which calculates how much water one should temper a dose of absinthe with in accordance with the ABV percentage as laid out by Michael Meyers of The Wormwood Society.

So what’s new in this version? Quite a bit!

  • New application imagery
  • Default database of absinthes
  • Clicking upon an absinthe will load it into the calculator
  • Ability to add your favorite absinthes to the database
  • Database management: add/update/delete
  • Include tasting notes for each brand of absinthe

So… go download and louche up a few ;)

The application was compiled with PhoneGap Build and written with HTML, CSS, and JavaScript. Libraries used include jQuery Mobile and HTML5SQL.JS. Also – please welcome Midge back as the faerie, herself!

PhoneGap and HTML5SQL.JS

I’ve been doing a lot of digging around in PhoneGap lately. This dovetails nicely with my Edge Animate and Edge Reflow work – but I also see it as an extension of my work with Adobe AIR and Flash Player on mobile.

One of the interesting things about working in web technologies with modern browsers (including mobile), is that we have so many choices due to fragmentation or simply because of competing ideas. I’ve found many of the solutions for web storage on mobile to be either lacking or frustratingly complex. A few weeks back, I rand across a nice solution to simply all of this and have adopted it into my workflow.

HTML5SQL.JS makes working with local databases in a PhoneGap app super easy. This video demonstrates how to use it within a project.

Also – you can check out my progress for this app on the project Github repository.

Absinthe Dilution Faerie

absinthewormwood

“Absinthe Dilution Faerie” is a small application which calculates how much water one should temper a dose of absinthe with in accordance with the ABV percentage as laid out by Michael Meyers of The Wormwood Society.

The application also has the support of The Wormwood Society! If you are at all interested in absinthe or absinthe education; The Wormwood Society is an absolutely invaluable resource.

Happy to say that some prominent Absintheurs are supportive of this little application!
review

Grab it for FREE on the Google Play store:

Get it on Google Play

I’ve also created an entry for the app on the PhoneGap site: http://phonegap.com/app/absinthe-dilution-faerie/

Fun with HTML Video

These days, formulating a video playback experience is a complicated and broken process… especially when streaming. The ideal for us, in the specific case referenced in this article, is to deliver a stream over Real Time Messaging Protocol (RTMP) via Adobe Media Server into Strobe Media Player or some other Flash-based player for a robust, feature-rich video experience. On devices which do not support Flash Player, fall back to HTTP Live Streaming (HSL) using the HTML video tag for a simplified experience. For those older browsers which do not support the video tag and do not have Flash Player installed… provide a small message letting the user know why they cannot view the stream.

This should be simple and the approach we are taking is to set up a container div element which includes the video tag with fallback to a simple set of plain text compatibility messaging. If Flash Player is detected, we use the SWFObject JavaScript library to overwrite everything in our container element, embedding the Flash object for playback.

The main problem we had with this approach is that while many browsers do support the video tag for fallback from Flash Player – hardly any actually support streaming over the video tag using HLS. In fact, the only ones that do are basically OSX Safari (with certain additional requirements) and iOS Safari… that leaves a lot of browsers out of the mix. Sure, just about anything else can use Flash Player for a playback solution – but some people either have this disabled or just not installed (~2% at the university level, incidentally). One would expect that the fallback message would be displayed in this case as per the HTML5 specs, but not so.

Take Internet Explorer 9, for example. With Flash Player disabled, it picks up the video tag and even displays the specified poster frame correctly. We get the right-click video controls menu as well… but since HLS streaming is not supported in that browser – it will not play. What is worse – the fallback messaging never appears since the video tag is supported and actually renders a video container. The result of all this is a completely broken experience for users as it will appear as though the video loads (the poster does load!) but nothing useful ever happens.

To get around all this, there is a JavaScript method we can use to detect whether a stream type is supported and then react to that.

The first things we must do is get a video element for reference. Any video element will do but a simple way of just grabbing the first one is to invoke the following:

var video = document.getElementsByTagName("video")[0];

This will grab the first video element in the document and assign a reference to a variable. Next, we can see whether the video method canPlayType() is actually supported by testing against the following:

if (video.canPlayType) { }

So long as the  canPlayType()  method is available, we can get more specific and test against a certain stream or file type – depending upon our needs. I’m serving an HLS stream through .m3u8 so will test against the mime type of application/x-mpegURL as below:

if (video.canPlayType("application/x-mpegURL")) {
	//nothing;
} else {
	$("#MediaPlayer").append("<p class='failmsg'>This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.</p>");
}

If it is supported, I do nothing – but if it is not supported… I write out a message that is styled and positioned over the poster frame via CSS which lets the user know what’s up.

Of course, this is a lot simpler if we are just serving up simple files off of a local web server – but what fun is that?  :)

Here are the final bits of code:

<div id="MediaPlayer">
	<video id="HLSPlayer" width="320" height="240" poster="<cfoutput>#posterpath#</cfoutput>" src="<cfoutput>#htmlsource#</cfoutput>" controls>
        This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.
    </video>
    <script type="text/javascript">
		var w = $(document).width();
		var h = $(document).height();
		$("#HLSPlayer").width(w);
		$("#HLSPlayer").height(h);
		var video = document.getElementsByTagName("video")[0];
		if(video.canPlayType) {
			if (video.canPlayType("application/x-mpegURL")) {
				//nothing;
			} else {
				$("#MediaPlayer").append("<p class='failmsg'>This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.</p>");
			}
		}
	</script>
</div>