<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>John Dyer's Code</title>
	
	<link>http://johndyer.name</link>
	<description>Curly Braces and Angled Brackets</description>
	<lastBuildDate>Thu, 03 May 2012 21:06:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/johndyer" /><feedburner:info uri="johndyer" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><media:keywords>c,ASP,NET,Flash,Papervision,JavaScript,HTML,XHTML,3D,NET,AS3,ActionScript</media:keywords><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology</media:category><itunes:owner><itunes:email>johndyer@gmail.com</itunes:email></itunes:owner><itunes:explicit>no</itunes:explicit><itunes:keywords>c,ASP,NET,Flash,Papervision,JavaScript,HTML,XHTML,3D,NET,AS3,ActionScript</itunes:keywords><itunes:subtitle>Technology and web development in ASP.NET, Flash, and JavaScript</itunes:subtitle><itunes:category text="Technology" /><item>
		<title>Cross-Browser Native Get/Set Properties in JavaScript</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/Fv0UkJOoJw8/</link>
		<comments>http://johndyer.name/native-browser-get-set-properties-in-javascript/#comments</comments>
		<pubDate>Wed, 02 May 2012 20:54:50 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://johndyer.name/?p=252</guid>
		<description><![CDATA[JavaScript Doesn&#8217;t Support Properties When I first created MediaElement.js a few years ago, I wanted to make a JavaScript object that fully mimicked the HTML5 Media API, but under the hood it might have a true &#60;video&#62; tag or a Flash object doing the rendering. The problem I quickly found was that the &#60;video&#62; tag has several properties [...]]]></description>
			<content:encoded><![CDATA[<h3>JavaScript Doesn&#8217;t Support Properties</h3>
<p>When I first created <a href="http://mediaelementjs.com/">MediaElement.js</a> a few years ago, I wanted to make a JavaScript object that fully mimicked the HTML5 Media API, but under the hood it might have a true <code>&lt;video&gt;</code> tag or a Flash object doing the rendering.</p>
<p>The problem I quickly found was that the <code>&lt;video&gt;</code> tag has several properties like <code>.src</code> and <code>.volume</code> that can&#8217;t be replicated since JavaScript doesn&#8217;t have true get/set capability that works in all browsers (by &#8220;all browsers&#8221; I mean &#8220;IE6 and up&#8221;). So I had to create methods like <code>.setSrc()</code> and <code>.setVolume()</code> (or use jQuery&#8217;s <code>.volume()</code> syntax) to make it work correctly across browsers, but that resulted in a API that didn&#8217;t match the HTML5 spec.</p>
<h3>Ah, But JavaScript <em>Does</em> Support Properties</h3>
<p>A long time ago, in Firefox&#8217;s distant past there was a proprietary way to create properties, using the <code><a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/DefineGetter">__defineGetter__</a></code> and <code>__defineSetter__</code>methods. Here&#8217;s what it looks like:</p>
<pre class="brush: javascript; gutter: true">var myObject = {};
myObject.seconds = 22;
myObject.__defineGetter__(&#039;milliseconds&#039;, function() { return this.seconds / 1000;} );
myObject.__defineSetter__(&#039;milliseconds&#039;, function(value) { this.seconds = value * 1000;});

myObject.milliseconds = 1750;
console.log(myObject.seconds); // outputs 1.75;</pre>
<p>It&#8217;s great because it allows you to easily define properties that can do additional calculation work (e.g., from milliseconds to seconds), but it doesn&#8217;t work in all other browsers. The method that <em>is</em> more universally available is <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a> which offers a slightly cleaner syntax:</p>
<pre class="brush: javascript; gutter: true">var myObject = {};
myObject.seconds = 22;

Object.defineProperty(obj, &#039;milliseconds&#039;, {
     get: function() { return this.seconds / 1000;},
     set: function(value) { this.seconds = value * 1000;}
});

myObject.milliseconds = 1750;
console.log(myObject.seconds); // outputs 1.75;</pre>
<p>Looks super useful right? So why doesn&#8217;t anyone use it?</p>
<p>The problem is that IE6 and IE7 don&#8217;t support it, and while IE8 does support the <code>Object.defineProperty</code> method, it sadly only works on DOM objects that are attached to the tree.</p>
<p>So, if you really, really needed an object that supported properties, you can create a DOM object, attach it to the document, and then use <code>Object.defineProperty</code> to give it some properties. That&#8217;s a lot of trouble just to support IE8, and you still don&#8217;t get IE6 or IE7 support, so I don&#8217;t know of any libraries that currently use the approach.</p>
<h3>Hacking IE6 and IE7</h3>
<p>I recently came across a technique that I haven&#8217;t seen demonstrated before from <a href="http://thewikies.com/">Jonathan Neal</a> using the <a href="http://msdn.microsoft.com/en-us/library/ie/ms536956(v=vs.85).aspx"><code>onpropertychanged</code></a> event. IE will fire this event when any property, native or added by a developer, is changed. However, like IE8 this technique only works on a real DOM object, not a plain old <code>{}</code>.</p>
<p>Based on Jonathan&#8217;s work, here is a function that will add a property and work in IE6 and up.</p>
<pre class="brush: javascript; gutter: true">// Super amazing, cross browser property function, based on http://thewikies.com/
function addProperty(obj, name, onGet, onSet) {

	// wrapper functions
	var
		oldValue = obj[name],
		getFn = function () {
			return onGet.apply(obj, [oldValue]);
		},
		setFn = function (newValue) {
			return oldValue = onSet.apply(obj, [newValue]);
		};

	// Modern browsers, IE9+, and IE8 (must be a DOM object),
	if (Object.defineProperty) {

		Object.defineProperty(obj, name, {
			get: getFn,
			set: setFn
		});

	// Older Mozilla
	} else if (obj.__defineGetter__) {

		obj.__defineGetter__(name, getFn);
		obj.__defineSetter__(name, setFn);

	// IE6-7
	// must be a real DOM object (to have attachEvent) and must be attached to document (for onpropertychange to fire)
	} else {

		var onPropertyChange = function (e) {

			if (event.propertyName == name) {
				// temporarily remove the event so it doesn&#039;t fire again and create a loop
				obj.detachEvent(&quot;onpropertychange&quot;, onPropertyChange);

				// get the changed value, run it through the set function
				var newValue = setFn(obj[name]);

				// restore the get function
				obj[name] = getFn;
				obj[name].toString = getFn;

				// restore the event
				obj.attachEvent(&quot;onpropertychange&quot;, onPropertyChange);
			}
		};	

		obj[name] = getFn;
		obj[name].toString = getFn;

		obj.attachEvent(&quot;onpropertychange&quot;, onPropertyChange);

	}
}

// must be a DOM object (even if it&#039;s not a real tag) attached to document
var myObject = document.createElement(&#039;fake&#039;);
document.body.appendChild(myObject);

// create property
myObject.firstName = &#039;John&#039;;
myObject.lastName = &#039;Dyer&#039;;
addProperty(myObject, &#039;fullname&#039;,
	function() {
		return this.firstName + &#039; &#039; + this.lastName;
	},
	function(value) {
		var parts = value.split(&#039; &#039;);
		this.firstName = parts[0];
		this.lastName = (parts.length &gt; 1) ? parts[1] : &#039;&#039;;
	});

console.log(myObject.fullname); // returns &#039;John Dyer&#039;</pre>
<p>Pretty aweseome.</p>
<h3>Real World Application</h3>
<p>Mozilla&#8217;s April <a href="https://developer.mozilla.org/en-US/demos/devderby">Dev Derby</a> was on using the &lt;audio&gt; tag, so I thought it&#8217;d be a fun chance to try this out and make a native looking HTML5 API that could wrap things like a Flash Ogg player or the amazing <a href="http://jsmad.org/">JsMad</a> library which can play MP3s using pure JavaScript (great for Firefox which can&#8217;t play MP3s natively).</p>
<p>The result is a fun little audio library called <a href="https://developer.mozilla.org/en-US/demos/detail/shimichanga">Shimichanga</a> that has functional properties like <code>.src</code>. What&#8217;s interesting about the library is that when you set the <code>.src</code> property, the set method loads an appropriate renderer (HTML5, Flash, or JavaScript) depending on the browser&#8217;s capability and then sends the value to renderer to use, all seemless to the developer and end-user. <em>Note: Mozilla didn&#8217;t allow the flash shim part, so to see a full working demo go to: <a href="http://shimichanga.com">shimichanga.com</a></em>.</p>
<p>Hopefully, I can back port this into <a href="http://mediaelementjs.com/">MediaElement.js</a> and make the entire library more dynamic and usable. For now, go check out my hideously styled demo on Mozilla&#8217;s site (<a href="https://developer.mozilla.org/en-US/demos/detail/shimichanga">Shimichanga</a>) and give me some likes!</p>
<p><a class="post-button demo" href="https://developer.mozilla.org/en-US/demos/detail/shimichanga">Dev Derby</a> <a class="post-button demo" href="http://shimichanga.com">shimichanga.com</a></p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/Fv0UkJOoJw8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/native-browser-get-set-properties-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://johndyer.name/native-browser-get-set-properties-in-javascript/</feedburner:origLink></item>
		<item>
		<title>HTML5 Video Wrapper for YouTube and Vimeo API – MediaElement.js</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/J2C8lGur_G0/</link>
		<comments>http://johndyer.name/html5-video-wrapper-for-youtube-and-vimeo-api-mediaelement-js/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 20:17:40 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://johndyer.name/?p=234</guid>
		<description><![CDATA[YouTube and Vimeo APIs YouTube and Vimeo have nice APIs to allow JavaScript developers to control the playback of embedded content (oh, and YouTube has a new design). They&#8217;ve also updated the APIs to use the newer &#60;iframe&#62; embed style instead requiring &#60;object&#62;&#60;embed&#62; flash tags. But as powerful as those APIs are, they are not [...]]]></description>
			<content:encoded><![CDATA[<h3><a href="http://mediaelementjs.com/examples/?name=youtube"><img class="aligncenter size-full wp-image-238" title="youtube-mediaelementjs" src="http://johndyer.name/wp-content/uploads/2011/11/youtube-mediaelementjs.jpg" alt="" width="750" height="194" /></a></h3>
<h3>YouTube and Vimeo APIs</h3>
<p><a href="http://code.google.com/apis/youtube/iframe_api_reference.html">YouTube</a> and <a href="http://vimeo.com/api/docs/player-js">Vimeo</a> have nice APIs to allow JavaScript developers to control the playback of embedded content (oh, and <a href="http://www.theverge.com/2011/11/21/2577332/how-to-enable-the-new-youtube-design">YouTube has a new design</a>). They&#8217;ve also updated the APIs to use the newer <code>&lt;iframe&gt;</code> embed style instead requiring <code>&lt;object&gt;&lt;embed&gt;</code> flash tags. But as powerful as those APIs are, they are not consistent with each other and neither one conforms to HTML5 <code>&lt;video&gt;</code> <a href="http://www.w3.org/TR/html5/video.html">properties or events</a> so you can&#8217;t leverage your existing skills or code.</p>
<h3>MediaElement.js HTML5 Wrapper</h3>
<p>To make the YouTube and Vimeo APIs easier to use, I wrapped the MediaElement.js shim structure around their proprietary APIs to make them feel like HTML5. So for a YouTube video, you can use this <code>&lt;video&gt; markup</code></p>
<pre class="brush: html; gutter: true">&lt;video id="youtube1" width="640" height="360"&gt;
	&lt;source src="http://www.youtube.com/watch?v=nOEw9iiopwI" type="video/youtube" &gt;
&lt;/video&gt;</pre>
<p>Then to build a full-fledged player that is CSS skinnable on top of YouTube Chromeless , you can simply call the MediaElementPlayer like this:</p>
<pre class="brush: javascript; gutter: true">jQuery(document).ready(function($) {
	$('#youtube1').mediaelementplayer();
});</pre>
<p><a class="post-button demo" href="http://www.mediaelementjs.com/examples/?name=youtube">Demo</a></p>
<p>Or you can skip MediaElementPlayer&#8217;s controls and build your own player using just the MediaElement wrapper which does not require jQuery (MediaElement is the wrapper which shims HTML5 support into old browsers, MediaElement<em>Player</em> is the full-fledged jQuery-based control bar built on top of MediaElement).</p>
<pre class="brush: javascript; gutter: true">new MediaElement('youtube#', {
	success: function(media, domNode) {
		// add HTML5 events to the YouTube API media object
		media.addEventListener('play', function() {
			console.log('yeah, it is playing!');
		}, false);

		media.addEventListener('timeupdate', function() {
// access HTML5-like properties
			console.log('current: ' + media.currentTime);
		}, false);

		// add click events to control player
		myMuteButton.addEventListener('click', function() {
			// HTML5 has a "muted" setter, but we have to use a function here
			media.setMuted(true);
		}, false);
	}
});</pre>
<p>Once the success event fires, the <code>media</code> object is a JavaScript wrapper that mimics the HTML5 Media API, but under the hood is really a wrapper around YouTube&#8217;s API. Nice right?</p>
<h3>Gotchas</h3>
<h3><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">There are a few things you should look out for if you want to try it:</span></h3>
<ul>
<li>This code is now in the official 2.4.0 release of MediaElement.js, but it should be considered experimental. I&#8217;d like to pull it out of the core and make it a plugin, but this will require some re-architecting.</li>
<li>The Vimeo API wrapper is not finished yet. It will simply display the default Vimeo controls. (Also, unlike YouTube&#8217;s chromeless option, only Vimeo Pro users can totally remove controls)</li>
<li>Some browsers (Chrome, IE) don&#8217;t allow HTML to be placed over an <code>&lt;iframe&gt;</code> with Flash inside which makes MediaElementPlayer&#8217;s controls not work, so I&#8217;m using the pure Flash version of YouTube for desktop browsers</li>
<li>Fullscreen: JavaScript can&#8217;t initiate Flash&#8217;s true fullscreen, and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=90268">Firefox still has terrible Flash support</a> (if you try to adjust the size of a Flash movie&#8217;s surrounding DOM nodes, Firefox reloads it!)</li>
</ul>
<p><a class="post-button demo" href="http://mediaelementjs.com/examples/?name=youtube">Demo</a> <a class="post-button demo" href="http://mediaelementjs.com/">Download</a></p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/J2C8lGur_G0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/html5-video-wrapper-for-youtube-and-vimeo-api-mediaelement-js/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://johndyer.name/html5-video-wrapper-for-youtube-and-vimeo-api-mediaelement-js/</feedburner:origLink></item>
		<item>
		<title>Pinbox.js – Photos Then and Now (jQuery plugin)</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/zfxlEJ7h-EU/</link>
		<comments>http://johndyer.name/pinbox-js-photos-then-and-now-jquery-plugin/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 15:02:02 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://johndyer.name/?p=215</guid>
		<description><![CDATA[With the help of a colleague, I&#8217;m gathering images of an area of Dallas, TX just east of downtown around the campus of Dallas Theological Seminary where I work. I wanted to make the photos interactive like the animated GIF you see here. Live Demo Download Code Code Explanation To make this work, I start with [...]]]></description>
			<content:encoded><![CDATA[<p>With the help of a colleague, I&#8217;m gathering images of an area of Dallas, TX just east of downtown around the campus of <a href="http://www.dts.edu/">Dallas Theological Seminary</a> where I work. I wanted to make the photos interactive like the animated GIF you see here.</p>
<p><a href="http://johndyer.name/lab/pinbox/"><img class="aligncenter size-full wp-image-224" title="pinboxdemo" src="http://johndyer.name/wp-content/uploads/2011/11/pinboxdemo.gif" alt="" width="680" height="252" /></a></p>
<p><a class="post-button demo" href="http://johndyer.name/lab/pinbox/">Live Demo</a> <a class="post-button demo" href="http://github.com/johndyer/pinbox.js/">Download Code</a></p>
<h2>Code Explanation</h2>
<p><span id="more-215"></span></p>
<p>To make this work, I start with a simple <code>&lt;img /&gt;</code> tag and then add some HTML5 <code>data-*</code> attributes that specify the size and position of the inner image:</p>
<pre class="brush: html; gutter: true">&lt;img src="images/convent-pano.jpg"
	width="940"
	height="365"
	data-small-src="images/convent-pano-inner.jpg"
	data-small-width="507"
	data-small-height="264"
	data-small-left="163"
	data-small-top="11"
	class="pinbox"
	alt="View from Convent Street"
/&gt;</pre>
<p>This ensures the images will still function properly even if the JavaScript doesn&#8217;t fire properly. The next step is to include the Pinbox.js library and then use jQuery to instantiate it when the document has loaded. The script takes care of the rest.</p>
<pre class="brush: html; gutter: true">&lt;script src="src/jquery.js"&gt;&lt;/script&gt;
&lt;script src="src/jquery.pinbox.js"&gt;&lt;/script&gt;
&lt;link rel="stylesheet" href="src/jquery.pinbox.css" /&gt;
&lt;script&gt;
jQuery(document).ready(function($) {
	$('.pinbox').pinbox();
});
&lt;/script&gt;</pre>
<p><a class="post-button demo" href="http://johndyer.name/lab/pinbox/">Live Demo</a> <a class="post-button demo" href="http://github.com/johndyer/pinbox.js/">Download Code</a></p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/zfxlEJ7h-EU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/pinbox-js-photos-then-and-now-jquery-plugin/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://johndyer.name/pinbox-js-photos-then-and-now-jquery-plugin/</feedburner:origLink></item>
		<item>
		<title>Native Fullscreen JavaScript API (plus jQuery plugin)</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/wxEXTeRBsuo/</link>
		<comments>http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 13:17:57 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://johndyer.name/?p=181</guid>
		<description><![CDATA[HTML5 &#60;video&#62; is great, but when it was first released, one of the big complaints was that it couldn&#8217;t do true FullScreen like Flash. Thankfully, this is changing and native FullScreen support is coming to most browsers in the next few months (no word from the Internet Explorer team Update on IE below #5)) The API [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://johndyer.name/wp-content/uploads/2011/10/js-fullscren.png"><img class="size-medium wp-image-213 alignright" title="JS Fullscreen" src="http://johndyer.name/wp-content/uploads/2011/10/js-fullscren-300x297.png" alt="" width="300" height="297" /></a></p>
<p>HTML5 <code>&lt;video&gt;</code> is great, but when it was first released, one of the big complaints was that it couldn&#8217;t do true FullScreen like Flash. Thankfully, this is changing and native FullScreen support is coming to most browsers in the next few months (<del>no word from the Internet Explorer team</del> Update on IE below #5))</p>
<p>The API is still heavily in flux especially since the W3C joined in this week. I spent some time working through the differences to implement FullScreen in <a href="http://mediaelementjs.com/">MediaElement.js HTML5 video player</a>, and it&#8217;s working great in Safari 5.1+, <del><a href="http://tools.google.com/dlpage/chromesxs">Chrome Canary</a></del> Chrome 15+, or <a href="http://nightly.mozilla.org/">Firefox Nightly</a> (go to about:config and set full-screen-api.enabled= true) and scheduled for <a href="https://wiki.mozilla.org/Platform/Features/Full_Screen_APIs">Firefox 10</a>. Below I&#8217;m going to try to explain how things evolved, where we are today, and then some code that you can play with.</p>
<p><a class="post-button demo" href="http://johndyer.name/lab/fullscreenapi/">Simple Demo</a> <a class="post-button demo" href="http://mediaelementjs.com/">Video Demo<span id="more-181"></span></a></p>
<h2>A Brief History of the FullScreen API</h2>
<ol>
<li>The first native FullScreen implementation appeared in Safari 5.0 (and iOS) added a a <code>webkit<strong>Enter</strong>FullScreen()</code> function that only worked on &lt;video&gt; tags using Safari&#8217;s video controls (see <a href="http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html">Apple&#8217;s HTML5VideoElement</a>).</li>
<li>For Safari 5.1, Apple changed the API to be more inline with <a href="https://wiki.mozilla.org/Gecko:FullScreenAPI">Mozilla&#8217;s FullScreen API proposal</a> (which actually predates Apple&#8217;s implementation). Now, <code>webkit<strong>Request</strong>FullScreen()</code> can be called on <em>any</em> DOM element which makes that portion of an HTML page go fullscreen.</li>
<li>Firefox and Chrome announced that they will add FullScreen API support, and the feature has already arrived in <del><a href="http://tools.google.com/dlpage/chromesxs">Chrome Canary</a></del> Chrome 15+ and <a href="http://nightly.mozilla.org/">Firefox Nightly</a> (scheduled for <a href="https://wiki.mozilla.org/Platform/Features/Full_Screen_APIs">Firefox 10</a>). The Mozilla team has posted some <a href="http://pearce.org.nz/full-screen/">a demo</a>.</li>
<li>On October 15, 2011, the W3C released a <a href="http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html">Fullscreen API proposal</a> (written by a member of the Opera team) which has two main differences from Mozilla&#8217;s proposal:</li>
<ol>
<li>Mozilla/Webkit uses a Capital &#8216;S&#8217; (FullScreen) while W3C does not (Fullscreen)</li>
<li>Mozilla/Webkit uses <code><strong>cancel</strong>FullScreen</code><br />
while W3C uses <code><strong>exit</strong>Fullscreen</code></li>
</ol>
<li><strong>Update (11/15/2011)</strong>: Ted Johnson from <a href="blogs.msdn.com/b/ie/">IEBlog</a> says<del> IE10 will <em>not</em> support the FullScreen API</del> (12/05/2011: I misunderstood the first email from Ted) that the IE10 team has not yet decided whether to implement the FullScreen API. He notes however that, &#8220;Windows 8 Metro style Internet Explorer is always full screen &#8230; and as before, F11 enters full screen mode in desktop versions of IE.&#8221;</li>
</ol>
<h2>Understanding the FullScreen API</h2>
<p>Here are the most important parts of the FullScreen API with notes on how things differ among browsers. In general, I&#8217;m using the Mozilla/Webkit spelling in the examples below, but I&#8217;m also noting the W3C differences where needed.</p>
<h3>1. Detecting FullScreen support</h3>
<p>To detect fullscreen support, you&#8217;ll need to use the typeof command to find out if a given browser has support for the FullScreen API methods. There is also boolean property called <code>fullScreenEnabled</code> that tells you if the user has disabled the feature (strangely WebKit does not have the <code>fullScreenEnabled</code> property making it difficult to detect if it&#8217;s turned off).</p>
<pre class="brush: javascript; gutter: true">// Mozilla's proposed API: in practice, you'll need vendor prefixes (see examples below)
if (typeof document.cancelFullScreen != 'undefined' &amp;&amp; document.fullScreenEnabled === true) {
    /* do fullscreen stuff */
}</pre>
<h3>2. Entering and Exiting FullScreen</h3>
<p>To enter FullScreen mode, you call <code>requestFullScreen</code> (or <code>requestFullscreen</code> for W3C) on the element want to be viewed in FullScreen. To exit you call <code>cancelFullScreen</code> (or <code>exitFullscreen</code> for W3C) on the <code>document</code> object.</p>
<pre class="brush: javascript; gutter: true">// mozilla proposal
element.requestFullScreen();
document.cancelFullScreen(); 

// Webkit (works in Safari and Chrome Canary)
element.webkitRequestFullScreen(); 
document.webkitCancelFullScreen(); 

// Firefox (works in nightly)
element.mozRequestFullScreen();
document.mozCancelFullScreen(); 

// W3C Proposal
element.requestFullscreen();
document.exitFullscreen();</pre>
<p>Mozilla has also proposed an alternate <code>requestFullScreenWithKeys()</code> method which would enable the user to use the keyboard in FullScreen mode. With Flash, Adobe always disabled keyboard support in FullScreen to prevent malicious sites from attempting to steal passwords, but it looks like the browser makers are considering making this an option.</p>
<h3>3. Fullscreen Event and Current Status</h3>
<p>To detect when a FullScreen event happens, there is a <code>fullscreeneventchange</code> that fires on the element going FullScreen and a boolean property (<code>fullScreen</code>) on the document object that reports if it&#8217;s in FullScreen mode or not.</p>
<pre class="brush: javascript; gutter: true">element.addEventListener('fullscreeneventchange', function(e) {
    if (document.fullScreen) {
       /* make it look good for fullscreen */
    } else {
       /* return to the normal state in page */
    }
}, true);</pre>
<p>Mozilla also mentions the possibility of adding a <code>fullscreendenied</code> event in the future. You should also know that Webkit added an &#8216;Is&#8217; to their boolean property and that the W3C proposal strangely does not include this property:</p>
<pre class="brush: javascript; gutter: true">// Mozilla proposal
document.fullScreen;
// Firefox (Nightly)
document.mozFullScreen;
// Webkit (Chrome, Safari)
document.webkitIsFullScreen; // note the 'Is'
// W3C proposal
// None? Why?</pre>
<h3>4. Styling FullScreen</h3>
<p>Both Mozilla and the W3C have proposed new pseudo CSS classes for styling elements in FullScreen mode.</p>
<pre class="brush: css; gutter: true">/* normal state */
.my-container {
    width: 640px;
    height: 360px;
}

/* Mozilla proposal (dash) */
.my-container:full-screen {
    width:100%;
    height:100%;
}

/* W3C proposal (no dash) */
.my-container:fullscreen {
    width:100%;
    height:100%;
}

/* currently working vendor prefixes */
.my-container:-webkit-full-screen, .my-container:-moz-full-screen {
    width:100%;
    height:100%;
}</pre>
<h3>5. Embedding FullScreen</h3>
<p>When you embed content from another site (like a YouTube video) using Flash&#8217;s <code>&lt;object&gt;&lt;embed&gt;</code> tags, you can specificy whether or not to allow FullScreen to work. This feature has also been added to the <code>&lt;iframe&gt;</code> tag using the allowFullScreen attribute.</p>
<pre class="brush: html; gutter: true">&lt;!-- content from another site that is allowed to use the fullscreen command --&gt;
&lt;iframe src="http://anothersite.com/video/123" width="640" height="360" allowFullScreen&gt;&lt;/iframe&gt;</pre>
<h2>Putting it All Together</h2>
<p>To make this work in its current state, you need a wrapper that can help detect the right features. Here&#8217;s what I&#8217;ve put together to work in Safari 5.1, <del><a href="http://tools.google.com/dlpage/chromesxs">Chrome Canary</a></del> Chrome 15+, and <a href="http://nightly.mozilla.org/">Firefox Nightly</a>. I&#8217;ll update it if the W3C notation goes through:</p>
<pre class="brush: javascript; gutter: true">(function() {
	var
		fullScreenApi = {
			supportsFullScreen: false,
			isFullScreen: function() { return false; },
			requestFullScreen: function() {},
			cancelFullScreen: function() {},
			fullScreenEventName: '',
			prefix: ''
		},
		browserPrefixes = 'webkit moz o ms khtml'.split(' ');

	// check for native support
	if (typeof document.cancelFullScreen != 'undefined') {
		fullScreenApi.supportsFullScreen = true;
	} else {
		// check for fullscreen support by vendor prefix
		for (var i = 0, il = browserPrefixes.length; i &lt; il; i++ ) {
			fullScreenApi.prefix = browserPrefixes[i];

			if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined' ) {
				fullScreenApi.supportsFullScreen = true;

				break;
			}
		}
	}

	// update methods to do something useful
	if (fullScreenApi.supportsFullScreen) {
		fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';

		fullScreenApi.isFullScreen = function() {
			switch (this.prefix) {
				case '':
					return document.fullScreen;
				case 'webkit':
					return document.webkitIsFullScreen;
				default:
					return document[this.prefix + 'FullScreen'];
			}
		}
		fullScreenApi.requestFullScreen = function(el) {
			return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
		}
		fullScreenApi.cancelFullScreen = function(el) {
			return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
		}
	}

	// jQuery plugin
	if (typeof jQuery != 'undefined') {
		jQuery.fn.requestFullScreen = function() {

			return this.each(function() {
				if (fullScreenApi.supportsFullScreen) {
					fullScreenApi.requestFullScreen(this);
				}
			});
		};
	}

	// export api
	window.fullScreenApi = fullScreenApi;
})();</pre>
<p>This creates an object called <code>fullScreenApi</code> with a boolean property <code>supportsFullScreen</code> and some methods that allow you to do something more universal. Here&#8217;s an example usage:</p>
<pre class="brush: javascript; gutter: true">if (fullScreenApi.supportsFullScreen) {
	myButton.addEventListener('click', function() {
		fullScreenApi.requestFullScreen(someElement);
	}, true);
}</pre>
<p>You can see it in action below:</p>
<p><a class="post-button demo" href="http://johndyer.name/lab/fullscreenapi/">Simple Demo</a> <a class="post-button demo" href="http://mediaelementjs.com/">Video Demo</a></p>
<h2>Issues and Updates</h2>
<p>Since this post, there are some additional things worth mentioning</p>
<ul>
<li><strong>Security concerns</strong> &#8211; Browser vendors are well aware of the potential security issues with fullscreen. For example, a malicious site could show a full screen Windows or Mac login window and steal a password. That&#8217;s why they are disabling keyboard support by default and only enabling by explicitly asking.</li>
<li><strong>Internet Explorer support</strong> &#8211; <del>I have an email from a IE team member saying they are discussing it, but have not made any decisions. </del>As of now, <del>IE10 will <em>not</em> implement the FullScreen API</del>, the IE team has not yet decided if they will implement the FullScreen API.</li>
<li><strong>FullscreenEnabled vs. IsFullScreen</strong> &#8211; The W3C includes the very helpful <code>fullscreenEnabled</code> flag to let your code know if you can use the API, but strangely the W3C does not include an <code>isFullscreen</code> flag. WebKit on the other hand has <code>webkitIsFullScreen</code>, but does not have a <code>webkitFullScreenEnabled</code> equivalent property. Mozilla helpfully includes both.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/wxEXTeRBsuo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/feed/</wfw:commentRss>
		<slash:comments>53</slash:comments>
		<feedburner:origLink>http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/</feedburner:origLink></item>
		<item>
		<title>Getting Counts for Twitter Links, Facebook Likes/Shares, and Google (+1) PlusOnes in C# or PHP</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/U7O7m9GzEKQ/</link>
		<comments>http://johndyer.name/getting-counts-for-twitter-links-facebook-likesshares-and-google-1-plusones-in-c-or-php/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 21:58:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://e9c7c3e6-a1a4-4a1d-990a-c9cfbab89779</guid>
		<description><![CDATA[I am working on a project where I need to know the number of social shares on Facebook, Twitter, and Google +1 (plusone). Facebook and Twitter make this easy with a simple URL that returns clear JSON data, but Google has not offered an official way to do it yet. However, I found someone who [...]]]></description>
			<content:encoded><![CDATA[<p>I am working on a project where I need to know the number of social shares on Facebook, Twitter, and Google +1 (plusone). Facebook and Twitter make this easy with a simple URL that returns clear JSON data, but Google has not offered an official way to do it yet. However, I <a href="http://www.tomanthony.co.uk/blog/google_plus_one_button_seo_count_api/comment-page-1/">found someone</a> who tracked down how to do it using Google&#8217;s JSON-RPC API, and I&#8217;ve repackaged them together in ASP.NET and PHP for anyone who wants to give it a try.<span id="more-9"></span></p>
<h2>Data URLs</h2>
<p>Here&#8217;s where you can find the data</p>
<table>
<tbody>
<tr>
<th>Facebook</th>
<td>http://graph.facebook.com/?ids=YOURURL</td>
</tr>
<tr>
<th>Twitter</th>
<td>http://urls.api.twitter.com/1/urls/count.json?url=YOURURL</td>
</tr>
<tr>
<th>Google</th>
<td>https://clients6.google.com/rpc [see below for JSON-RPC]</td>
</tr>
</tbody>
</table>
<h2>ASP.NET C#</h2>
<p>Note: Since I&#8217;m using &#8220;dynamic,&#8221; this requires .NET 4.0. Also, I&#8217;m using the JavaScriptSerializer class which is officially depreciated, but will probably not actually be removed. You could also easily use Regex to get these simple values.</p>
<pre class="brush: c-sharp;">int GetTweets(string url) {

	string jsonString = new System.Net.WebClient().DownloadString("http://urls.api.twitter.com/1/urls/count.json?url=" + url);

	var json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(jsonString);
	int count = (int)json["count"];	

	return count;
}

int GetLikes(string url) {

	string jsonString = new System.Net.WebClient().DownloadString("http://graph.facebook.com/?ids=" + url);

	var json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(jsonString);
	int count = json[url]["shares"];

	return count;
}

int GetPlusOnes(string url) {

	string googleApiUrl = "https://clients6.google.com/rpc"; //?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ";

	string postData = @"[{""method"":""pos.plusones.get"",""id"":""p"",""params"":{""nolog"":true,""id"":""" + url + @""",""source"":""widget"",""userId"":""@viewer"",""groupId"":""@self""},""jsonrpc"":""2.0"",""key"":""p"",""apiVersion"":""v1""}]";

	System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(googleApiUrl);
	request.Method = "POST";
	request.ContentType = "application/json-rpc";
	request.ContentLength = postData.Length;

	System.IO.Stream writeStream = request.GetRequestStream();
	UTF8Encoding encoding = new UTF8Encoding();
	byte[] bytes = encoding.GetBytes(postData);
	writeStream.Write(bytes, 0, bytes.Length);
	writeStream.Close();

	System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
	System.IO.Stream responseStream = response.GetResponseStream();
	System.IO.StreamReader readStream = new System.IO.StreamReader(responseStream, Encoding.UTF8);
	string jsonString = readStream.ReadToEnd();

	readStream.Close();
	responseStream.Close();
	response.Close();

	var json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(jsonString);
	int count = Int32.Parse(json[0]["result"]["metadata"]["globalCounts"]["count"].ToString().Replace(".0", ""));

	return count;
}</pre>
<h2>PHP</h2>
<p>Again, thanks to <a href="http://www.tomanthony.co.uk/blog/google_plus_one_button_seo_count_api/comment-page-1/">Tom Anthony</a> for the Google part</p>
<pre class="brush: php;">function get_tweets($url) {

	$json_string = file_get_contents('http://urls.api.twitter.com/1/urls/count.json?url=' . $url);
	$json = json_decode($json_string, true);

	return intval( $json['count'] );
}

function get_likes($url) {

	$json_string = file_get_contents('http://graph.facebook.com/?ids=' . $url);
	$json = json_decode($json_string, true);

	return intval( $json[$url]['shares'] );
}

function get_plusones($url) {

	$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL, "https://clients6.google.com/rpc");
	curl_setopt($curl, CURLOPT_POST, 1);
	curl_setopt($curl, CURLOPT_POSTFIELDS, '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"' . $url . '","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]');
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
	$curl_results = curl_exec ($curl);
	curl_close ($curl);

	$json = json_decode($curl_results, true);

	return intval( $json[0]['result']['metadata']['globalCounts']['count'] );
}</pre>
<p>Hope that helps someone out there!</p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/U7O7m9GzEKQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/getting-counts-for-twitter-links-facebook-likesshares-and-google-1-plusones-in-c-or-php/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://johndyer.name/getting-counts-for-twitter-links-facebook-likesshares-and-google-1-plusones-in-c-or-php/</feedburner:origLink></item>
		<item>
		<title>bib.ly – ASP.NET MVC Url Shortener for Bible References</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/rpqTuF5EgQs/</link>
		<comments>http://johndyer.name/bib-ly-asp-net-mvc-url-shortener-for-bible-references/#comments</comments>
		<pubDate>Sat, 02 Apr 2011 02:26:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Bible Tools]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://4ec77775-bfef-42ab-aad9-5fb075a029d4</guid>
		<description><![CDATA[Last week, I turned a URL shortening website called bib.ly which is a play on the word “Bible” and the popular URL shortener bit.ly. It has two main functions: A Bible URL shortener and a Bible version popup detector for any website. 1. URL Shortener bib.ly let&#8217;s you easily create short URLs to Bible verses for use [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I turned a URL shortening website called <strong><a href="http://bib.ly/">bib.ly</a></strong> which is a play on the word “Bible” and the popular URL shortener <a href="http://bit.ly">bit.ly</a>. It has two main functions: A Bible URL shortener and a Bible version popup detector for any website.<span id="more-10"></span></p>
<h2>1. URL Shortener</h2>
<p>bib.ly let&#8217;s you easily create short URLs to Bible verses for use on Twitter and Facebook. You can use the interface you see below or just type in something that looks like a Bible verse after http://bib.ly/</p>
<p><a href="http://bib.ly/"><img src="http://johndyer.name/wp-content/uploads/2011/04/bibly-entry-1chr.jpg" alt="" /></a></p>
<p><span>When someone clicks a link, they see the Biblical text and get links to several Bible </span></p>
<p><a href="http://bib.ly/1Chr11.22"><img src="http://johndyer.name/wp-content/uploads/2011/04/bibly-verse.jpg" alt="" /></a></p>
<h2>2. Bible Refernece Popup</h2>
<p>You can also add bib.ly to a site by adding the following two lines of code to your own site</p>
<pre class="brush: xml;">&lt;script src="http://code.bib.ly/bibly.min.js"&gt;&lt;/script&gt;
&lt;link href="http://code.bib.ly/bibly.min.css" rel="stylesheet" /&gt;</pre>
<p>This script will find all Bible references like these Mark 5:36; John 3:16; Eph 2:8-9 and create links to the main bib.ly site along with a popup so you can read the text.</p>
<h2>How I Built It</h2>
<p>I chose to use ASP.NET MVC 3.0 because it makes this kind of URL handling pretty easy and because I wanted the Bible parsing code to look pretty close in both JavaScript and the server-side language (C#). I fooled around with doing the site in <a href="http://nodejs.org">node.js</a>, but decided that I wasn’t confident enough in my node.js skills to pull it off and get it properly hosted.</p>
<p>So what follows are my notes about how the site works and how ASP.NET MVC made it really easy to build.</p>
<div>
<div>
<h2>URL design</h2>
<p>The site needs to have two kinds of URLs:</p>
<ol style="padding-right: 40px;">
<li><strong>Fixed pages </strong>– I needed a few normal pages like Home, Plugins, and Contact that will look like this:<br />
<a href="http://bib.ly/plugins">http://bib.ly/plugins</a><br />
<a href="http://bib.ly/contact">http://bib.ly/contact</a></li>
<li><strong>Parsed URLs</strong> - All the other URLs will need to be checked to see if they are a valid Bible Reference. Bit.ly has to check if the URL is a valid id in its enormous database, but we need to actually attempt to read the URL and see if it makes sense as a Bible verse.<br />
<a href="http://bib.ly/John3.16">http://bib.ly/John3.16</a> for John 3:16<br />
<a href="http://bib.ly/Gen12:1-3">http://bib.ly/Gen12:1-3</a> for Genesis 12:1-3<br />
<a href="http://bib.ly/1Chr11.22-ESV">http://bib.ly/1Chr11.22-ESV</a> for 1 Chronicles 11:22 in the ESV<br />
<a href="http://bib.ly/asdfasd12">http://bib.ly/asdfasd12</a> needs to throw a 404 error.</li>
</ol>
<h2>Controller Setup</h2>
<p>Getting this to work was actually really easy once I figured it out. Basically, I hard coded the paths to the static pages in one controller and then setup another controller as a wildcard URL handler.</p>
<h3>Global.asax</h3>
<p>To handle the Bible references, I used wildcard mapping. The only problem with that is that it breaks the normal “{controller}/{action}/{id}” which usually hooks up a root/home page. This means I needed to manually hook up the “Fixed pages” above.</p>
<pre class="brush: c-sharp;">// Map the home page
routes.MapRoute(
     "home", "", new { controller = "Home", action = "Index"}
);

// Map all sub pages
foreach(String route in new string[] { "About", "Contact", "Plugins", "Feedback" }) {
     routes.MapRoute(
           "page_" + route, route.ToLower(),
           new { controller = "Home", action = route }
     );
}

// Send everything else to the Reference controller to parse
routes.MapRoute(
     "verses", "{*referencetext}",
     new { controller = "Verses", action = "Show"}
);</pre>
<h3>HomeController.cs</h3>
<p>This one is pretty boring. It’s just a list of Views and one post handler for the Contact form.</p>
<h3>VersesController.cs</h3>
<p>This controller has two actions: Show and NotFound. The Show action attempts to parse the URL into a Bible reference. If it’s successful, it shows a page. If not, you get a <a href="http://bib.ly/pearlofgreatprice">404 error page</a>. This could have been handled in the Global.asax with a UrlConstraint, but I thought this was clearer.</p>
<pre class="brush: c-sharp;">public ActionResult Show(string referencetext) {

     // parse the reference
     Reference reference = ReferenceParser.Parse(referencetext);

     // if it didn’t parse, show the not found View
     if (reference == null) {
           Response.StatusCode = 404;
          return View("NotFound");
     }

     // show the view, using the reference object as the model
     return View(reference);
}

public ActionResult NotFound() {
     Response.StatusCode = 404;
     return View();
}</pre>
<h3>URLs with a Colon (:) Character</h3>
<p>Technically, you’re not supposed to use the colon character in a URL without escaping it. But it’s very common to use a colon to separate a chapter and a verse when giving a Bible reference (2 Cor 5:17; Rev. 22:1-4) so I wanted bib.ly to understand the colon character if someone chose to use it.</p>
<p>ASP.NET, however, disallows the colon character (and five other no-nos) by default. To allow colons, you just have to edit the following line in the web.config file.</p>
<p>Default requestPathInvalidCharacters value</p>
<pre class="brush: xml;">&lt;httpRuntime requestPathInvalidCharacters="&amp;lt;,&amp;gt;,*,:,%,&amp;amp;,\"/&gt;</pre>
<p>With the colon removed.</p>
<pre class="brush: xml;">&lt;httpRuntime requestPathInvalidCharacters="&amp;lt;,&amp;gt;,*,:,%,&amp;amp;,\"/&gt;</pre>
<h2>Wrap Up</h2>
<p>Hope that gives a basic sense of how the site works. There is a little more code on the C# side to help manage the versions and Bible website links, but the rest of the site’s functionality is mostly just simple HTML and CSS controlled by JavaScript utilizing JSONP to get the Biblical text from their content providers.</p>
</div>
</div>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/rpqTuF5EgQs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/bib-ly-asp-net-mvc-url-shortener-for-bible-references/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://johndyer.name/bib-ly-asp-net-mvc-url-shortener-for-bible-references/</feedburner:origLink></item>
		<item>
		<title>ffmpeg Settings for HTML5 codecs (h264/mp4, theora/ogg, vp8/webm)</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/fdQM4NFZed4/</link>
		<comments>http://johndyer.name/ffmpeg-settings-for-html5-codecs-h264mp4-theoraogg-vp8webm/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 08:00:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://531316e4-53dd-42e8-bed2-9eb57911136a</guid>
		<description><![CDATA[This is just a quick tip for people encoding video for HTML5 (and using sweet HTML5 players like MediaElement.js). Go download a copy of ffmpeg, and if you&#8217;re on Windows, use this guide to set it up. Then use the following commands to create H.264, WebM, and Ogg videos, along with an image you can [...]]]></description>
			<content:encoded><![CDATA[<p>This is just a quick tip for people encoding video for HTML5 (and using sweet <a href="http://mediaelementjs.com/">HTML5 players like MediaElement.js</a>). Go download a <a href="http://ffmpeg.arrozcru.org/autobuilds/">copy of ffmpeg</a>, and if you&#8217;re on Windows, use <a href="http://www.moosechips.com/2009/08/installing-ffmpeg-binary-in-windows/">this guide</a> to set it up. Then use the following commands to create H.264, WebM, and Ogg videos, along with an image you can use as a poster.</p>
<pre class="brush: plain;">REM mp4  (H.264 / ACC)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -i %1 -b 1500k -vcodec libx264 -vpre slow -vpre baseline  											-g 30 -s 640x360 %1.mp4
REM webm (VP8 / Vorbis)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -i %1 -b 1500k -vcodec libvpx  							-acodec libvorbis -ab 160000 -f webm 	-g 30 -s 640x360 %1.webm
REM ogv  (Theora / Vorbis)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -i %1 -b 1500k -vcodec libtheora							-acodec libvorbis -ab 160000 			-g 30 -s 640x360 %1.ogv
REM jpeg (screenshot at 10 seconds)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -i %1 -ss 00:10 -vframes 1 -r 1 -s 640x360 -f image2 %1.jpg</pre>
<p>I save this as a batch file and then just drag and drop videos on it to get everything ready for HTML5.</p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/fdQM4NFZed4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/ffmpeg-settings-for-html5-codecs-h264mp4-theoraogg-vp8webm/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://johndyer.name/ffmpeg-settings-for-html5-codecs-h264mp4-theoraogg-vp8webm/</feedburner:origLink></item>
		<item>
		<title>HTML5 Reset Debug</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/Wf2Kqm8eDAo/</link>
		<comments>http://johndyer.name/html5-reset-debug/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 22:17:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[HTML/CSS]]></category>

		<guid isPermaLink="false">http://6ba9db92-0782-45e6-b2ca-0a76e372a757</guid>
		<description><![CDATA[I&#8217;m a huge fan of using HTML Reset, originally created by Eric Meyer and given HTML5 updates by people like Richard Clark. The only problem is that when you try to use Firebug, WebKit inspector, IE Developer Tools, or Opera Dragonfly, you get tons of declarations. Ever seen something like this? HTML Reset Production It&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a huge fan of using HTML Reset, originally created by <a href="http://meyerweb.com/eric/tools/css/reset/">Eric Meyer</a> and given HTML5 updates by people like <a href="http://html5doctor.com/html-5-reset-stylesheet/">Richard Clark</a>.</p>
<p>The only problem is that when you try to use Firebug, WebKit inspector, IE Developer Tools, or Opera Dragonfly, you get tons of declarations. Ever seen something like this?</p>
<h2>HTML Reset Production</h2>
<p><img src="http://johndyer.name/wp-content/uploads/2010/12/htmlreset-release.png" alt="" /><span id="more-12"></span></p>
<p>It&#8217;s a little hard to tell what&#8217;s going on. So instead of several large blocks of HTML selectors which are needed in production, I&#8217;ve listed each selector only once and explicitly defined all CSS properties and values. This makes the above WebKit screenshot turn into</p>
<h2>HTML Reset Debug</h2>
<p><img src="http://johndyer.name/wp-content/uploads/2010/12/htmlreset-debug.png" alt="" /></p>
<p>Of course, you should never use this in production because it&#8217;s around 11KB compared to .6KB for a minified HTML reset designed for production. But I&#8217;ve been finding it helpful for development, and I thought I would share it.</p>
<h3>Make Your Own</h3>
<ul>
<li><a href="/lab/cssdecompactor/">CSS De-Compactor</a></li>
</ul>
<h3>Get it</h3>
<ul>
<li><a href="https://github.com/johndyer/html5-reset-debug">HTML5 Reset Debug</a> (my original CSS reset debug)</li>
</ul>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/Wf2Kqm8eDAo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/html5-reset-debug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://johndyer.name/html5-reset-debug/</feedburner:origLink></item>
		<item>
		<title>MediaElement.js – a magic unicorn HTML5 video library</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/G1Pn4E4ViVQ/</link>
		<comments>http://johndyer.name/mediaelement-jsa-magic-unicorn-html5-video-library/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 20:31:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://10dae2df-55ef-44d6-8e52-3982c7798b68</guid>
		<description><![CDATA[I&#8221;ve posted before about HTML5 video and based on what I found I released an HTML5 &#60;video&#62; framework and player called MediaElement.js. But I never got around to explaining the logic behind the new library so here it goes: The Problems with HTML5 &#60;video&#62; (1) Codecs It has been well documented that browsers supporting HTML5 [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8221;ve posted <a href="http://johndyer.name/post/Simple-Cross-Browser-H264-video-in-HTML5.aspx">before about HTML5 video</a> and based on what I found I released an <a href="http://mediaelementjs.com/">HTML5 &lt;video&gt; framework and player called MediaElement.js</a>. But I never got around to explaining the logic behind the new library so here it goes:</p>
<h2>The Problems with HTML5 &lt;video&gt;</h2>
<h3>(1) <strong>Codecs</strong></h3>
<p><strong> </strong>It has been well documented that browsers supporting HTML5 &lt;video&gt; don’t support the same codecs. Here’s the current breakdown of <em>proposed(*)</em> codec support including mobile browsers and plugins.</p>
<table border="1" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th></th>
<th>&lt;IE9</th>
<th>IE9</th>
<th>Firefox</th>
<th>Safari</th>
<th>Chrome</th>
<th>Opera</th>
<th>Andriod</th>
<th>iOS</th>
<th>WP7</th>
<th>Flash</th>
<th>Silverlight</th>
</tr>
</thead>
<tbody>
<tr>
<th>H.264</th>
<td>-</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<th>OGG</th>
<td>-</td>
<td>-</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>WebM</th>
<td>-</td>
<td>X*</td>
<td>X</td>
<td></td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td>X*</td>
<td></td>
</tr>
</tbody>
</table>
<p><span id="more-13"></span></p>
<h3><strong>(2) Old Browsers</strong></h3>
<p><strong> </strong>Even if codecs weren’t an issue, older browsers don’t understand the HTML5 &lt;video&gt; tag. This means you have to provide alternatives viewing mechanisms like Flash or Silverlight fallbacks.</p>
<h3>(3) <strong>Style/UI</strong></h3>
<p><strong> </strong>Each browser has a different UI for their HTML5 &lt;video&gt; players. You can write a player in JavaScript/CSS to bring consistency, but then older browsers will get a different UI when they fall back to Flash. Here are the native controls (from <a href="http://dev.opera.com/articles/view/custom-html5-video-player-with-css3-and-jquery/">Opera&#8217;s tutorial</a>)</p>
<p><img src="http://johndyer.name/wp-content/uploads/2010/09/native-video-controls.jpg" alt="" /></p>
<h2>Proposed Solutions</h2>
<h3><strong>(1) Nested HTML</strong></h3>
<p><strong></strong><a href="http://camendesign.com/code/video_for_everybody">Video for Everybody</a> from Kroc Camden is a pure HTML way of serving video that works in just about every OS/browser combination.</p>
<p>Pros:</p>
<ul>
<li><em>No JavaScript requirement</em>:  Video for Everybody is pure HTML with Flash nested inside for browsers that don’t understand the &lt;video&gt; tag.</li>
</ul>
<p>Cons:</p>
<ul>
<li><em>A lot of HTML</em>: You’re probably going to need some backend code to help manage this since it’s very unruly to type on your own.</li>
<li><em>Requires multiple files</em>: When a browser like IE8 hits the &lt;video&gt; tag which it doesn’t understand, it just skips it and moves on to the nested &lt;object&gt; tag inside. However, when a browser that does understand &lt;video&gt; comes along, it always ignores the nested code even if it can’t play the provided video file. So, if you try to server an OGG file to Safari or a MP4 to Firefox, you just get a black box with an X. This means you have to provide both MP4 and OGG files.</li>
</ul>
<h3><strong>(2) JavaScript player with Flash fallbacks</strong></h3>
<p><strong></strong>This is the solution of every other library. They detect if the browser supports the &lt;video&gt; tag and if the browser can play the given file. If the browser can play the file, then a cool HTML/CSS/JS player is shown. If not, then the JavaScript replaces the &lt;video&gt; tag with an Flash player. You can find a great list of these players from <a href="http://praegnanz.de/html5video/">Praegnanz’s HTML5 video list</a>.</p>
<p>Pros:</p>
<ul>
<li><em>Single Video file</em>: This allows you to use a single H.264/MP4 which will work natively on IE9, Safari, Chrome, WM7, Andriod, and iOS. Firefox, Opera, and older browsers get a Flash player.</li>
<li><em>Same UI for HTML5</em>: All browsers with HTML5 get the same UI instead of the browser default.</li>
</ul>
<p>Cons</p>
<ul>
<li><em>Inconsistent interface(s)</em>: While HTML5 browsers get the same UI, other browser get a different UI in Flash. If you just want someone to play a video, this isn’t really a problem. But if you need anything beyond basic video buttons, then you’ll have to build the feature twice, once in HTML/CSS (IE9, WebKit) and again for Flash (Opera, FF, &lt;IE9). JW Player pulls this off, but overall this problem makes HTML5 video seem not worth the effort.</li>
</ul>
<h2>MediaElement Solution: Wrap the HTML5 spec around a plugin, then build the player</h2>
<p><a href="http://mediaelementjs.com/">MediaElement.js</a> goes at the problem a bit differently than the other JavaScript libraries. Instead of falling back to a full-fledged Flash video player for browsers that don’t support &lt;video&gt;, MediaElement inserts a tiny Flash object and wraps it with a JavaScript object that mirrors the <a href="http://www.w3.org/TR/html5/video.html">HTML5 &lt;video&gt; spec</a>.</p>
<p>This means that developers can write one set of code to MediaElement.js and have it work in every browser regardless of what it supports. And instead of just supporting Flash, there is also a Silverlight plugin that allows you to support more browsers (or avoid Flash on the Mac) and even put old WMV files that you don’t want to encode in a &lt;video&gt; tag.</p>
<p>On top of MediaElement (which is library independent JavaScript) and jQ<br />
<script type="text/javascript" src="http://johndyer.name/editors/tiny_mce3/themes/advanced/langs/en.js"></script><br />
 uery, I built MediaElementPlayer which is a sample HTML/CSS/JavaScript player that is easily skinnable through CSS and provides the same interface to every browser. Here’s how it works:</p>
<p><img src="http://johndyer.name/wp-content/uploads/2010/09/medialement-api.png" alt="" /></p>
<p>And here&#8217;s the result:</p>
<p><img src="http://johndyer.name/wp-content/uploads/2010/09/mediaelementplayer-example.jpg" alt="" /></p>
<p>Pros</p>
<ul>
<li><em>Single Video file</em>: like the other JavaScript libraries, you can use a single MP4 file for everyone. Also, when Flash starts supporting WebM, you could use that and have Safari use the Flash plugin.</li>
<li><em>Single API</em>: MediaElement gives you a single programming API defined by the W3.</li>
<li><em>Consistent UI</em>: the controls are HTML/CSS even in Flash or Silverlight modes.</li>
</ul>
<p>Bonus!</p>
<ul>
<li><em>Double your codecs, double your fun: </em>The Flash and Silverlight fallbacks enable the &lt;video&gt; tag to use additional media types like the older FLV (Flash video) format, Flash RMTP streaming, or even Window Media (WMA, WMV). MediaElement will choose the appropriate playback mechanism (native HTML5, Flash, or Silverlight) for your media and browser, and you&#8217;ll still get the same player UI.</li>
</ul>
<p>Cons</p>
<ul>
<li><em>Slight API differences</em>: Because JavaScript doesn’t have native get/set properties, I’ve had to implement<br />
<script type="text/javascript" src="http://johndyer.name/editors/tiny_mce3/themes/advanced/langs/en.js"></script><br />
some HTML5 media properties as get/set methods. See <a href="http://mediaelementjs.com/">http://mediaelementjs.com/</a> for the main changes [e.g. media.src becomes media.setSrc(url)]</li>
</ul>
<h2>Future Work</h2>
<p>One gotcha with HTML5 video is the issue of fullscreen support. HTML5 video does not have a consistent way to do true fullscreen video (in fact, the <a href="http://www.w3.org/TR/html5/video.html">HTML5 spec discourages it</a>). You can expand the video to fill the browser, but currently only Safari provides a JavaScript API to do real fullscreen video (Chrome has the API, but it’s not implemented yet). Firefox can do fullscreen, but users must select it in a context menu. Also, Flash and Silverlight do not allow you to trigger fullscreen through the JavaScript API.</p>
<p>Also, I&#8217;d like to provide some example skins that mimic popular players like YouTube and Vimeo and a default theme that&#8217;s a little prettier.</p>
<h2>Implementations</h2>
<h3>MediaElementPlayer</h3>
<p>If you want a full-fledged player that just works, here&#8217;s the code:</p>
<pre>&lt;!-- requirements --&gt;
&lt;script src="jquery.js"&gt;&lt;/script&gt;
&lt;script src="mediaelement.js"&gt;&lt;/script&gt;
&lt;script src="mediaelementplayer.js"&gt;&lt;/script&gt;
&lt;link rel="stylesheet" href="mediaelementplayer.css" /&gt;

&lt;!-- video tag --&gt;
&lt;video id="v1" src="myvideo.mp4" width="320" height="240"&gt;&lt;/video&gt;

&lt;!-- startup --&gt;
&lt;script&gt;
$('video').mediaelementplayer();
// OR
new MediaElementPlayer('#v1');
&lt;/script&gt;</pre>
<h3>MediaElement</h3>
<p>If you want to build your own player using MediaElement and your own JavaScript, here&#8217;s a sample:</p>
<pre>&lt;!-- requirements --&gt;
&lt;script src="mediaelement.js"&gt;&lt;/script&gt;

&lt;!-- video tag --&gt;
&lt;video id="v1" src="myvideo.mp4" width="320" height="240"&gt;&lt;/video&gt;
&lt;!-- startup --&gt;

&lt;script&gt;
var v = document.getElementsByTagName("video")[0];
new MediaElement(v, {success: function(media) {
	media.play();
}});
&lt;/script&gt;</pre>
<h2>References</h2>
<ul>
<li>Full description of the API with options at the <a href="http://mediaelementjs.com/">MediaElement.js</a> site.</li>
<li><a href="http://github.com/johndyer/mediaelement">Github project</a></li>
<li><a href="http://github.com/johndyer/mediaelement/zipball/master">Download MediaElement</a></li>
</ul>
<h3>See Also</h3>
<ul>
<li><a href="http://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills">HTML5 shim list</a> &#8211; Paul Irish&#8217;s list of JavaScript libraries that enable features</li>
<li><a href="http://videojs.com/">VideoJS</a> &#8211; I think this is the best other HTML5 player out there</li>
<li><a href="http://www.projekktor.com">Projekktor</a> &#8211; I also like this one quite a bit</li>
<li><a href="http://camendesign.com/code/video_for_everybody">Video for Everybody</a> - HTML only player</li>
<li><a href="http://praegnanz.de/html5video/">HTML5 player list</a> - I&#8217;ve learned a lot from these other players</li>
</ul>
<p>Hope you like it. GPL and MIT.</p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/G1Pn4E4ViVQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/mediaelement-jsa-magic-unicorn-html5-video-library/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		<feedburner:origLink>http://johndyer.name/mediaelement-jsa-magic-unicorn-html5-video-library/</feedburner:origLink></item>
		<item>
		<title>Simple Cross-Browser HTML5 video with a single H.264 file and fallback options</title>
		<link>http://feedproxy.google.com/~r/johndyer/~3/hCkFwDhBsNs/</link>
		<comments>http://johndyer.name/simple-cross-browser-html5-video-with-a-single-h-264-file-and-fallback-options/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 01:32:00 +0000</pubDate>
		<dc:creator>johndyer@gmail.com</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://7102eb9c-e1ed-4226-aefe-83ec89d024ad</guid>
		<description><![CDATA[At first glance, the promise of HTML5 &#60;video&#62; seems awesome. Just a simple &#60;video src="myvideo.mp4" controls&#62;&#60;/video&#62; and you&#8217;re done right? Not quite. In reality there are all kinds of browser inconsistence that make this impossible. Here&#8217;s a run down of the problems: 1. Older browsers don&#8217;t support &#60;video&#62; Only the most recent versions of the [...]]]></description>
			<content:encoded><![CDATA[<p>At first glance, the promise of HTML5 &lt;video&gt; seems awesome. Just a simple</p>
<pre>&lt;video src="myvideo.mp4" controls&gt;&lt;/video&gt;</pre>
<p>and you&#8217;re done right? Not quite. In reality there are all kinds of browser inconsistence that make this impossible. Here&#8217;s a run down of the problems:</p>
<p><strong>1. Older browsers don&#8217;t support &lt;video&gt;</strong></p>
<p><strong></strong>Only the most recent versions of the big five (Firefox, Chrome, Safari, IE, Opera) support &lt;video&gt;, so you have to have a fallback solution of some kind if you want to use &lt;video&gt; and still support your audience.<span id="more-14"></span></p>
<p><strong>2. Newer browsers don&#8217;t support the same codecs</strong></p>
<p>Sadly, different browsers support different codecs. H.264 works in Chrome, Safari, and IE9, while Firefox and Opera only support Ogg/Vorbis. All the major browser vendors have pledged support for Google&#8217;s recently released <a href="http://webmproject.blogspot.com/">WebM</a> format, but this will take some time for the browers and encoding software to catch up.</p>
<p><strong>3. Fallback HTML requires multiple video files</strong></p>
<p>The most common solution offered is to use nested HTML to allow browsers that don&#8217;t support &lt;video&gt; to fallback to flash. One of the best of these is called <a href="http://camendesign.com/code/video_for_everybody">Video for Everybody</a> and looks something like this:</p>
<pre>&lt;video&gt;<strong>   &lt;source src="myfile.mp4"&gt;   &lt;source src="myfile.ogg"&gt;</strong>   &lt;object src="flashplayer.swf?file=myfile.mp4"&gt;      &lt;embed src="flashplayer.swf?file=myfile.mp4"&gt;   &lt;/object&gt;&lt;/video&gt;</pre>
<p>This works in all browsers, but it has a major problem: <strong>You must have two video files</strong>. If you attempt to use only MP4, Firefox on Opera will fail. If you remove the &lt;source src=&#8221;myfile.ogg&#8221;&gt;, <strong>Firefox and Opera will not fallback to the Flash &lt;object&gt;</strong>. They will just display a big, blank, black box with an X. The same goes if you only use OGG on browsers that don&#8217;t support OGG, or attempt to use WebM.</p>
<p>The HTML fallback mechanism only works if the browser doesn&#8217;t understand the &lt;video&gt; tag. It doesn&#8217;t work if it doesn&#8217;t understand the &lt;source&gt; file. So if you want to only use one file, then you must use JavaScript.</p>
<p><strong>A Simple JavaScript Solution</strong></p>
<p>Since I don&#8217;t want to maintain two versions of every video, I need a way to fallback to Flash for non-H.264 browsers. Here&#8217;s my simple solution using jQuery.</p>
<pre>&lt;video id="my-video"&gt;
   &lt;source src="myfile.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;script&gt;
(function() {
  var video = document.createElement("video");
  if ( typeof(video.canPlayType) == 'undefined' || // detect browsers with no &lt;video&gt; support
       video.canPlayType('video/mp4') == '') { // detect the ability to play H.264/MP4

       var video = $('#my-video');
       var videoUrl = video.find('source').attr('src');
       var flashUrl = '/flash/myplayer.swf';

       // create flash
       var flash = '&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +
				'	codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ' +
				'	width="' + video.width() + '" height="' + video.height() + '" id="fallbackplayer"&gt;' +
				'		&lt;param name="allowfullscreen" value="true" /&gt; ' +
				'		&lt;param name="movie" value="' + flashUrl + '?mediaUrl=' + videoUrl + '" /&gt; ' +
				'		&lt;embed id="dtsplayer" width="' + video.width() + '" height="' + video.height() + '" allowfullscreen="true" allowscriptaccess="always" ' +
				'			quality="high" name="fallbackplayer" ' +				'			src="' + flashUrl + '?mediaUrl=' + videoUrl + '" ' +
				'			type="application/x-shockwave-flash" /&gt; ' +
				'&lt;/object&gt;';

        // insert flash and remove video
        video.before(flash);
        video.detach();
  }
})();
&lt;/script&gt;</pre>
<p>The code is fairly simple. It just checks if the browser understands the &lt;video&gt; tag by checking for the &#8220;canPlayType&#8221; function, then it uses canPlayType to determine if the browser can play an H.264/MP4. If not, it inserts Flash as a fallback.</p>
<p>Please note: This is a simplified script for example purposes only. It needs flash version detection, and it should be turned into a jQuery extension, but it should still be a nice guide for</p>
<img src="http://feeds.feedburner.com/~r/johndyer/~4/hCkFwDhBsNs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://johndyer.name/simple-cross-browser-html5-video-with-a-single-h-264-file-and-fallback-options/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://johndyer.name/simple-cross-browser-html5-video-with-a-single-h-264-file-and-fallback-options/</feedburner:origLink></item>
	<media:rating>nonadult</media:rating><media:description type="plain">Technology and web development in ASP.NET, Flash, and JavaScript</media:description></channel>
</rss><!-- Dynamic page generated in 1.200 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-25 09:48:49 -->

