<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
					xmlns:content="http://purl.org/rss/1.0/modules/content/"
					xmlns:wfw="http://wellformedweb.org/CommentAPI/"
				  >
<channel>
<title>MiniApps Blog</title>
<link>http://miniapps.co.uk/blog/</link>
<description><![CDATA[Beautifully crafted mobile web apps.]]></description>
<language>en-us</language>
<pubDate>Fri, 18 May 2012 03:07:12 +0100</pubDate>
<item>
<title>Multi touch gestures using Webkit</title>
<link>http://miniapps.co.uk/blog/post/multi-touch-gestures-using-webkit/</link>
<pubDate>Wed, 10 Mar 2010 19:53:16 +0000</pubDate>
<description><![CDATA[<p>I thought it might be useful if I posted a working example that demonstrates how to use touch and gesture events on the iPhone/iPad using Safari and Webkit.</p>

<p>I won&#39;t go into depth covering the basics of how touch events work, you can read about that in <a href="http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/">this article</a>. What I will go into, is the basics of how my template works, so that you can easily adapt it for your own applications.</p>

<p>First, feel free to <a href="http://miniapps.co.uk/gesture/">view the live demo</a>, and <a href="http://miniapps.co.uk/gesture/touchGesture.js">read the documented code</a>.</p>

<p>The HTML template file consists of a single square block that can be touched, dragged, resized and rotated using touch events. The JavaScript file provides a basis for handling six different types of touch event. The first three, <em>touchstart</em>, <em>touchmove</em> and <em>touchend</em> are all used to handle single finger touch events. In the example, the square block can be touched and dragged around the screen using a single finger. You can easily see when a <em>touchstart</em> event is triggered, as the square will turn blue in colour. If you drag your finger when the square is blue, a <em>touchmove</em> event is then triggered, and the square will follow your finger. When you release your finger, a <em>touchend</em> event is triggered, and the square will turn back to its original colour and remain where you left it on the screen.</p>

<p>The next three touch events, <em>gesturestart</em>, <em>gesturemove</em> and <em>gestureend</em>, are all used to handle multi touch events. These class as any touch event that uses more than one finger. In the example, a <em>gesturestart</em> event is indicated by the square block turning red in colour. A <em>gesturechange</em> event is triggered by performing a typical two finger pinch/zoom/rotate gesture, which has the effect of scaling and rotating the square. When your fingers are released, a <em>gestureend</em> event is triggered, and the square turns back to its original colour. It will also remain at the scale and angle of rotation that you left it at.</p>

<p>Take some time to read through the documented code and understand the way events are triggered. Any questions, please feel free to <a href="http://miniapps.co.uk/contact/">get in touch</a>.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/multi-touch-gestures-using-webkit/</guid>
<category>Webkit</category>
</item>
<item>
<title>Serving iOS retina startup images for the new iPad</title>
<link>http://miniapps.co.uk/blog/post/serving-ios-retina-startup-images-for-the-new-ipad/</link>
<pubDate>Wed, 28 Mar 2012 21:52:51 +0100</pubDate>
<description><![CDATA[<p>In the past we have touched on how to serve iOS startup images for full screen web apps using both <a href="http://miniapps.co.uk/blog/post/ios-startup-images-using-css-media-queries/">CSS media queries and JavaScript</a> techniques. Now that the latest iPad sports a retina calibre display, we must again look at the best way to serve startup images in our web apps.</p>

<p>Given the potential bandwidth cost incurred by downloading such large images (2048 x 1496 landscape, 1536 x 2006 portrait), the most advisable technique is to use JavaScript to serve only the assets a device requires (rather than downloading every asset, which would happen if we used media queries). This can be done using the following code snippet in the <code>&lt;head&gt;</code> of your page.</p>

<pre><code>&lt;script&gt;(function(){
var p, l, r = window.devicePixelRatio;
if (navigator.platform === "iPad") {
    p = r === 2 ? "img/startup-tablet-portrait-retina.png" : "img/startup-tablet-portrait.png";
    l = r === 2 ? "img/startup-tablet-landscape-retina.png" : "img/startup-tablet-landscape.png";
    document.write('&lt;link rel="apple-touch-startup-image" href="' + l + '" media="screen and (orientation: landscape)"/&gt;&lt;link rel="apple-touch-startup-image" href="' + p + '" media="screen and (orientation: portrait)"/&gt;');
} else {
    p = r === 2 ? "img/startup-retina.png": "img/startup.png"; 
    document.write('&lt;link rel="apple-touch-startup-image" href="' + p + '"/&gt;');
}
})()&lt;/script&gt;</code></pre>

<p>You can test this code out using the <a href="http://miniapps.co.uk/code/splashjs/">example here</a>.</p>

<p>It would be nice if Apple would provide a better way to do this rather than having to rely on JavaScript. Perhaps in the future we will be able to have the option to use vector formats, such as <abbr>SVG</abbr> for startup images?</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/serving-ios-retina-startup-images-for-the-new-ipad/</guid>
<category>JavaScript</category>
</item>
<item>
<title>iOS startup images using CSS media queries</title>
<link>http://miniapps.co.uk/blog/post/ios-startup-images-using-css-media-queries/</link>
<pubDate>Mon, 24 Oct 2011 20:47:09 +0100</pubDate>
<description><![CDATA[<p>Ever since the arrival of the iPad and iPhone 4, serving correctly sized <code>apple-touch-startup-images</code> for <abbr>iOS</abbr> web apps has been somewhat problematic, especially if you wish to cater for every type of <abbr>iOS</abbr> device.</p>

<p>A common solution has been to use JavaScript to detect what device the user is on, and then to write the correct image into the <code>&lt;head&gt;</code> of your <abbr>HTML</abbr> file.</p>

<pre><code>&lt;!-- iOS App Splash Screen --&gt;
(function () {
	var filename;
	if (navigator.platform === 'iPad') {
		filename = window.orientation === 90 || window.orientation === -90 ? 'splash-1024x748.png' : 'splash-768x1004.png';
	} else {
		filename = window.devicePixelRatio === 2 ? 'splash-640x920.png' : 'splash-320x460.png';
	}
	document.write('&lt;link rel="apple-touch-startup-image" href="' + filename + '"/&gt;' );
})();
&lt;/script&gt;</code></pre>

<p>To make things more complicated, you also need to serve a high-res startup image for the iPhone 4's retina display. The iPad requires two different splash screen images for each orientation as well. Things quickly start to get a bit messy&hellip;</p>

<p>As of iOS5, you can now use <abbr>CSS</abbr> Media Queries to serve each type of startup image required, so no need for JavaScript anymore!</p>

<p>Just use any of the following media queries in the <code>&lt;head&gt;</code> of your <abbr>HTML</abbr> file.</p>

<pre><code>&lt;!-- 320x460 for iPhone 3GS --&gt;
&lt;link rel="apple-touch-startup-image" media="(max-device-width: 480px) and not (-webkit-min-device-pixel-ratio: 2)" href="startup-iphone.png" /&gt;

&lt;!-- 640x920 for retina display --&gt;
&lt;link rel="apple-touch-startup-image" media="(max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2)" href="startup-iphone4.png" /&gt;

&lt;!-- iPad Portrait 768x1004 --&gt;
&lt;link rel="apple-touch-startup-image" media="(min-device-width: 768px) and (orientation: portrait)" href="startup-iPad-portrait.png" /&gt;

&lt;!-- iPad Landscape 1024x748 --&gt;
&lt;link rel="apple-touch-startup-image" media="(min-device-width: 768px) and (orientation: landscape)" href="startup-iPad-landscape.png" /&gt;</code></pre>

<p>If you are on <abbr>iOS5</abbr> you can check out an <a href="http://miniapps.co.uk/code/applestartup/">online demo here</a>. Add the web page to your home screen and then launch from the icon.</p>

<h3>Caveat</h3>

<p>The only drawback to this CSS only method is that every image seems to be downloaded, regardless of which one is used on the device. If your application is supporting both iPhone and iPad, it may be worth using the JavaScript solution still. But the choice is yours to make, depending on the number of files and their respective sizes. Hopefully Apple will eventually support another solution to serving the correct file, such as using the <code>sizes</code> attribute.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/ios-startup-images-using-css-media-queries/</guid>
<category>CSS</category>
</item>
<item>
<title>Adaptive CSS layouts using Media Queries</title>
<link>http://miniapps.co.uk/blog/post/adaptive-css-layouts-using-media-queries/</link>
<pubDate>Wed, 23 Jun 2010 22:03:06 +0100</pubDate>
<description><![CDATA[<p>(Update 10/10/11) This an old blog post, and is no longer true to the way this site is built. If you would like to read about more current techniques, check out the article on <a href="http://miniapps.co.uk/blog/post/site-redesign-a-mobile-first-approach/">mobile first, responsive design</a>.</p>

<p>Over the past few weeks I have been refining the <a href="http://www.w3.org/TR/css3-mediaqueries/">CSS3 Media Queries</a> on this site in order to try and create an adaptive layout that can scale and resize to any window or screen size, whether it be on desktop, tablet or mobile device. I think (hope) that I&#39;ve got things flowing pretty smoothly now, so I thought I would post the queries here so that others can adapt them:</p>

<pre>
<code>&lt;!-- CSS MAIN STYLESHEET --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot; media=&quot;all&quot; /&gt;

&lt;!-- LAYOUTS SMALLER THAN 650px AND MOBILES --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;mobile.css&quot; media=&quot;handheld, screen and (max-width: 650px), screen and (max-device-width: 480px)&quot; /&gt;

&lt;!-- LAYOUTS BETWEEN 651px/1024px AND iPAD --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;tablet.css&quot; media=&quot;screen and (min-width:651px) and (max-width: 1024px), screen and (min-device-width: 768px) and (max-device-width: 1024px)&quot; /&gt;</code></pre>

<p>I could have included all three media queries inside a single CSS file using the <code>@media</code> rule, but I quite like to keep things separate for simplicity. For now, I have chosen to use three individual stylesheets. The main site stylesheet (<code>styles.css</code>) is used as a master, and then the separate <code>mobile.css</code> and <code>tablet.css</code> stylesheets override certain CSS rules in the main stylesheet, to provide an optimised view that is dependant on the media query being used. I have also used queries based on both <code>min/max-width</code> and <code>min/max-device-width</code>, so that both desktop browsers and intermediate size devices can also make use of the adaptive stylesheets. Have a go at resizing your browser window to see the results.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/adaptive-css-layouts-using-media-queries/</guid>
<category>CSS</category>
</item>
<item>
<title>Targeting iPhone 4 using CSS Media Queries</title>
<link>http://miniapps.co.uk/blog/post/targeting-iphone-4-using-css-media-queries/</link>
<pubDate>Sat, 26 Jun 2010 16:12:09 +0100</pubDate>
<description><![CDATA[<p>With the release of iPhone 4 and it&#39;s 326<abbr>ppi</abbr> display, there has been a fair bit of speculation as to what impact this would have on mobile web apps and websites that are optimised for mobile screen sizes. How would web developers target both older iPhones with a 480<abbr title="times">x</abbr>320 display, as well as the iPhone 4&#39;s 960<abbr title="times">x</abbr>640 display? Would we need separate <abbr>CSS</abbr> stylesheets for each device? How would images need to be optimised for the new screens?</p>

<p>It turns out that <abbr>CSS</abbr> media queries <a href="http://miniapps.co.uk/blog/post/adaptive-css-layouts-using-media-queries/">targeting 320px screens</a> still work on iPhone 4. It&#39;s all down to Mobile Safari utilising a <em>&#39;device to pixel ratio&#39;</em> density of 2. There is actually a distinct difference between a device (screen) pixel and a pixel that we typically define in <abbr>CSS</abbr>. For example, when the iPhone 4 browser viewport is equal to the device width, 1 <abbr>CSS</abbr> pixel actually translates to 2<abbr title="times">x</abbr>2 device pixels. For those interested, there is a quite old (but very relevant) Webkit article about <a href="http://webkit.org/blog/55/high-dpi-web-sites/">high <abbr>dpi<abbr> websites</abbr></abbr></a>. It makes for an interesting read.</p>

<p>This is largely good news for mobile web developers, as very little needs to be done to our mobile <abbr>CSS</abbr> stylesheets for iPhone 4. Device pixels are translated to <abbr>CSS</abbr> pixels automatically. But what about images? Well, this is where some work needs to be done. In order for images to look crisp on the new iPhone 4 display, we now need to serve images that have a higher <abbr>ppi</abbr> than the standard web traditionally uses. To do this, the iPhone 4 (and any other high <abbr>ppi</abbr> device) can be targeted using the following <abbr>CSS</abbr> media query (Notice I have included rules both with and without the -webkit venor prefix).</p>

<p>Update (07/10/11) - the code below has now been updated to include additional vendor prefix properties, that did not exist at the original time of publishing this article.</p>

<pre>
<code>/* High PPI Devices ----------- */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
only screen and (min--moz-device-pixel-ratio: 1.5),
only screen and (-o-device-pixel-ratio: 3/2), 
only screen and (min-device-pixel-ratio: 1.5) {

	//high resolution images go here

}</code></pre>

<p>I won&#39;t go into great detail on how to best serve images, but it basically involves creating images that are double the pixel size that you would traditionally need (<abbr title="For example">e.g.</abbr> a 100<abbr title="times">x</abbr>50 pixel image translates to 200<abbr title="times">x</abbr>100 pixels). You can then set the <a href="http://www.w3.org/TR/2002/WD-css3-background-20020802/#background-size">background size in <abbr>CSS</abbr></a> so the large images still take up the same number of <abbr>CSS</abbr> pixels as they would on a normal display. <a href="http://blog.iwalt.com/2010/06/targeting-the-iphone-4-retina-display-with-css3-media-queries.html">Walt Dickinson</a> has already written a nice article that has some more info on how to do this.</p>

<p>Finally, one last tip &ndash; you can also test for the same value using using JavaScript:</p>

<pre>
<code>if (window.devicePixelRatio == 2) {

//Targeted code goes here

}</code></pre>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/targeting-iphone-4-using-css-media-queries/</guid>
<category>CSS</category>
</item>
<item>
<title>Pixel perfect icons for iOS devices using CSS Media Queries</title>
<link>http://miniapps.co.uk/blog/post/pixel-perfect-icons-for-ios-devices-using-css-media-queries/</link>
<pubDate>Fri, 02 Jul 2010 14:26:31 +0100</pubDate>
<description><![CDATA[<p>Jesse Dodds has written an excellent article on how to serve <a href="http://notes.jessedodds.com/post/730336221">pixel perfect web clip icons</a> for Apple iOS devices using CSS3 Media Queries. Well worth a look.</p>

<pre>
<code>&lt;!-- iPHONE 3G WEB CLIP ICON --&gt;
&lt;link rel=&quot;apple-touch-icon-precomposed&quot; media=&quot;screen and (resolution: 163dpi)&quot; href=&quot;iOS-57.png&quot; /&gt;
&lt;!-- iPAD WEB CLIP ICON --&gt;
&lt;link rel=&quot;apple-touch-icon-precomposed&quot; media=&quot;screen and (resolution: 132dpi)&quot; href=&quot;iOS-72.png&quot; /&gt;
&lt;!-- iPHONE 4 WEB CLIP ICON --&gt;
&lt;link rel=&quot;apple-touch-icon-precomposed&quot; media=&quot;screen and (resolution: 326dpi)&quot; href=&quot;iOS-114.png&quot; /&gt;</code></pre>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/pixel-perfect-icons-for-ios-devices-using-css-media-queries/</guid>
<category>CSS</category>
</item>
<item>
<title>WKTouch - Multi-touch JavaScript plugin for Apple iOS</title>
<link>http://miniapps.co.uk/blog/post/wktouch-multi-touch-javascript-plugin-for-apple-ios/</link>
<pubDate>Mon, 19 Jul 2010 19:53:02 +0100</pubDate>
<description><![CDATA[<p>I&#39;ve just released a little JavaScript plugin called WKTouch up on <a href="http://github.com/alexgibson/WKTouch">github</a>. It&#39;s a tiny plugin for Apple&#39;s <abbr>iOS</abbr> Safari browser, enabling multi&ndash;touch drag, scale and rotate on <abbr>HTML</abbr> elements.</p>

<p>Using the plugin is pretty simple. Firstly, include the main JavaScript file in the header of your <abbr>HTML</abbr> document:</p>

<pre>
<code>&lt;script type=&quot;text/javascript&quot; src=&quot;WKTouch.js&quot;&gt;&lt;/script&gt;</code></pre>

<p>Next, add the following <abbr>CSS</abbr> to your stylesheet. Please note, your <abbr>HTML</abbr> element must use absolute positioning:</p>

<pre>
<code>.touch {
    -webkit-user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
    -webkit-text-size-adjust: none;
    -webkit-touch-callout: none; 
}

#element1 {
    position: absolute;
    left: 10px;
    top: 10px;
    height:120px; 
    width:120px;
    background-color: blue;
}</code></pre>

<p>Now add the class name and <abbr>id</abbr> to your <abbr>HTML</abbr> element:</p>

<pre>
<code>&lt;div class=&quot;touch&quot; id=&quot;element1&quot;&gt;&lt;/div&gt;</code></pre>

<p>Finally, in the head of your <abbr>HTML</abbr> file, include the following JavaScript to create a new instance of the plugin, making sure to pass it the <abbr>id</abbr> of your <abbr>HTML</abbr> element:</p>

<pre>
<code>&lt;script type=&quot;text/javascript&quot;&gt; 
window.onload = function() {                     
    var element1 = new WKTouch(&#39;element1&#39;).init();       
};
&lt;/script&gt;</code></pre>

<p>That&#39;s it! You can view a fully working <a href="http://miniapps.co.uk/code/wktouch/">online demo here</a> using multiple instances of the plugin on one page. You can also download or checkout the source over on <a href="http://github.com/alexgibson/WKTouch">github</a>.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/wktouch-multi-touch-javascript-plugin-for-apple-ios/</guid>
<category>JavaScript</category>
</item>
<item>
<title>iOS 4.2.1 brings some major new features to Mobile Safari</title>
<link>http://miniapps.co.uk/blog/post/ios-421-brings-some-major-new-features-to-mobile-safari/</link>
<pubDate>Tue, 23 Nov 2010 11:21:11 +0000</pubDate>
<description><![CDATA[<p>Apple has just released iOS 4.2.1 which offers some really interesting new features and improvements to Apple&#39;s Safari mobile browser. New features include access to the Accelerometer via the <a href="http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceMotionEventClassRef/DeviceMotionEvent/DeviceMotionEvent.html">DeviceMotion</a> event class, Gyroscope event data via the <a href="http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html">DeviceOrientationEvent</a> class, an implementation of <abbr>HTML5</abbr> <a href="http://dev.w3.org/html5/websockets/">WebSockets <abbr>API</abbr></a> and a <a href="http://developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/StyleMedia/StyleMedia/StyleMedia.html">StyleMedia</a> class for querying <abbr>CSS</abbr> features via JavaScript. There is also improved support for web fonts amongst other useful enhancements.</p>

<p>There is a nice blog post detailing many of the new features over on <a href="http://www.mobilexweb.com/blog/safari-ios-accelerometer-websockets-html5">Mobile Web Programming</a>.</p>

<p>I&#39;d still like to see access to things such as the iPhone camera, photo library and contacts &mdash; but this is a great looking update for iOS users and mobile web developers.</p>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/ios-421-brings-some-major-new-features-to-mobile-safari/</guid>
<category>Webkit</category>
</item>
<item>
<title>WKShake - 'Shake to Undo' JavaScript plugin for iOS Mobile Safari/Webkit</title>
<link>http://miniapps.co.uk/blog/post/wkshake-shake-to-undo-javascript-plugin-for-ios-mobile-safari-webkit/</link>
<pubDate>Thu, 25 Nov 2010 09:51:29 +0000</pubDate>
<description><![CDATA[<p>I&#39;ve created a little JavaScript plugin that emulates the familiar &#39;shake to undo&#39; gesture found in many iOS apps, so you can now use it in your web applications on iOS 4.2.1 onward.</p>

<p>Check out the <a href="http://alexgibson.github.com/shake.js/examples/basic.html">online demo</a>, or alternatively grab the source direct from <a href="http://alexgibson.github.com/shake.js/">GitHub</a>.</p>

<p>Note: WKShake has since been renamed to <em>shake.js</em>.</p>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/wkshake-shake-to-undo-javascript-plugin-for-ios-mobile-safari-webkit/</guid>
<category>JavaScript</category>
</item>
<item>
<title>WKTouch and WKSlider now hardware accelerated in Mobile Webkit / Safari</title>
<link>http://miniapps.co.uk/blog/post/wktouch-and-wkslider-now-hardware-accelerated-in-mobile-webkit-safari/</link>
<pubDate>Thu, 10 Feb 2011 11:38:43 +0000</pubDate>
<description><![CDATA[<p>I&#39;ve recently pushed a few updates to <a href="https://github.com/alexgibson/WKTouch">WKTouch</a> and <a href="https://github.com/alexgibson/WKSlider">WKSlider</a> on GitHub that enable full hardware acceleration in Mobile Webkit / Safari. iOS users now get a considerable performance boost when dragging and manipulating objects and UI elements. This is achieved by using CSS 3D transformations where available, as iOS devices offload these processes to the device GPU. For Webkit devices that do not yet support CSS 3D transforms (such as Android), the plugins provide a fallback using regular 2D transformations.</p>

<p>Another small improvement to WKTouch is the ability to drag an object at the same time as performing a two finger scale / rotate gesture.</p>

<p>Head over to the <a href="http://miniapps.co.uk/code/">code</a> section to try out demos of each plugin, or check out the source over on <a href="https://github.com/alexgibson/">GitHub</a>.</p>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/wktouch-and-wkslider-now-hardware-accelerated-in-mobile-webkit-safari/</guid>
<category>Webkit</category>
</item>
<item>
<title>New sizes attribute in iOS 4.2.1 for web clip icons</title>
<link>http://miniapps.co.uk/blog/post/new-sizes-attribute-in-ios-421-for-web-clip-icons/</link>
<pubDate>Tue, 30 Nov 2010 09:31:06 +0000</pubDate>
<description><![CDATA[<p>A small but relatively undiscovered new feature in iOS 4.2.1 is the new <a href="http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html">&#39;sizes&#39; attribute</a> for defining different sized web clip icons. Instead of using <a href="http://miniapps.co.uk/blog/post/pixel-perfect-icons-for-ios-devices-using-css-media-queries/">previous methods</a>, Apple now have a custom attribute you can use to target different device resolutions on iOS. Here&#39;s an example:</p>

<pre>
<code>&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;touch-icon-iphone.png&quot; /&gt;
&lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;72x72&quot; href=&quot;touch-icon-ipad.png&quot; /&gt;
&lt;link rel=&quot;apple-touch-icon&quot; sizes=&quot;114x114&quot; href=&quot;touch-icon-iphone4.png&quot; /&gt;</code></pre>

<p>Now what we really need is for this new attribute to also work on <code>apple-touch-startup-image</code>, so we can finally define different resolution startup images.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/new-sizes-attribute-in-ios-421-for-web-clip-icons/</guid>
<category>Webkit</category>
</item>
<item>
<title>Using HTML5 localStorage as a fallback for offline form submission</title>
<link>http://miniapps.co.uk/blog/post/using-html5-localstorage-as-a-fallback-for-offline-form-submission/</link>
<pubDate>Sat, 18 Dec 2010 20:39:50 +0000</pubDate>
<description><![CDATA[<p>I recently put together a working demo for a client showing how you might use HTML5 localStorage as a fallback for form data submission when a mobile device is offline without signal. I&#39;ve uploaded a <a href="http://miniapps.co.uk/code/offlineform/">working demo</a> for anyone interested and the full source code is over on <a href="https://github.com/alexgibson/OfflineForm">GitHub</a>.</p>

<p>The demo uses <code>window.navigator.onLine</code> to listen for a boolean value of <code>true</code> or <code>false</code>, determining whether the device is <em>online</em> or <em>offline</em>. When online, the app makes a regular <code>XmlHttpRequest</code> and sends data to a server. If the device loses signal and goes offline, the app queues up and saves submitted data to <code>localStorage</code> as a JSON string. When online connection is next restored, the app then re-sends the queued data to the server automatically. Once the data has been sent successfully, the item is then removed from localStorage.</p>

<p>I won&#39;t go through all the code line by line as it&#39;s reasonably straight forward, but feel free to take a closer look on <a href="https://github.com/alexgibson/OfflineForm">GitHub</a>. Many Webkit based smart phones now support <code>window.navigator.onLine</code>, as does desktop Safari or Firefox. To test, try enabling flight mode on your phone, or disable wifi on your laptop once the app is open.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/using-html5-localstorage-as-a-fallback-for-offline-form-submission/</guid>
<category>JavaScript</category>
</item>
<item>
<title>WKSlider - A touch slider UI JavaScript plugin for Mobile Webkit</title>
<link>http://miniapps.co.uk/blog/post/wkslider-a-touch-slider-ui-javascript-plugin-for-mobile-webkit/</link>
<pubDate>Thu, 23 Dec 2010 09:33:24 +0000</pubDate>
<description><![CDATA[<p>I&#39;ve just released another JavaScript plugin for Mobile Webkit, this time a simple to use touch&ndash;based slider UI plugin. So far I&#39;ve tested it successfully on iOS, Android and Opera Mobile 10.1.</p>

<p>Check out the <a href="http://miniapps.co.uk/code/wkslider/">online demo</a>, or alternatively grab the source direct from <a href="https://github.com/alexgibson/WKSlider">GitHub</a>.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/wkslider-a-touch-slider-ui-javascript-plugin-for-mobile-webkit/</guid>
<category>JavaScript</category>
</item>
<item>
<title>Tap.js - A lightweight 'tap' event JavaScript plugin</title>
<link>http://miniapps.co.uk/blog/post/tapjs-a-lightweight-tap-event-javascript-plugin/</link>
<pubDate>Mon, 12 Mar 2012 20:49:45 +0000</pubDate>
<description><![CDATA[<p>While the <a href="http://www.w3.org/TR/touch-events/">W3C touch events API</a> is quite flexible in its low-level implementation for dealing with multi-touch interaction, it means that the higher level gestures we use daily in our web apps can take <a href="http://miniapps.co.uk/blog/post/event-delegation-for-touch-events-in-javascript/">quite a lot of work</a> for developers to implement themselves, even down to the basic 'tap' event. Many mobile web frameworks already offer support for such gestures, but if your app does not use or require such a framework, something as simple as a 'tap' plugin can become a necessity on nearly every mobile project.</p>

<p><a href="https://github.com/alexgibson/tap.js">Tap.js</a> is a simple, lightweight plugin for a common 'tap' gesture. It has no dependencies and can be used just like any regular JavaScript event, along with standard event listener syntax. It also falls back to using regular mouse events when touch is not supported, so you don't need to manually feature detect or provide two different event types in your code.</p>

<h3>Setup</h3>

<p>First, include the main JavaScript file in the <code>&lt;head&gt;</code> of your HTML document:</p>

<pre><code>&lt;script src="tap.js"&gt;&lt;/script&gt;</code></pre>

<p>Next create a new Tap instance, passing the element you want to use:</p>

<pre><code>var el = document.getElementById('my-id'),
    myTap = new Tap(el);</code></pre>

<p>You can then start listening for 'tap' events using the regular JavaScript event listener syntax:</p>

<pre><code>el.addEventListener('tap', tapDidOccur, false); 
function tapDidOccur (e) {
    //your code
}</code></pre>

<p>You can stop listening for tap events like so:</p>

<pre><code>el.removeEventListener('tap', tapDidOccur, false);</code></pre>

<p>Tap.js is open source and available on <a href="https://github.com/alexgibson/tap.js">GitHub</a>.</p>

<h4>Tested browsers</h4>

<ul>
<li>iOS Safari (5.1)</li>
<li>Android default browser (2.3.5)</li>
<li>Opera Mobile 11.50 (Android)</li>
<li>BlackBerry Playbook (1.0.8.6067)</li>
<li>HP webOS 2.1.0 (click fallback)</li>
<li>All modern desktop browsers (click fallback)</li>
</ul>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/tapjs-a-lightweight-tap-event-javascript-plugin/</guid>
<category>JavaScript</category>
</item>
<item>
<title>Enable CSS active pseudo styles in Mobile Safari</title>
<link>http://miniapps.co.uk/blog/post/enable-css-active-pseudo-styles-in-mobile-safari/</link>
<pubDate>Mon, 17 Oct 2011 10:05:08 +0100</pubDate>
<description><![CDATA[<p>By default Mobile Safari disables <abbr>CSS</abbr> active pseudo styles on web pages, instead opting for a generic tap&ndash;highlight colour on clickable elements. A little known trick is that you can easily re-enable your active pseudo styles by declaring a <code>touchstart</code> event on the page. You don't even need to actually use the event, simply declaring an empty function will suffice.</p>

<p>Just add the following single line of JavaScript to your web page and all your active CSS styles will spring to life.</p>

<pre><code>document.addEventListener("touchstart", function() {},false);</code></pre>

<p>Note: if you do this trick it is also worth removing the default tap&ndash;highlight colour Mobile Safari applies using the following CSS rule.</p>

<pre><code>html {
	-webkit-tap-highlight-color: rgba(0,0,0,0);
	tap-highlight-color: rgba(0,0,0,0);
}</code></pre>

<p>You can view an <a href="http://miniapps.co.uk/code/pseudo-active/">online demo here</a>.</p>

<img class="qr no-float" width="150" height="150" src="http://goo.gl/opbNr.qr" alt="QR Code to launch app" title="Launch this demo directly on your mobile phone by scanning this barcode." />

<p>On a related note, there are also some other useful mobile Webkit oddities that can activated by using empty event declarations, like <a href="http://krijnhoetmer.nl/stuff/javascript/label-checkbox-ios/">making form labels clickable</a>.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/enable-css-active-pseudo-styles-in-mobile-safari/</guid>
<category>JavaScript</category>
</item>
<item>
<title>Making web content more accessible with iOS VoiceOver</title>
<link>http://miniapps.co.uk/blog/post/making-web-content-more-accessible-with-ios-voiceover/</link>
<pubDate>Mon, 06 Jun 2011 10:34:49 +0100</pubDate>
<description><![CDATA[<p>If you&#39;re a web developer and own an <abbr>iOS</abbr> device, you may have noticed it comes with a whole range of accessibility features. One such feature is a built-in screen reader for visually impaired users, called <em>VoiceOver</em>. For a touch screen device, VoiceOver is a wonderfully capable piece of assistive technology, and a very useful tool that you can use to help test the accessibility of your web content.</p>

<p>This article gives an introduction to using VoiceOver on <abbr>iOS</abbr>, followed by some basic tips to help improve the accessibility of your web content. While covering <abbr>iOS</abbr> specifically for example&#39;s sake, many of these tips are also applicable to improving accessibility for screen reader users in general.</p>

<h4>Navigating a web page using VoiceOver on <abbr>iOS</abbr></h4>

<p>You can enable VoiceOver on <abbr>iOS</abbr> by going to: <em>Settings -&gt; General -&gt; Accessibility -&gt; VoiceOver</em>.</p>

<p>Using VoiceOver at its most basic level involves selecting an item by touching it, activating a selected item by double-tap, and scrolling by flicking three fingers. You can also swipe left/right to navigate through content elements in the natural order of your page&rsquo;s markup. For quick page navigation, you can swipe up/down to jump through predefined sections of web content, such as headings, links, words, lines and even landmark roles. These pre-defined options are selected via a feature known as Rotator. A user can cycle through Rotator settings using a two finger rotation gesture anywhere on screen. The selected option is then read aloud as you rotate your fingers.</p>

<p>Aside from regular click events which operate using double-tap, touch events operate a little differently with <abbr>iOS</abbr> VoiceOver, since they rely on dragging the finger and not just tapping. If a web page features an element that has a touch event associated with it, the user must double-tap &amp; hold on the element until an audible sound effect of three small tones is heard. Once the tones have played, VoiceOver then allows a touch gesture to be performed and ignores all other actions until the finger is next released. At this point VoiceOver returns back to it&#39;s normal state.</p>

<p>This may sound like a lot to remember at first, but VoiceOver is actually very simple to use and feels very intuitive after just a few sessions. Give it a go before reading on and try to familiarize yourself with the gestures.</p>

<p>There is a nice <a href="http://www.apple.com/accessibility/iphone/vision.html">introduction to VoiceOver on the iPhone</a> over on Apple&#39;s website for some more in-depth examples and other features not covered here.</p>

<h4>Using <abbr title="Accessible Rich Internet Applications">WAI-ARIA</abbr> landmark roles</h4>

<p>As you will have discovered after trying VoiceOver, one of the fastest ways to navigate through a large web page is to use the Rotator feature. If your web pages use well structured headings and markup, then your pages should already be relatively easy to navigate. A nice additional feature you can take advantage of however, is the use of <a href="http://www.w3.org/WAI/PF/aria-practices/"><abbr>WAI-ARIA</abbr> landmark roles</a>. These role attributes enable screen reader users to quickly jump to predefined sections of a web page, and these can be accessed by VoiceOver using the Rotator &#39;landmark&#39; option.</p>

<p>Here&#39;s some basic <abbr>HTML5</abbr> markup for a common web page complete with landmark roles:</p>

<pre>
<code>&lt;header role=&quot;banner&quot;&gt;
     &lt;h1&gt;Page heading&lt;/h1&gt;
&lt;/header&gt;

&lt;div role=&quot;main&quot;&gt;
     &lt;section role=&quot;region&quot;&gt;
          &lt;h2&gt;Sub heading 1&lt;/h2&gt;
     &lt;/section&gt;
     &lt;section role=&quot;region&quot;&gt;
          &lt;h2&gt;Sub heading 2&lt;/h2&gt;
     &lt;/section&gt;
&lt;/div&gt;

&lt;footer role=&quot;contentinfo&quot;&gt;
     &lt;h4&gt;Footer title&lt;/h4&gt;
&lt;/footer&gt;</code></pre>

<p>Note: as of <abbr>iOS</abbr> 4.3 the &#39;landmark&#39; option is not included as a default rotator setting, and must be selected first in the general accessibility options. <abbr>iOS</abbr> does not currently read out the landmark types either, it just simply describes each as &#39;landmark start&#39; and &#39;landmark end&#39;.</p>

<h4>Hiding and showing content</h4>

<p>Because many client-based web applications are often just single page controllers that hide and show content when switching between views, it is important to make sure that only visible content is accessible to screen readers. If you can&#39;t visually see something on screen, then (usually) it should be hidden from assistive technologies as well. Some mobile web applications simply slide elements in and out of the viewport when transitioning between screens. This can be problematic since elements that are not visible can still be read out and accessed by VoiceOver.</p>

<p>You can hide an HTML element from screen readers by setting the <code>aria-hidden</code> attribute to true. Likewise, setting the value to false will un-hide the element again.</p>

<pre>
<code>document.querySelector(&#39;#panel&#39;).setAttribute(&#39;aria-hidden&#39;, &#39;true&#39;); //not visible
document.querySelector(&#39;#panel&#39;).setAttribute(&#39;aria-hidden&#39;, &#39;false&#39;); //visible</code></pre>

<p>If you wish to visually hide the content as well, you can also take advantage of this attribute to set the element&#39;s <code>display</code> property in <abbr>CSS</abbr> like so.</p>

<pre>
<code>#panel[aria-hidden=&quot;true&quot;] { display: none; }
#panel[aria-hidden=&quot;false&quot;] { display: block; }</code></pre>

<p>Note here we are only changing the <code>display</code> property for the element <code>#panel</code> and not simply for every element that might have <code>aria-hidden</code> applied. There are situations where you might want content hidden from screen readers, but still visible on screen. Take for example, if your website creates a floating dialog box that is displayed on top of the existing page. In this case the content is still visible behind the dialog box, but should not be accessible until the user responds and the dialog box is closed. Here you might want to apply <code>aria-hidden</code> to the page behind, but not actually change the <code>display</code> property.</p>

<h4>Making faux-buttons behave like buttons</h4>

<p>While it is advisable to use a native <abbr>HTML</abbr> <code>&lt;button&gt;</code> element wherever possible, sometimes you may want to (for stylistic reasons) make a non-interactive <abbr>HTML</abbr> element such as a <code>&lt;div&gt;</code>, act like a button.</p>

<pre>
<code>&lt;div id=&quot;my-button&quot;&gt;Button text&lt;/div&gt;</code></pre>

<p>It is important to make sure this behaves like an interactive element to VoiceOver, so assign a <code>role</code> attribute of type <code>button</code> to the element. The role attribute will enable VoiceOver to verbally identify the element just as it would do a native <abbr>HTML</abbr> <code>&lt;button&gt;</code>.</p>

<pre>
<code>&lt;div id=&quot;my-button&quot; role=&quot;button&quot;&gt;Button text&lt;/div&gt;</code></pre>

<p>Now that VoiceOver identifies the element as a button and not just a piece of text, it makes it much clearer how the user should interact with this element and that they should and double-tap to activate it.</p>

<h4>Providing textual descriptions for icons</h4>

<p>It is common to use visual icons to represent actions that buttons perform on mobile devices. Icons have the advantage of saving valuable screen space and are often universally understood. For assistive technologies, it is still important to provide a textual alternative. Take for example the following faux-button that does not contain any inner text.</p>

<pre>
<code>&lt;div id=&quot;edit-button&quot; role=&quot;button&quot;&gt;&lt;/div&gt;
</code></pre>

<p>Here we must use another piece of <abbr>HTML</abbr> markup that is visible to assistive technologies, in order to provide a textual label.</p>

<pre>
<code>&lt;p class=&quot;hide&quot; id=&quot;edit-label&quot;&gt;Edit item&lt;/p&gt;</code></pre>

<p>We can then link the button with the textual label using the <code>aria-labelledby</code> attribute on our faux-button.</p>

<pre>
<code>&lt;div id=&quot;edit-button&quot; role=&quot;button&quot; aria-labelledby=&quot;edit-label&quot;&gt;&lt;/div&gt;</code></pre>

<p>In order to hide the textual label visually on the screen, but not from assistive technology, we can position the label off screen.</p>

<pre>
<code>.hide {
	position: absolute;
	top: -20em;
	left: -200em;
}</code></pre>

<p>When VoiceOver gains focus on the element, it will now read out the label, before describing the role.</p>

<h4>Final Note</h4>

<p>These are just a few basic things that you can do to help improve the accessibility of your web content for VoiceOver on <abbr>iOS</abbr>. Mobile specific content is sadly often forgotten when it comes to accessibility, since many still regard it as not having the right tools available to assist people. It is a good thing that iOS uses the same underlying technology as VoiceOver for Mac <abbr>OSX</abbr>, because if you&#39;re building accessible content for the web, then you&#39;re already well on the way to providing a great experience on <abbr>iOS</abbr> too.</p>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/making-web-content-more-accessible-with-ios-voiceover/</guid>
<category>Accessibility</category>
</item>
<item>
<title>Different ways to trigger touchcancel in mobile browsers</title>
<link>http://miniapps.co.uk/blog/post/different-ways-to-trigger-touchcancel-in-mobile-browsers/</link>
<pubDate>Fri, 23 Dec 2011 09:30:54 +0000</pubDate>
<description><![CDATA[<p>The <code>touchcancel</code> event is often neglected when building touch&ndash;interfaces using JavaScript. Historically, browsers vendors have never really published documentation detailing the circumstances as to when this event gets fired, and hence it has always been associated with a level of obscurity by many developers. The aim of this post is to try and shed some light on the matter.</p>

<p>Apple originally created touch events for <abbr>iOS</abbr> Safari, which have since been adopted as a basis for the <a href="http://www.w3.org/TR/2011/WD-touch-events-20110505/">W3C Touch Events Specification</a>. The original <a href="http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html#//apple_ref/doc/uid/TP40009358">Safari DOM Additions Reference</a> documentation provides very little information on <code>touchcancel</code>:</p>

<blockquote>
	<p>Sent when the system cancels tracking for the touch.</p>
</blockquote>

<p>Thankfully, the W3C Touch Events specification <a href="http://www.w3.org/TR/2011/WD-touch-events-20110505/#the-touchcancel-event">gives us a bit more detail</a>, including some situations where the event should occur:</p>

<blockquote>
	<p>A user agent must dispatch this event type to indicate when a touch point has been disrupted in an implementation-specific manner, such as a synchronous event or action originating from the UA canceling the touch, or the touch point leaving the document window into a non-document area which is capable of handling user interactions. (e.g. The UA's native user interface, plug-ins) A user agent may also dispatch this event type when the user places more touch points on the touch surface than the device or implementation is configured to store, in which case the earliest Touch object in the TouchList should be removed.</p>
</blockquote>

<p>From this description we can begin to understand <code>touchcancel</code> with regard to browser behaviour a little better. It not only helps the browser keep accurate references to active <code>Touch</code> objects in the <code>TouchList</code>, but it can also be used by developers to carry out <abbr>UI</abbr> specific tasks, such as reseting any variables used during <code>touchstart</code> or <code>touchmove</code>. In the event that the system cancels tracking and the <code>touchend</code> event does not fire, <code>touchcancel</code> saves the day.</p> 

<p>But when do browsers actually trigger this event? To start investigating, it was necessary to build a <a href="http://miniapps.co.uk/code/touchcancel/">simple event logger</a> to track all touch events. This test features a touch-area and logs the last touch event fired, making it easier to see exactly what kind of interactions result in a <code>touchcancel</code>. Try it out in your browser and see how many ways you can manage to trigger the event.</p>

<p>What follows is a list of findings for various mobile web browsers. It is interesting to note that <code>touchcancel</code> is not very predictable, especially on Android (2.3.5). But even on <abbr>iOS5</abbr> you cannot always correctly guess what will trigger a <code>touchcancel</code>.</p>

<h3><abbr>iOS</abbr> Safari 5.0.1 (iPhone 4 &amp; iPad 1)</h3>

<p>Actions that <strong>do</strong> trigger <code>touchcancel</code> during a <code>touchstart</code> or <code>touchmove</code> event:</p>

<ul>
<li>User presses the home button.</li>
<li>User presses the action button in Safari's bottom toolbar.</li>
<li>User presses/smears the palm of their hand on the screen, creating no discernible single touch points (iPhone only?).</li>
<li>User presses the lock button.</li>
<li>User initiates a gesture using four or more simultaneous touch points on iPad and <em>Multitasking Gestures</em> are enabled in system preferences.</li>
</ul>

<p>Actions that do <strong>not</strong> trigger <code>touchcancel</code> during a <code>touchstart</code> or <code>touchmove</code> event:</p> 

<ul>
<li>User presses the bookmark button in Safari's bottom toolbar.</li>
<li>User presses the back or forward history buttons in Safari's bottom toolbar.</li>
<li>User taps to focus on the Safari search bar.</li>
<li>User rotate's the device orientation.</li>
<li>Popup notification such as WiFi locator or Clock timer alert appears on screen.</li>
<li>New <abbr>iOS5</abbr> style notification appears at top of the screen.</li>
<li>User opens a new tab (iPad).</li>
<li>User refreshes the page.</li>
<li>User presses the volume buttons.</li>
<li>User switches the device onto silent/vibrate.</li>
<li>User receives a phone call.</li>
</ul>

<p>In some of these circumstances the browser will simply fire a <code>touchend</code> instead of <code>touchcancel</code>. In others situations (such as the old&ndash;style popup notifications), <code>touchstart</code> or <code>touchmove</code> will remain active (even while the content is hidden underneath the notification), until the user releases their finger, at which point <code>touchend</code> is fired.</p>

<p>Notable <abbr>iOS5</abbr> system functions that will not activate during a <code>touchstart</code> or <code>touchmove</code> event:</p>

<ul>
<li>User cannot focus on the Safari address bar.</li>
<li>User cannot open a new page (iPhone).</li>
<li>User cannot double&ndash;tap the home button to open the app tray.</li>
<li>User cannot swipe down from the top of screen to open notification centre.</li>
<li>User cannot tap on a new <abbr>iOS5</abbr> style notification when it appears at the top of the screen.</li>
</ul>

<h3>Android 2.3.5 (Samsung Galaxy Y GT-S5363) stock browser</h3>

<p>Actions that <strong>do</strong> trigger <code>touchcancel</code> during a <code>touchstart</code> or <code>touchmove</code> event:</p>

<ul>
<li>User presses the lock button.</li>
<li>Appears to fire randomly for no immediately obvious reason. This is especially noticeable when performing repeated quick taps and swipes.</li>
</ul>

<p>Actions that do <strong>not</strong> trigger <code>touchcancel</code> during a <code>touchstart</code> or <code>touchmove</code> event:</p>

<ul>
<li>User presses the home button.</li>
<li>User rotate's the device orientation.</li>
<li>User presses the volume buttons.</li>
</ul>

<p>Notable Android 2.3.5 system functions that will not activate during a <code>touchstart</code> or <code>touchmove</code> event:</p>

<ul>
<li>User cannot press the menu or back buttons.</li>
<li>User cannot open notifications menu.</li>
<li>User cannot focus on the browser address bar.</li>
<li>User cannot tap the bookmarks button.</li>
</ul>

<p>Opera Mobile 11.50 for Android was also tested. While the browser appears to have support for <code>touchcancel</code>, it does not actually seem to fire the event. In the case of pressing the home button for example, Opera Mobile appears to immediately fire <code>touchend</code> instead.</p>

<h3>BlackBerry Playbook (1.0.8.6067)</h3>

<p>Even though the browser reportedly supports the <code>touchcancel</code> event, it does not appear to get fired at all. Even when pressing the power button to put the device on standby, <code>touchcancel</code> is not fired. The same goes for pressing browser tool bar buttons, or focusing on the address bar. It is also worth noting that when performing a <code>touchstart</code> or <code>touchmove</code>, the Playbook does not respond to any bevel swipe gestures.</p>

<h4>Conclusion</h4>

<p>It is appears from the tests that <code>touchcancel</code> is still a bit unpredictable. While it is easy enough to identify situations where it gets fired, there are often near identical situations where it does not. While the usefulness of this event is by no means in question, it seems like developers cannot yet rely on this event getting fired in all expected circumstances.</p>

<p>What is clear though, is that you cannot rely on <code>touchend</code> getting fired on every device. You <strong>need</strong> to write code that deals with <code>touchcancel</code>. This is especially true on the iPad for example, say if you're building a multi&ndash;touch app or multi&ndash;player <abbr>HTML5</abbr> game. Since there is no way of telling if the user has enabled Multitasking Gestures, your app needs to handle <code>touchcancel</code> gracefully. The unpredictable nature of Android browser also demonstrates the importance of dealing with this event, as failure to do so will likely cause bugs in your <abbr>UI</abbr>.</p>

<p>So, next time you're writing your own touch events, don't forget about <code>touchcancel</code>. Despite the varying levels of browser support, it still comes in very handy when dealing with certain unexpected user interactions.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/different-ways-to-trigger-touchcancel-in-mobile-browsers/</guid>
<category>JavaScript</category>
</item>
<item>
<title>Event delegation for touch events in JavaScript</title>
<link>http://miniapps.co.uk/blog/post/event-delegation-for-touch-events-in-javascript/</link>
<pubDate>Tue, 16 Aug 2011 21:02:51 +0100</pubDate>
<description><![CDATA[<p>Anyone who has experience developing web applications on mobile devices will have no doubt encountered the 300ms delay when firing <code>click</code> events in web browsers such as Mobile Safari. There are some useful <a href="https://github.com/cheeaun/tappable">standalone libraries</a> and <a href="http://code.google.com/mobile/articles/fast_buttons.html">informative articles</a> to help combat this delay, but this post aims to show a super&ndash;quick example of how to do simulated 'tap' events on dynamic content using JavaScript <em>event delegation</em>.</p>

<p>A common technique when dealing with <code>click</code> events in dynamic content is to use event delegation to capture events bubbling up through the <abbr>DOM</abbr>. This same technique can be applied to touch events, although it is a little more difficult since there are at least four different events to capture; <code>touchstart</code>, <code>touchmove</code>, <code>touchend</code> and <code>touchcancel</code>.</p>

<p>Here&#39;s a <a href="https://gist.github.com/1068146">Gist</a> containing a very basic example of how to capture a simulated &#39;tap&#39; event:</p>

<pre><code>var tapArea, moved, startX, startY;

tapArea = document.querySelector('#list'); //element to delegate
moved = false; //flags if the finger has moved
startX = 0; //starting x coordinate
startY = 0; //starting y coordinate

//touchstart			
tapArea.ontouchstart = function(e) {

	moved = false;
	startX = e.touches[0].clientX;
  	startY = e.touches[0].clientY;
};

//touchmove	
tapArea.ontouchmove = function(e) {

        //if finger moves more than 10px flag to cancel
        //code.google.com/mobile/articles/fast_buttons.html
	if (Math.abs(e.touches[0].clientX - startX) > 10 ||
      	Math.abs(e.touches[0].clientY - startY) > 10) {
    		moved = true;
  	}
};

//touchend
tapArea.ontouchend = function(e) {

	e.preventDefault();

        //get element from touch point
	var element = e.changedTouches[0].target;

        //if the element is a text node, get its parent.
	if (element.nodeType === 3) {	
		element = element.parentNode;
	}

	if (!moved) {
                //check for the element type you want to capture
		if (element.tagName.toLowerCase() === 'label') {
                        alert('tap');
                }
	}
};

//don't forget about touchcancel!
tapArea.ontouchcancel = function(e) {

        //reset variables
	moved = false;
	startX = 0;
  	startY = 0;
};</code></pre>

<p>Notice here it is useful to make use of <code>touchmove</code> to detect any finger dragging gestures that might occur after a <code>touchstart</code> has fired. This way it is easy to cancel the &#39;tap&#39; on <code>touchend</code> if desired.</p>

<p><strong>Update:</strong> Originally this article was using the function <code>document.elementFromPoint(x,y)</code> to get the element target in <code>ontouchend</code>. A few people have kindly pointed out that you can actually just use <code>e.changedTouches[0].target</code> or even <code>e.target</code> to get the same result for a simple 'tap'. It should be noted however, that the <code>target</code> attribute in this case always refers to the originating element, so if you do need to reference the element a finger might have moved on/off during <code>touchmove</code> or <code>touchend</code>, you would still need to use:</p> 

<pre><code>document.elementFromPoint(e.changedTouches[0].clientX, e.changedTouches[0].clientY)</code>.</pre> 

<p>Any questions, comments or suggestions feel free to leave one on the <a href="https://gist.github.com/1068146">Gist</a>. Life would be so much easier if we had a native 'tap' event in mobile browsers!</p>
]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/event-delegation-for-touch-events-in-javascript/</guid>
<category>JavaScript</category>
</item>
<item>
<title>Site redesign, a mobile first approach</title>
<link>http://miniapps.co.uk/blog/post/site-redesign-a-mobile-first-approach/</link>
<pubDate>Thu, 22 Sep 2011 11:30:17 +0100</pubDate>
<description><![CDATA[<p>Anyone who has visited this site over the last few weeks will no doubt have noticed a few changes. <a href="http://miniapps.co.uk/">MiniApps</a> has now had a complete design overhaul, which is probably long overdue given the current rise in interest of principals such as <a href="http://www.alistapart.com/articles/responsive-web-design/">responsive web design</a> and <a href="http://www.lukew.com/ff/entry.asp?933">mobile first</a>. What follows is a run down of basic changes to the site, in what hopefully makes for a much improved reading experience, in our rapidly changing, device-agnostic world.</p>

<h3>Establishing a useful baseline</h3>

<p>Rather than using a traditional <abbr>CSS</abbr> reset, MiniApps now uses <a href="http://necolas.github.com/normalize.css/">normalize.css</a> to establish a consistent baseline for cross-browser <abbr>CSS</abbr> rendering. Normalize.css makes web browsers render elements more consistently and in line with modern standards. It also preserves useful defaults and corrects common browser inconsistencies, unlike many <abbr>CSS</abbr> resets.</p>

<h3>Mobile First</h3>

<p>For a site where 62.46% of visitors in August to September 2011 were on mobile devices, this is real a no-brainer. Whilst the majority of mobile visitors to MiniApps are on more capable smart phone platforms such as <abbr>iOS</abbr> and Android (where a simple set of <a href="http://www.w3.org/TR/css3-mediaqueries/">CSS Media Queries</a> could suffice), given the <a href="http://www.lukew.com/ff/entry.asp?1405">continual rise</a> in the number of people using mobile devices to access the world wide web, it still makes sense to design using a <a href="http://www.lukew.com/ff/entry.asp?933">mobile first</a> approach.</p>

<p>The MiniApps site now serves styling for browsers in the following order:</p>

<ul>
<li>A default CSS style sheet suited to small&ndash;screen devices</li>
<li>CSS Media Queries then optimize content for larger screen sizes such as tablets, e&ndash;readers and desktop web browsers.</li>
<li>Note: since Internet Explorer 8 (and below) does not support <abbr>CSS</abbr> Media Queries, it is served a static set of <abbr>CSS</abbr> styles optimized for desktop, via a single conditional comment.</li>
<li>Update: <abbr>IE</abbr> Mobile is now set as version 7 in the conditional comment. This is because the new Mango update uses mobile <abbr>IE</abbr> 9 (thanks <a href="http://paulirish.com/">Paul Irish</a>!).</li>
</ul>

<pre><code>/* Default CSS for mobile here -- */

/* Tablets (portrait) ----------- */
@media (min-width : 570px) and (max-width : 768px) {
	
}

/* Tablets landscape, and desktop */
@media (min-width : 769px) {

}</code></pre>

<pre><code>&lt;!--[if (lt IE 9)&(!IEMobile 7)]&gt;
&lt;link href="css/desktop.css" rel="stylesheet" /&gt;
&lt;![endif]--&gt;</code></pre>

<h3>Responsive design</h3>

<p>Whilst the new MiniApps design is quite minimal, using a single column design centered on readability and clear presentation of content - there are still some interesting pieces of responsiveness worth noting (other than the typical resizing of content to fit the browser window).</p>

<h4>Content first, navigation second</h4>

<p>Despite MiniApps already using a mobile first approach for <abbr>CSS</abbr>, more capable small&ndash;screen web browsers can benefit from a further layer of progressive enhancement, with the adoption of a <a href="http://adactio.com/journal/4778/">content first, navigation second</a> design pattern. Using the <a href="http://dev.w3.org/csswg/css3-flexbox/">CSS3 Flexbox module</a>, visitors on capable mobile web browsers will see the page header and main content first, followed by the navigation further down the page, but before the footer.</p> 

<p>Here is a basic template for the site's structural <abbr>HTML</abbr> markup:</p>

<pre><code>&lt;body&gt;
        &lt;nav role="navigation"&gt; &hellip; &lt;/nav&gt;
        &lt;header role="banner"&gt;  &hellip; &lt;/header&gt;
        &lt;section role="main"&gt;  &hellip; &lt;/section&gt;
        &lt;aside role="complementary"&gt;  &hellip; &lt;/aside&gt;
        &lt;footer role="contentinfo"&gt; &hellip; &lt;/footer&gt;
&lt;/body&gt;</code></pre>

<p>Nested inside an appropriate <abbr>CSS</abbr> Media Query, small&ndash;screen browsers are then be served a different ordering of page content, using the <code>box-ordinal-group</code> property.</p>

<pre><code>/* Smartphones (portrait and landscape) ----------- */
@media (max-width : 569px) {

body {
        display: -webkit-box;
        display: -moz-box;
        display: box;
        -webkit-box-orient: vertical;
        -moz-box-orient: vertical;
        box-orient: vertical;
}
	
nav[role=navigation] {
        -webkit-box-ordinal-group: 4;
        -moz-box-ordinal-group: 4;
        box-ordinal-group: 4;
}

header[role=banner] {
        -webkit-box-ordinal-group: 1;
        -moz-box-ordinal-group: 1;
        box-ordinal-group: 1;
}

section[role=main] {
        -webkit-box-ordinal-group: 2;
        -moz-box-ordinal-group: 2;
        box-ordinal-group: 2;
}
	
aside[role=complementary] {
        -webkit-box-ordinal-group: 3;
        -moz-box-ordinal-group: 3;
        box-ordinal-group: 3;
}
	
footer[role=contentinfo] {
        -webkit-box-ordinal-group: 5;
        -moz-box-ordinal-group: 5;
        box-ordinal-group: 5;
}

}</code></pre>


<p>This gets the user straight to the content they want to see, making much better use of valuable screen real&ndash;estate. Each page also features skip links, allowing for quick access to navigation and main content irrespective of the content order.</p>

<p>Note: for the subset of mobile browsers that support <abbr>CSS</abbr> Media Queries but do not yet support Flexbox (e.g. Opera Mobile/Mini), featured detection comes to the rescue courtesy of <a href="http://modernizr.com">Modernizr</a>. A few alternate CSS styling rules are all that is needed for the navigation and footer sections. Modernizr also provides the site's <abbr>HTML5</abbr> shim that enables Internet Explorer to correctly style new sectioning elements.</p>

<h5>QRCodes</h5>

<p>Since this site often features web applications optimized for small&ndash;screen devices - desktop and tablet visitors are now served <a href="http://en.wikipedia.org/wiki/QR_code">QRCodes</a>, linking directly to mobile&ndash;specific content. These scannable barcodes act as super&ndash;fast links for any desktop visitor wishing to view content on a mobile device. Just looking at the stats from the last few weeks of use, people really do seem to be using them (110 scans between August 26 2011 - 22 September 2011). So they are now here to stay - no need to type in tricky URL's on small screens with even smaller keys.</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/site-redesign-a-mobile-first-approach/</guid>
<category>General</category>
</item>
<item>
<title>Building a PlayBook WebWorks app</title>
<link>http://miniapps.co.uk/blog/post/building-a-playbook-webworks-app/</link>
<pubDate>Mon, 03 Oct 2011 16:37:35 +0100</pubDate>
<description><![CDATA[<p>MiniApps was recently hired to develop the front&ndash;end <abbr>HTML</abbr>, <abbr>CSS</abbr> and JavaScript for a BlackBerry PlayBook application, packaged using RIM's <a href="http://us.blackberry.com/developers/tablet/webworks.jsp">WebWorks SDK</a>. The main purpose of the app was to assist the user in consuming a large volume of digital content (in the form of text, images and video) via a streamlined, touch&ndash;friendly interface. Despite a reasonably small development window, the PlayBook browser and development tools proved to be very capable in getting the job done.</p>

<p>What follows is a run down of the key <abbr>HTML5</abbr> features used in the application, and how well they performed on the device. Please note the code shown in this article is simplified in places for the sake of clarity, and is by no means complete.</p>

<h3>Local database support</h3>

<p>While an internet connection would be required to view online images and stream video via YouTube, one of the main technical requirements was that the app should still function and be navigable when offline. Incremental data returned via a remote server should be permanently stored on the device and always accessible. The maximum payload of data this app required was around 15 to 20<abbr>MB<abbr>, so the natural development choice was to use an <a href="http://www.w3.org/TR/webdatabase/"><abbr>HTML5</abbr> Web<abbr>SQL</abbr> Database</a>, since the Playbook browser does not yet support <a href="http://www.w3.org/TR/IndexedDB/">IndexedDB</a>, and the 5<abbr>MB<abbr> limit for <a href="http://dev.w3.org/html5/webstorage/">localStorage</a> was too small for the size of data required.</p> 

<p>Implementation was quite straight forward, with the application creating a simple Web<abbr>SQL</abbr> database on first launch, together with a single table called 'appdata' to act as a main store.</p> 

<pre><code>var storage = {},
    myData = null,
    dbName = 'mydatabase',
    dbVersion = '1.0',
    dbDescription = 'app data store',
    dbSize = 20 * 1024 * 1024;

function handleDbError (e) {
	
	console.log(e.message);
	console.log(e.code);
}

function initDatabase () {
	
	try {
		var data = '';
						
		storage.db = openDatabase(dbName, dbVersion, dbDescription, dbSize);
		storage.db.transaction(function (tx) {
					
  			tx.executeSql("CREATE TABLE IF NOT EXISTS appdata (id unique, text)");
  						
		}, handleDbError);
  					
  		storage.db.transaction(function (tx) {
  					
  			tx.executeSql("INSERT OR IGNORE INTO appdata (id, text) VALUES(?,?)", [dbName, data]);
  					
  		}, handleDbError);
  									
    	} catch(e) {
    		handleDbError(e);
	}
}

initDatabase();</code></pre>

<p>The application then makes a remote server call, and the JSON string returned as a response is then parsed and used immediately. At the same time, the data is saved asynchronously to the local database (in a single table row entry).</p>

<pre><code>function getData () {
			
	var myRequest = new XMLHttpRequest();

	myRequest.onreadystatechange = function () {	

		if (myRequest.readyState === 4 && myRequest.status === 200) {
			myData = JSON.parse(myRequest.responseText);
			updateDatabase();
			startApp();			
		}
	};

	myRequest.open('GET', 'http://', true);
	myRequest.send();
}

function updateDatabase () {
	
	try {	
		var data = JSON.stringify(myData);
						
		storage.db = openDatabase(dbName, dbVersion, dbDescription, dbSize);		
  		storage.db.transaction(function (tx) {
  					
  			tx.executeSql("UPDATE appdata SET text=? WHERE id=?", [data, dbName]);
  					
  		}, handleDbError);
  									
    	} catch(e) {    			
    		handleDbError(e);
	}
}</code></pre>

<p>If the app is later launched while offline, local data is then read back from the database and parsed back to an object, so the app only ever requires a single database read operation.</p>

<pre><code>function throwReadError (e) {
	
	console.log(e.message);
	console.log(e.code);
			
	if(!myData) {
		showAlert("This app requires an internet connection for first launch");
	}
}
		
function readFromDatabase () {
				
	storage.db = openDatabase(dbName, dbVersion, dbDescription, dbSize);
	storage.db.transaction(function (tx) {
  				
		tx.executeSql('SELECT * FROM appdata', [], function (tx, results) {
  				
			myData = JSON.parse(results.rows.item(0).text);
			startApp();
		});

	}, throwReadError);		
}</code></pre>

<p>The PlayBook coped with this size of data store very well. We never hit any bugs or performance issues. Updating the client data on subsequent app launches was also pretty trivial due to the very basic data store model. The PlayBook does not appear to ask the user for storage permission at any size of data we tested, although 50MB is likely the limit if other browsers are anything to go by.</p>

<h3>Offline detection</h3>

<p>For offline detection the app initially used <code>navigator.Online</code>, which at first appears to be supported by the PlayBook Browser.</p> 

<pre><code>var isOnline = window.navigator.onLine;

initDatabase();
				
if (isOnline) {
	getData();
				
} else {
	readFromDatabase();
}</code></pre>

<p>However, once the first WebWorks build was made it became clear something was not right, since <code>navigator.Online</code> was always returning <code>true</code> on launch. This turns out to be an <a href="http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/Bug-report-navigator-onLine-incorrect-status/m-p/1214513/highlight/true#M15043">existing bug</a>, but one that can be easily fixed using a WebWorks <abbr>API</abbr> call for offline detection:</p>

<pre><code>var isOnline = 'blackberry' in window ? blackberry.system.hasDataCoverage() : window.navigator.onLine;</code></pre>

<p>Notice here we use a simple feature detect using the <code>blackberry</code> window object, so we can carry on using <code>navigator.Online</code> in the browser (for development purposes).</p>

<h3>CSS animation</h3>

<p>While the PlayBook has very good support for <abbr>CSS</abbr> <a href="http://www.w3.org/TR/css3-2d-transforms/">2D</a> and <a href="http://www.w3.org/TR/css3-3d-transforms/">3D</a> Transforms and <a href="http://www.w3.org/TR/css3-animations/">animations</a>, it seems to struggle providing hardware acceleration. While RIM claims 3d transforms are hardware accelerated on the PlayBook, in real&ndash;world development we found that only the simplest examples managed anywhere near the smooth performance you come to expect on the iPad.</p>

<p>When building an app with a sizable <abbr>DOM</abbr>, the PlayBook seems to struggle when it comes to animating content. For example, if you display an element that has a <abbr>CSS</abbr> animation associated with it, the PlayBook seems to choke if it needs to render the element and then immediately animate it. Searching on the WebWorks support forums, there are many other developers experiencing <a href="http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/State-of-hardware-accelleration-in-browser/m-p/1050143/highlight/true#M12534">similar issues</a>. More odd quirks also exist, like hardware acceleration failing if the element uses CSS gradients.</p>

<p>For this reason, performing full&ndash;screen animations and transitions we're simply too much for the Playbook to pull off reliably. Only after lots of testing, <code>setTimeout</code> wrangling, tweaking and refining, we're we able to achieve some decent results.</p> 

<p>Hopefully <abbr>RIM</abbr> can provide a future update that fixes current hardware acceleration issues, but as it stands this is currently the Playbook's only major weak point for WebWorks development.</p>

<h3>Touch events</h3>

<p>The app featured multiple sections where scrollable, dynamic touch&ndash;based carousels were needed. For this task <a href="http://cubiq.org/iscroll-4">iScroll4</a> came to the rescue, and proved to be very reliable on the PlayBook browser. Even zoom-able sections that needed multi&ndash;touch proved to be no problem for the device.</p>

<p>The only notable exception is that the PlayBook seems to support multi-touch in a slightly different way to how it works on iOS. For example, while you can perform a two&ndash;touch gesture on a single element on the PlayBook, you do not seem to be able to drag around two separate elements independently of each other. The Playbook appears to be limited in the number of simultaneous, independent touch&ndash;points it can support.</p>

<h3>Native hooks</h3>

<p><abbr>API</abbr> wise, the app used 95% browser&ndash;based <abbr>API</abbr>'s. The remaining areas where WebWorks had to step in were for small things, like opening external links in the PlayBook browser and providing native alert boxes.</p>

<pre><code>function showAlert (message) {
	try {
		blackberry.ui.dialog.standardAskAsync(message, blackberry.ui.dialog.D_OK, {
			title : "Alert", 
			size: blackberry.ui.dialog.SIZE_MEDIUM, 
			position : blackberry.ui.dialog.CENTER
		});
	} catch (e) {
		alert(message);
		console.log(e);
	}
}

function launchBrowser (url) {
	var args = new blackberry.invoke.BrowserArguments(url);
	blackberry.invoke.invoke(blackberry.invoke.APP_BROWSER, args);
}</code></pre>

<h3>Remote debugging</h3>

<p>This is the area really where the Playbook shines in the eyes of a web developer, as you can quickly and very easily <a href="http://devblog.blackberry.com/2011/06/debugging-blackberry-web-apps/">remote debug</a> on an actual device, over your local network. This saved many hours development time and bug fixing, especially when testing device related JavaScript events, such as orientation changes.</p>

<p>Hopefully one day we will have this kind of support on the other major mobile web browsers, and not need rely on third party solutions. RIM are really one step ahead of the competition here.</p>

<h3>Conclusion</h3>

<p>For web developers, building native applications using the WebWorks SDK is overall a very good experience. There is still room for improvement in key areas such as hardware acceleration performance, but otherwise the Playbook browser is a close second to <abbr>iOS</abbr> Safari in terms of <a href="http://www.sencha.com/blog/blackberry-playbook-the-html5-developer-scorecard/">browser features and support</a>.</p>

<p>If only it was as easy for RIM to instill the same level of enthusiasm and confidence in tablet&ndash;buying consumers!</p>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/building-a-playbook-webworks-app/</guid>
<category>WebWorks</category>
</item>
<item>
<title>Make sure to use correct meta viewport syntax</title>
<link>http://miniapps.co.uk/blog/post/make-sure-to-use-correct-meta-viewport-syntax/</link>
<pubDate>Wed, 23 Nov 2011 09:46:21 +0000</pubDate>
<description><![CDATA[<p>When browsing the web it's not uncommon to come across two slight variations on the syntax for declaring <em>meta viewport</em> <code>content</code> values. It's a bit unclear how the two variations originated, but it should be noted that only one is correct, and using an incorrect syntax can actually create problems on certain web browsers.</p>

<p><strong>This is the correct syntax:</strong></p>

<pre><code>&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /&gt;</pre></code>

<p><strong>This is the incorrect syntax:</strong></p>

<pre><code>&lt;meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;" /&gt;</code></pre>

<p>Notice the correct syntax uses <em>comma</em> separated values. The incorrect way is to use a <em>semi-colon</em> separator. There is also no real need for the separator on the last value, <code>user-scalable</code>.</p>

<p>So, why does all of this really matter? &ldquo;It doesn't seem to make a difference on my iPad?&rdquo; Well, maybe not &mdash; but it <em>can</em> and <em><strong>does</strong></em> make a difference on other devices. The recent <a href="http://dev.w3.org/csswg/css-device-adapt/">CSS Device Adaptation</a> specification defines it, so real world implementations are now built toward the comma syntax style.</p>

<p>A real world example is the BlackBerry Playbook. It has a good web browser, but it's not very forgiving with error handling when parsing the meta viewport. If you use semi-colons instead of comma's, <code>width</code> can in some circumstances not get set to <code>device-width</code>. There is currently a bug in the PlayBook's viewport implementation that means <code>width</code> gets set to an arbitrary value if <code>initial-scale</code> is not also set to <code>1.0</code>. If an error is thrown due to incorrect viewport syntax, <code>initial-scale</code> can be ignored and the whole page will appear enlarged, with over-sized text and blurry images. Not really what you intended, huh?</p>

<p>Safari and Chrome are currently the only web browsers that display a series of errors/warnings for an incorrect meta viewport declaration:</p>

<code><pre>Viewport argument value "device-width;" for key "width" not recognized. Content ignored.
Viewport argument value "1.0;" for key "initial-scale" was truncated to its numeric prefix.
Viewport argument value "1.0;" for key "maximum-scale" was truncated to its numeric prefix.
Viewport argument value "0;" for key "user-scalable" was truncated to its numeric prefix.</code></pre>

<p>It would be nice if more browsers did this. Maybe once <a href="http://dev.opera.com/articles/view/an-introduction-to-meta-viewport-and-viewport/">@viewport</a> becomes more widely adopted, we could then begin to phase out the messy meta viewport altogether?</p>

<p>So, the next time you are using meta viewport in a site &mdash; make sure you define it properly. Don't just cut and paste it from a old/bad example you found somewhere!</p>

<p>Please note, you should not necessarily be including all the different properties seen above in your declaration. This article is simply concentrating on how to define things correctly.</p>

<p>Update - for anyone wishing to use <code>width=device-width</code> without also setting <code>initial-scale=1.0</code>, the PlayBook can be tamed by inserting the legacy BlackBerry <code>HandheldFriendly</code> meta property before the viewport declaration:</p>

<pre><code>&lt;meta name="HandheldFriendly" content="True" /&gt;
&lt;meta name="viewport" content="width=device-width" /&gt;</code></pre>]]></description>
<guid isPermaLink="true" >http://miniapps.co.uk/blog/post/make-sure-to-use-correct-meta-viewport-syntax/</guid>
<category>HTML</category>
</item>
</channel>
</rss>
