<?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/"
	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/"
	>

<channel>
	<title>User Agent Man</title>
	<atom:link href="http://www.useragentman.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.useragentman.com/blog</link>
	<description>A Blog about Client Side Web Technology</description>
	<lastBuildDate>Tue, 09 Mar 2010 14:53:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Cross Browser CSS Transforms &#8211; even in IE</title>
		<link>http://www.useragentman.com/blog/2010/03/09/cross-browser-css-transforms-even-in-ie/</link>
		<comments>http://www.useragentman.com/blog/2010/03/09/cross-browser-css-transforms-even-in-ie/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 05:00:05 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=896</guid>
		<description><![CDATA[The CSS transform property allows developers to rotate, scale, and skew blocks of HTML via CSS.  Although you can do the same thing with images in Photoshop or The GIMP, using CSS transforms allows developers to do the same thing with any HTML markup and allows users to select the text within the transformed [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_822" class="wp-caption alignright" style="width: 267px"><a href="http://www.useragentman.com/tests/cssSandpaper/cube3.html"><img class="size-full wp-image-822 " title="CSS3 Cube Layout Example" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeExampleScreenshot.png" alt="" width="257" height="208" /></a><p class="wp-caption-text">
<div>An example of a page using the CSS Transform property and cssSandpaper.  Visible in most major browsers, including Internet Explorer.  Layout based on work done by Paul Hayes in his article <a href='http://www.fofronline.com/2009-04/3d-cube-using-css-transformations/'>3D Cube using CSS transformations</a></div>
<p></p></div>
<p>The <a href="http://www.w3.org/TR/css3-2d-transforms/">CSS <code>transform</code> property</a> allows developers to rotate, scale, and skew blocks of HTML via CSS.  Although you can do the same thing with images in Photoshop or The GIMP, using CSS transforms allows developers to do the same thing with any HTML markup and allows users to select the text within the transformed object.</p>
<p>When I first saw sites using <code>transform</code>, I looked at the underlying code and tried to produce pages using <code>transform</code> in all browsers.  Although Firefox, Opera and Webkit based browser support it via <a href="http://reference.sitepoint.com/css/vendorspecific">vendor-specific prefixes</a> (using <code>-moz-transform</code>, <code>-o-transform</code> and <code>-webkit-transform</code> respectively) Internet Explorer doesn&#8217;t support it at all.  I didn&#8217;t like that, so I took out my JavaScript whip, beat Explorer into submission and made it do my bidding (but not without getting a few mental bruises of my own).</p>
<p>Before I start talking about the details of my solution, let&#8217;s take a look at a few examples of it in action.  The following code has been tested with Firefox 3.5, Safari 4,  Chrome 4, Internet Explorer 6 and higher.</p>
<ol>
<li><a href="/tests/cssSandpaper/rotateTest.html">Rotations Example</a></li>
<li><a href="/tests/cssSandpaper/skewTest.html">Skew Example</a></li>
<li><a href="/tests/cssSandpaper/cube3.html">Cube Example, using rotates and skews</a></li>
<li><a href="/tests/cssSandpaper/example.html">Another example that looks like a CSS3 version of a Geocities page.</a></li>
</ol>
<p>(The examples  also work on my copy of Opera 10.5, although I have seen it fail on other installations &#8211; I will update this post when I find  out why).</p>
<h2>cssSandpaper to the Rescue</h2>
<p>I saw the design potential of using CSS transforms and was frustrated at Explorer&#8217;s lack of support.  I originally tried a non-JavaScript solution which involved creating CSS rules that combine <code>transform</code> with an IE technology that does something similar: the <a href="http://msdn.microsoft.com/en-us/library/ms533014%28VS.85%29.aspx"><code>DXImageTransform.Microsoft.Matrix</code> CSS <code>filter</code></a>.</p>
<p>I then, to steal a phrase from Russel Peters, started to Hurt Real Bad:</p>
<ul>
<li>the syntax of <code>transform</code> is very obvious:<br />
<blockquote class="code">
<pre>#myObject {
   transform: rotate(40deg) scale(2.0);
}</pre>
</blockquote>
<p>but the IE filter code is quite intimidating:</p>
<blockquote class="code">
<pre>#myObject {
   filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',
        M11=1.5320888862379554, M12=-1.2855752193730787,
        M21=1.2855752193730796, M22=1.5320888862379558);
}</pre>
</blockquote>
<p>The scary numbers that the <code>DXImageTransform.Microsoft.Matrix</code> filter uses requires knowledge of matrix and vector mathematics.  Even though there is a <a href="http://en.wikipedia.org/wiki/Transformation_matrix">great Wikipedia article on the subject</a>, even the mathematically gifted wouldn&#8217;t want to do the calculations to do a simple rotate in CSS (I would like to note here that even though I have a university degree in Mathematics, I hate doing arithmetic inside my head.  If you don&#8217;t believe me, watch  me figure out a tip at a restaurant sometime.  I&#8217;m not kidding).</li>
<li>although it is possible to have a list of transformations using <code>transform</code>, the <code>DXImageTransform.Microsoft.Matrix</code> filter only allows one transform matrix. In order to implement multiple transforms using one filter,  a designer would have to <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">convert all the transforms into matrices and multiply them together</a>.  Again, as ugly as I am when I first wake up in the morning.</li>
<li>when rotating, skewing, or doing any other transformations on objects using the <code>transform</code> property, the center of the object remains fixed.  However, the <code>Matrix</code> filter doesn&#8217;t keep the centre of the transformed object fixed, as seen by the illustration below:<br />
<table class="screenshots">
<thead>
<tr>
<th>Rotate using CSS transform</th>
<th>Rotate using IE Filter</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/rotateFirefox.png"></a><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/rotateFirefox.png"><img class="alignnone size-full wp-image-872" title="Screenshot of object rotated using CSS transform property." src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/rotateFirefox.png" alt="" width="241" height="240" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/rotateIE.png"><img class="alignnone size-full wp-image-873" title="example of object rotated with IE filter." src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/rotateIE.png" alt="" width="241" height="240" /></a></td>
</tr>
</tbody>
</table>
</li>
</ul>
<p><a class="exampleLink" href="/tests/cssSandpaper/failedRotateExample.html">See the above example in action (compare IE with the other browsers to see the difference for yourself)</a></p>
<p>I was about to give up on my endeavor until I read Weston Ruter&#8217;s clever <a href="http://weston.ruter.net/projects/css-gradients-via-canvas/">CSS Gradients in Canvas</a> article, which implements gradients in older versions Firefox and Opera.  What I really liked was how he used the CSS from a web page to place the canvas gradients in the page (as opposed to using CSS classes to indicate where the gradients should go).   I then thought it would be a great idea to do the same with CSS transforms &#8211; why not have  JavaScript find out which objects are transformed by reading the style sheets containing the transform rules, and if the browser is Internet Explorer, apply the <code>Matrix</code> filter, while translating the image so that the center is maintained.  How hard could it be &#8230;&#8230;.. right?</p>
<p>After a few obsessive months of coding, coffee drinking and Asprin popping (as well angrily asking myself on several occasions why the &#038;@$! I would wanted to do this in the first place), I created <code>cssSandpaper.js</code>, a library that implements <code>transform</code> (and some other CSS3 properties) as consistently as possible in all browsers.  It uses many ideas from Ruter&#8217;s gradient script, as well as <code>sylvester.js</code>, <a href="www.jcoglan.com/">James Coglan&#8217;s</a> brilliant <a href="http://sylvester.jcoglan.com/">matrix and vector math library</a>.</p>
<p>The code is currently in a beta stage, but I think that it&#8217;s in good enough shape that developers can start to play around with these really cool effects today and have it work in almost any browser.</p>
<h2>Browser Differences</h2>
<p>After I finished cssSandpaper and played around with transforms, I found some slight differences in the way browsers handled them:</p>
<ul>
<li>If you transform an object with scrollbars, it is possible to scroll the object in most browsers in most cases.  However, in the cube page I mocked up, I noticed the following behaviour:
<ul>
<li>the left facing side of the cube isn&#8217;t easily accessible in IE.</li>
<li>the scrollbars don&#8217;t appear at all in Opera.</li>
<li>the scrollbars are not quite clear in Chrome for Windows, although one can still scroll the sides if you can guess where they are.</li>
<li>Firefox 3.5 for Mac puts the scrollbars in strange places (this has been fixed 3.6).</li>
</ul>
</li>
<li>In Internet Explorer, the text is selectable but sometimes it takes a few tries to figure out how to do it (try selecting text with IE in my cube mockup and you&#8217;ll see what I mean).</li>
<li>When selecting text within Firefox, the text tends to jump around ever so slightly for some odd reason (this is quite a subtle effect that it is probably not noticeable in most instances).</li>
<li>It <strong>looks</strong> like Internet Explorer takes the block of HTML, converts it to an image and then does the transform (I&#8217;m not sure .. I&#8217;m guessing).  As a result, the text in certain situations will look a little blurry, especially if scaling is involved.</li>
</ul>
<p>As to be expected, the rendering of the transformed text in the other browsers slightly differs:</p>
<table class="screenshots">
<thead>
<tr>
<th></th>
<th>Explorer 6.x+</th>
<th>Firefox 3.5+</th>
<th>Safari 4.0+</th>
<th>Chrome 3.0+</th>
<th>Opera 10.0+</th>
</tr>
</thead>
<tbody>
<tr>
<th>Windows</th>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeExplorerWindows.png"><img class="alignnone size-full wp-image-840" title="cubeExplorerWindows" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeExplorerWindows.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxWindows.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxWindows.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeSafariWindows.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeSafariWindows.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeWindows.png"><img class="alignnone size-full wp-image-840" title="cubeExplorerWindows" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeWindows.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeOperaWindows.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeOperaWindows.png" alt="" /></a></td>
</tr>
<tr>
<th>Mac OS X</th>
<td style="text-align: center;">Not Applicable</td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxMac.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxMac.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeSafariMac.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeSafariMac.png" alt="" /></a></td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeMac.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeMac.png" alt="" /></a></td>
<td>Doesn&#8217;t support transforms yet (as of version 10.50)</td>
</tr>
<tr>
<th>Linux</th>
<td style="text-align: center;">Not Applicable</td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxUbuntu.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeFirefoxUbuntu.png" alt="" /></a></td>
<td style="text-align: center;">Not Applicable</td>
<td><a href="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeUbuntu.png"><img class="alignnone size-full wp-image-840" src="http://www.useragentman.com/blog/wp-content/uploads/2010/03/cubeChromeUbuntu.png" alt="" /></a></td>
<td>Doesn&#8217;t support transforms yet (as of version 10.50)</td>
</tr>
</tbody>
</table>
<h2>Using cssSandpaper</h2>
<p>After <a href="/downloads/cssSandpaper.1.0-beta1.zip">downloading the archive</a> you must put the following tags into the head of your document <strong>after all of your style sheet declarations</strong> (this is to ensure the JavaScripts will run after the style sheets are loaded):</p>
<blockquote class="code">
<pre>&lt;script type="text/javascript" src="path/to/js/cssQuery-p.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="path/to/js/jcoglan.com/sylvester.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="path/to/js/css3Helpers.js"&gt;&lt;/script&gt;</pre>
</blockquote>
<p>You can then use the transform property in your web pages.  Note that since the specification for the transform property is finalized by the W3C, I decided to use the  <a href="http://reference.sitepoint.com/css/vendorspecific">vendor-specific prefix</a> <code>-sand-</code> before each CSS3 property it supports.</p>
<p>The following is a description of how to use <code>transform</code>, as well as two other CSS3 properties that cssSandpaper supports, <code>box-shadow</code> and <code>gradient</code>.</p>
<p><a class="exampleLink" href="/downloads/cssSandpaper.1.0-beta1.zip">Download version 1.0 beta of cssSandpaper</a></p>
<h2>-sand-transform</h2>
<p><!-- Begin steps --></p>
<div class="steps">
<h3 class="first">Description</h3>
<p>Transforms allow developers to rotate, scale, and skew blocks of HTML via CSS.</p>
<h3>Syntax</h3>
<blockquote class="code">
<pre>#container {
   -sand-transform:  <em>&lt;function-list&gt;</em>;
}</pre>
</blockquote>
<p>where <em>&lt;function-list&gt;</em> can be a space separated list of the following functions:</p>
<table class="screenshot">
<thead>
<tr>
<th>Function</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>rotate(angle)</code></td>
<td>Rotates HTML elements.  <code>angle</code> can be in degrees (e.g. rotate(30deg)) or radians <code>rotate(1.3rad)</code></td>
</tr>
<tr>
<td><code>scale(sx[, sy])</code></td>
<td>Scales HTML elements.  <code>sx</code> and <code>sy</code> are numbers, where <code>1</code> represents the original size, <code>2</code> represents twice the size, etc.  Note that if <code>sy</code> isn&#8217;t specified, it is assumed to be equal to <code>sx</code>.  Similar functions are <code>scaleX(sx)</code> and <code>scaleY(sy)</code>.</td>
</tr>
<tr>
<td><code>skew(ax[, ay])</code></td>
<td>Skews the object around the x and y axes by the specified angles in degrees or radians.  If <code>ay</code> isn&#8217;t provided, it is assumed to be <code>0deg</code>.</td>
</tr>
<tr>
<td><code>matrix(a, c, b, d, tx, ty)</code></td>
<td>Applies a 2D transformation matrix comprised of the specified six values.  If you aren&#8217;t familiar with linear algebra and matrix arithmetic, this function will be hard to understand.  For further information, you may want to read <a href="http://en.wikipedia.org/wiki/Transformation_matrix">Wikipedia&#8217;s Transformation Matrix</a> article, although if you are mathematically challenged, you may run away from your computer screaming.</p>
<p>If you are familiar with matrix multiplication, note that c and b are reversed.  This follows the way Firefox has implemented this method (i <strong>believe</strong> WebKit based browsers reverse these numbers).</td>
</tr>
</tbody>
</table>
<p><strong>Note:</strong> non-Explorer browsers support the <code>translate</code> function as well.  I have not been able to find a way to make this work IE at this time, due to a technical  issue with the IE&#8217;s <code>Matrix</code> filter property (for those who want details, I use <code>sizingMethod='auto expand'</code> when using the <code>Matrix</code> filter which doesn&#8217;t support translations, and using sizingMethod=&#8217;crop&#8217; is not suitable to emulate the <code>transform</code> property).  For this reason, the <code>tx</code> and <code>ty</code> values of the <code>matrix()</code> function are not supported as well.</p>
<h3>Examples</h3>
<ul>
<li><a href="/tests/cssSandpaper/rotateTest.html">Rotations</a></li>
<li><a href="/tests/cssSandpaper/skewTest.html">Skews</a></li>
</ul>
</div>
<h2>-sand-box-shadow</h2>
<div class="steps">
<h3 class="first">Description</h3>
<p><code>box-shadow</code> allows us to take a block level element and put a shadow underneath.  There can optionally set a blur factor to give a warmer effect to the shadow.</p>
<h3>Syntax</h3>
<blockquote class="code">
<pre>#container {
   -sand-box-shadow: <em>&lt;horizontal-offset&gt;</em> <em>&lt;vertical-offset&gt;</em> <em>&lt;blur-radius&gt;</em> <em>
</em>;
}</pre>
</blockquote>
<p>Note that in IE, the <code>blur-radius</code> is not supported, due to a lack of support in IE&#8217;s <a href="http://msdn.microsoft.com/en-us/library/ms533014%28VS.85%29.aspx"><code>DropShadow</code> filter</a>.</p>
<h3>Examples</h3>
<ul>
<li><a href="/tests/cssSandpaper/boxShadowTest.html">Box-Shadow Example</a></li>
</ul>
</div>
<h2>-sand-gradient</h2>
<div class="steps">
<h3 class="first">Description</h3>
<p>Gradients are gradual blends of color, and can be <code>linear</code> or <code>radial</code>:</p>
<h3>Syntax</h3>
<blockquote class="code">
<pre>#container {
   background-image: -sand-gradient(<em>&lt;type&gt;, &lt;start-point&gt;, &lt;end-point&gt;, &lt;color-stop1&gt;, &lt;color-stop2&gt;, ..., &lt;color-stopN&gt;</em>)
}</pre>
</blockquote>
<p>The type can be <code>linear</code> and <code>gradient</code>, although Internet Explorer doesn&#8217;t support radial gradients at this time, due to limitations in IE&#8217;s <a href="http://msdn.microsoft.com/en-us/library/ms532997%28VS.85%29.aspx"><code>gradient</code> filter</a>.  Internet Explorer also only supports simple linear gradients (i.e. only  horizontal and vertical and only two colours).</p>
<p>A more detailed explanation can be found in the <a href="http://dev.w3.org/csswg/css3-images/#linear-gradients">section regarding gradients</a> of the <a href="http://dev.w3.org/csswg/css3-images/">W3C&#8217;s working draft of CSS Image Values Module Level 3</a></p>
<h3>Examples</h3>
<ul>
<li><a href="/tests/cssSandpaper/gradientTest.html">Gradients Example Page</a></li>
</ul>
</div>
<h2>Other Known Issues</h2>
<ul>
<li>Currently, when a users changes the font-size in IE, the layout gets a little messed up.  This will be fixed in a future release.</li>
<li>Scripting in IE cannot be done via the usual <code>obj.style.transform</code>.  There is, however, an alternative way of scripting the cssSandpaper supported properties which will be outlined in a future blog post (I don&#8217;t mean to keep anyone in suspense &#8230; it&#8217;s just that I feel like I&#8217;ve spent too much time on this post and I want to get at least this part out the door :-) ).</li>
<li>Opera 10.5 sort of works.  It works on my copy, but not on another copy I&#8217;ve seen.  I don&#8217;t know why yet, but I will find out soon and post and update when I do.</li>
<li>Weston Ruter&#8217;s gradient script has more features.  I will incorporate them in a future release.</li>
</ul>
<h2>Future Work</h2>
<p>cssSandpaper will eventually be about more than just transforms &#8211; I would like to be able to support other advanced CSS topics (maybe even animations, if it is possible). It probably has a few bugs in it &#8211; I would really appreciate anyone letting  me know if you find any (my e-mail address is at the top left part of the page).</p>
<p>If anyone would like to get contribute code or do testing, I would love the help too.  :-)</p>
<h2>Acknowledgments</h2>
<p>I would like to thank Weston Ruter for his <a href="http://weston.ruter.net/projects/css-gradients-via-canvas/">CSS Gradients in Canvas</a> script, since I stole many of his ideas with his permission (I will be implementing more of the advanced features of his script in a future release of CSS3Sandbox).  I would also like to thank  <a href="www.jcoglan.com/">James Coglan</a> for building  <a href="http://sylvester.jcoglan.com/">Sylvester</a> so I didn&#8217;t have to.</p>
<h2>Downloads</h2>
<p><a class="exampleLink" href="/downloads/cssSandpaper.1.0-beta1.zip">Download version 1.0 beta of cssSandpaper</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2010/03/09/cross-browser-css-transforms-even-in-ie/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Cross Browser HTML5 Drag and Drop</title>
		<link>http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/</link>
		<comments>http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 03:52:17 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=734</guid>
		<description><![CDATA[
Update (Feb 3, 2009):

A bug in Webkit seems to be the culprit in the permissions form example below not working correctly in Safari 4.  The code has been updated to work around this bug and the article below has been updated.  Thanks to russbuelt for pointing this out.
Apparently, an example made by Apple [...]]]></description>
			<content:encoded><![CDATA[<div class="importantNotes">
<h3>Update (Feb 3, 2009):</h3>
<ul>
<li>A <a href="http://code.google.com/p/chromium/issues/detail?id=14654">bug in Webkit</a> seems to be the culprit in the permissions form example below not working correctly in Safari 4.  The code has been updated to work around this bug and the article below has been updated.  Thanks to <code>russbuelt</code> for pointing this out.</li>
<li>Apparently, an example made by Apple which I reported not working in Safari <em>does</em> work in Safari 4.0.4 for Mac OS X.  Thanks for Scott Straker for this information.</li>
</div>
<div id="attachment_538" class="wp-caption alignleft" style="width: 267px"><a href="http://flickr.com/photos/svartling/3822068125/"><img class="size-full wp-image-538   " title="HTML5 Drag and Drop" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/html5DragAndDrop.png" alt="Remixed version of image by Svartling." width="257" height="174" /></a><p class="wp-caption-text">Image Credit: Flickr user svartling</p></div>
<p><a href="http://dev.w3.org/html5/spec/editing.html#dnd">HTML5 Drag and Drop</a> has been talked about a lot lately, but it&#8217;s hard to find really useful information about implementing it across multiple browsers.   <a href="http://hacks.mozilla.org/2009/07/html5-drag-and-drop/">Mozilla</a>, <a href="http://developer.apple.com/Mac/library/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html">Apple</a> and <a href="http://msdn.microsoft.com/en-us/library/ms537658%28VS.85%29.aspx">Microsoft</a> all have pages describing how to use it, but their examples seem to work only in their particular browser (<strike><em><a href="http://developer.apple.com/Mac/library/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html">Apple&#8217;s example</a> doesn&#8217;t even work in their own!</em></strike> <strong>Updated, Jan. 11, 2009:</strong> Although I have not been able to get this example working on Safari 2.0.4 and 3.1.2 for OS X and 4.0.4 for Windows, I have received word that it works on Safari 4.0.4 on OS X).  Remy Sharp&#8217;s great article <a href="http://html5doctor.com/native-drag-and-drop/">Native Drag and Drop</a> was a good place for me to start — however, the examples didn&#8217;t work in Internet Explorer.  I also thoroughly enjoyed JavaScript guru <a href="http://www.quirksmode.org/">Peter-Paul Koch&#8217;s</a> <a href="http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html">humorous and lengthy rant about cross-browser drag and drop headaches</a> where he uses creative and colourful language to describe what he thought of the standard, the browser manufacturers, and the WHAT-WG.</p>
<p>When normal people see the author of the <a href="http://www.quirksmode.org/compatibility.html">Compatibility Master Tables</a> respond negatively to a web technology, they would probably assume it would be a good sign to stay away from it.</p>
<p>However, I am not normal.  <strong>With a name like Zoltan, how could I <em>possibly</em> be normal?</strong> (and yes, <a href="http://www.useragentman.com/blog/the-infamous-zoltan-faq/">it <em>is</em> my real name</a>).</p>
<p>So, I decided to find out for myself how bad HTML5 Drag and Drop really is. Almost immediately, I understood Koch&#8217;s reaction &#8211; the browser vendors have not implemented all the same features, and there are even a few quirks in how the features that <em>are </em>implemented work.  However, after doing <em>a lot</em> of research, <strong>I found a common denominator that works well</strong>, with the help of a small bit of JavaScript that smooths out the edges.  Despite the implementation flaws, <strong>Future-proof HTML5 Drag and Drop is not too hard for developers to use in their own applications.</strong> This article will explain how to do this step by step with many examples along the way.  By the time you are done, you will be able to write useful  drag and drop scripts of your own like in this example:</p>
<p><a class="exampleLink" href="/tests/dragAndDrop/permissionForm.html#">See an example of HTML5 Drag and Drop in action.</a></p>
<h2>Advantages Over Existing Drag and Drop Implementations</h2>
<p>Koch mentioned in his blog post that &#8220;Web developers MUST NOT (in the sense of RFC 2119) use HTML 5 drag and drop. They should use <a href="http://www.quirksmode.org/js/dragdrop.html">old-school scripts</a> instead&#8221;.  I would argue that developers <em>should</em> use HTML5 drag and drop for the following reasons:</p>
<ul>
<li><strong>JavaScript Framework Independent: </strong>Most other (but not all) drag and drop implementations are tied into 3rd party frameworks like <a href="http://www.dojotoolkit.org/">Dojo</a>, <a href="http://www.prototypejs.org/">Prototype</a> or <a href="http://jquery.com/">jQuery</a>.</li>
<li><strong>Built-in Browser Support: </strong>HTML5 Drag and Drop is supported in Firefox 3.5+, Chrome 3.0+, Safari 3.0+ and Internet Explorer 5.0 (<strong>Note:</strong> that is not a typo &mdash; HTML5 Drag and Drop is based on work done by Microsoft <strong>in 1999</strong>).  Because it is part of HTML5, I assume Opera support should be inevitable.</li>
<li><strong>Integration With Other Web Applications:</strong> the HTML5 specification will allow developers to <em><strong>produce  drag and drop scripts that work across frames, and across browser windows.</strong></em></li>
<li><strong>Integration With Non-Web Applications:</strong> the HTML5 specification also allows users to <em><strong>drag and drop data to and from non-web applications</strong></em></li>
</ul>
<h2>The Basics of Drag and Drop, Step by Step</h2>
<p>In order to save other developers from the headaches I got deciphering cross browser drag and drop, I present the following guide that shows how to do in five easy steps.   Every step will describe a set of related concepts, and will show examples, most of which are built on code from previous steps.  At the end of each step, I will discuss any issues and interesting bits I came across.</p>
<div class="steps">
<h3>Step 1: Defining a Draggable Object</h3>
<p>First you need to define the HTML nodes that you want to drag.  Firefox requires that these nodes have their <code>draggable</code> attribute set to <code>"true"</code>, Internet Explorer requires that the node must be an <code>&lt;a&gt;</code> tag with (the <code>href</code> attribute set) or an <code>&lt;img&gt;</code> tag.</p>
<blockquote class="code">
<pre>&lt;a href="#" id="toDrag" draggable="true"&gt;This is a draggable item&lt;/a&gt;</pre>
</blockquote>
<p>To show how this works, I have written a very simple page with a the above markup in the <code>&lt;body&gt;</code>:</p>
<blockquote class="code">
<pre>&lt;!DOCTYPE html&gt;

&lt;html lang="en"&gt;
    &lt;head&gt;
        &lt;meta name="generator" content="HTML Tidy, see www.w3.org"&gt;

        &lt;title&gt;Test #1: A Simple Draggable Object&lt;/title&gt;

      &lt;script type="text/javascript" src="../../shared/js/EventHelpers.js"&gt;
      &lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/DragDropHelpers.js"&gt;
      &lt;/script&gt;

        &lt;link rel="stylesheet" type="text/css" media="screen" href=
        "css/test1.css"&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;h1&gt;Test #1: A Simple Draggable Object&lt;/h1&gt;

<span class="hilite">        &lt;a href="#" id="toDrag" draggable="true"&gt;This is a
        draggable item&lt;/a&gt;</span>

        &lt;p&gt;Try to drag the red box around. You will see the
        draggable object cloned in every browser except Explorer
        and Chrome.&lt;/p&gt;

        &lt;a href=
        "http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/"&gt;
        Go back to the User Agent Man HTML5 Drag and Drop
        article&lt;/a&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>Note that this HTML page has two scripts in the <code>&lt;head&gt;</code>:</p>
<ul>
<li><strong><code>EventHelpers.js</code>:</strong> this script implements cross-browser event handling routines without the need for a JavaScript framework.  All the examples in this article use it, but feel free to refactor all the code in this article to use a third party framework like Dojo, jQuery or whatever framework you like.</li>
<li><strong><code>DragDropHelpers.js</code>:</strong> among other things that I will get to later, will activate dragging on <code>draggable="true"</code> objects in Safari and Chrome using a built-in copy of Dean Edwards&#8217; <a href="http://dean.edwards.name/my/cssQuery/">cssQuery</a>.  It does this by inserting the following CSS code into the HTML document:<br />
<blockquote class="code">
<pre>[draggable=true] {
  -khtml-user-drag: element;
  -webkit-user-drag: element;
  -khtml-user-select: none;
  -webkit-user-select: none;
}</pre>
</blockquote>
<p>The first two rules allow the dragging of the <code>draggable="true"</code> nodes, while the last two prevent the user from selecting the text within the node (which can cause some unexpected behavior in Webkit browsers).  The <code>-khtml </code>properties work in older versions of Safari, while <code>-webkit</code> ones work in newer versions.  <strong>Without these CSS properties, these nodes will not be draggable when using the Safari web browser</strong></li>
</ul>
<p><a class="exampleLink" href="/tests/dragAndDrop/01-dragObject.html">See Example  #1: a draggable object</a></p>
<p>A couple of notes:</p>
<ol>
<li> You&#8217;ll notice that when you hover the mouse pointer over the draggable item, it will change to <img class="alignnone size-full wp-image-599" title="The  &quot;Move&quot; cursor" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/cursor-move.gif" alt="The  &quot;Move&quot; cursor" width="24" height="28" />(i.e. I the &#8220;move&#8221; cursor).  This is not the default behavior of the web browser &#8211; it is something I added in <code>DragDropHelpers</code>, since I believe that it&#8217;s a nice visual cue to show users that an object is draggable (if you don&#8217;t want this behavior, it is possible to turn it off in your own scripts by setting <code>DragDropHelpers.showMouseoverCue</code> to false</li>
<li>How draggable objects look in the various browsers varies.  Here are screenshots of how it looks in Windows web browsers (Note: although all screenshots were taken using Windows XP, similar results occur when viewing under Windows Vista or Windows 7):<br />
<table class="screenshots" border="0">
<thead>
<tr>
<th>Firefox (Windows XP)</th>
<th>Safari (Windows XP)</th>
<th>Explorer &amp; Chrome (Windows XP)</th>
</tr>
</thead>
<tbody>
<tr>
<td><img class="alignnone size-full wp-image-514" title="Dragging of a link element, Firefox Windows" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/dragLink-firefoxWindows.png" alt="[Dragging of a link element, Firefox Windows]" width="180" height="190" /></td>
<td><img class="alignnone size-full wp-image-514" title="Dragging of a link element, Safari Windows" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/dragLink-safariWindows.png" alt="[Dragging of a link element, Safari Windows]" width="180" height="190" /></td>
<td><img class="alignnone size-full wp-image-514" title="Dragging of a link element, Explorer Windows" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/dragLink-explorerWindows.png" alt="[Dragging of a link element, Explorer Windows]" width="180" height="190" /></td>
</tr>
</tbody>
</table>
<p>Note the differences between these three browsers:</p>
<ul>
<li>Firefox for Windows shows a cloned version of the draggable object underneath the mouse pointer when the object is being dragged, while Safari displays a grey box with the text &#8220;This is a draggable item&#8221; written inside.  Explorer and Chrome don&#8217;t show any effect at all (We will address this issue later).</li>
<li>Since we have not established <em>where</em> we are going to drag our object, all Windows browsers will change the mouse pointer cursor to <img class="alignnone size-full wp-image-567" title="&quot;Not-Allowed&quot; cursor." src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/cursor_not-allowed.gif" alt="&quot;Not-Allowed&quot; cursor." width="22" height="22" /> (a.k.a. the &#8220;not-allowed&#8221; mouse pointer).  This is the expected behavior, and you will see later that it will help the user know where to drop the object.</li>
</ul>
<p>On OS X, Firefox and Safari look similar to Firefox for Windows, except that the &#8220;not-allowed&#8221; mouse-pointer doesn&#8217;t show up:</p>
<table class="screenshots" border="0">
<thead>
<tr>
<th>Firefox (OS X)</th>
<th>Safari (OS X)</th>
<th>Chrome (OS X)</th>
</tr>
</thead>
<tbody>
<tr>
<td><img class="alignnone size-full wp-image-513" title="Dragging of a link element, Firefox OS X" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/dragLink-firefoxMac.png" alt="[Dragging of a link element, Firefox Windows]" width="180" height="190" /></td>
<td><img class="alignnone size-full wp-image-514" title="Dragging of a link element, Safari OS X" src="http://www.useragentman.com/blog/wp-content/uploads/2010/12/dragLink-safariMac.png" alt="[Dragging of a link element, Safari OS X]" width="180" height="190" /></td>
<td><img class="alignnone size-full wp-image-653" title="Chrome for Mac" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/dragLink-chromeMac.png" alt="Chrome for Mac" width="180" height="190" /></td>
</tr>
</tbody>
</table>
<p>The Linux browsers don&#8217;t have the &#8220;not-allowed&#8221; mouse cursor either.  Also, the cloned version of the draggable object isn&#8217;t transparent using the Linux version of Firefox, and Chrome under Linux behaves  pretty much the  same as on the other platforms (Note: all Linux testing was done using Ubuntu 9.10 using the standard Gnome window manager).</p>
<table class="screenshots" border="0">
<thead>
<tr>
<th>Firefox (Ubuntu)</th>
<th>Chrome (Ubuntu)</th>
</tr>
</thead>
<tbody>
<tr>
<td><img class="size-full wp-image-698 alignnone" title="dragLink-firefoxUbuntu" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/dragLink-firefoxUbuntu.png" alt="Firefox Linux" width="180" height="190" /></td>
<td><img class="size-full wp-image-697 alignnone" title="dragLink-chromeUbuntu" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/dragLink-chromeUbuntu.png" alt="Chrome Linux" width="180" height="190" /></td>
</tr>
</tbody>
</table>
<p>The fact that Explorer and Chrome don&#8217;t have any visual dragging cues bugged me, so I put a &#8220;fix&#8221; inside <code>DragDropHelpers.js</code> which can be turned on by setting <code>DragDropHelpers.fixVisualCues</code> to true.  Let&#8217;s look at a slightly refactored version of Example #1 where we insert the following code in the <code>&lt;head&gt;:</code></p>
<blockquote class="code">
<pre>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
   &lt;head&gt;
      &lt;title&gt;Test #1: A Simple Draggable Object (with visual cues added to Explorer and Chrome)&lt;/title&gt;
      &lt;script type="text/javascript" src="../../shared/js/EventHelpers.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/DragDropHelpers.js"&gt;&lt;/script&gt;
<span class="hilite">      &lt;script type="text/javascript"&gt;
      &lt;!--
      DragDropHelpers.fixVisualCues=true;
      --&gt;
      &lt;/script&gt;</span>

      &lt;link rel="stylesheet" type="text/css" media="screen" href="css/test1.css" /&gt;

   &lt;/head&gt;
   &lt;body&gt;

      &lt;h1&gt;Test #1: A Simple Draggable Object (with visual cues added to Explorer and Chrome)&lt;/h1&gt;

      &lt;a href="#" id="toDrag" draggable="true"&gt;This is a draggable item&lt;/a&gt;

      &lt;p&gt;Try to drag the red box around.  You will see the draggable object cloned in all browsers.&lt;/p&gt;

      &lt;a href="http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/"&gt;Go back to the User Agent Man HTML5 Drag and Drop article&lt;/a&gt;

   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
</li>
</ol>
<p><a class="exampleLink" href="/tests/dragAndDrop/01a-dragObject.html">See Example #1a, a draggable object with visual cue fix for Explorer and Chrome</a></p>
<p>Voila!  The visual cue now shows up.  I&#8217;ll explain how this works at the end of the article.</p>
<h3>Step 2: Setting Events on the Draggable Object</h3>
<p>Now that you have defined an object as draggable, you should attach some events to it so the browser knows what to do while it is being dragged.  There are three events that a draggable object can fire:</p>
<table class="dataTable" border="0">
<thead>
<tr>
<th>Event name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>dragstart</code></td>
<td>Fires when the user starts dragging of the object.</td>
</tr>
<tr>
<td><code>drag</code></td>
<td>Fires every time the mouse is moved while the object is being dragged.</td>
</tr>
<tr>
<td><code>dragend</code></td>
<td>Fires when the user releases the mouse button while dragging an object.</td>
</tr>
</tbody>
</table>
<p>A developer would attach these events the way they would any other JavaScript event &#8211; I use <code>EventHelpers.addEvent</code>, but one could use jQuery&#8217;s <code>bind()</code> method, prototype&#8217;s <code>Event.observe()</code> or whatever you favourite framework provides for event handling.  Developers can also use the old school inline events (i.e. <code>&lt;a href="#" id="toDrag" draggable="true" <span class="hilite">ondragstart="somefunction();"</span>&gt;This is a draggable item&lt;/a&gt;</code>), but I try to stay away from using those to seperate document structure from behavior.</p>
<p>Let&#8217;s take the example in step 1 and change it so we can log when these events happen to the <code>toDrag</code> node:</p>
<blockquote class="code">
<pre>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
   &lt;head&gt;
      &lt;title&gt;Example #2: a draggable object with events attached &lt;/title&gt;
<span class="hilite">      &lt;script type="text/javascript" src="../../shared/js/sprintf.js"&gt;&lt;/script&gt;</span>
      &lt;script type="text/javascript" src="../../shared/js/EventHelpers.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/DragDropHelpers.js"&gt;&lt;/script&gt;

<span class="hilite">      &lt;script type="text/javascript" src="js/02-dragObjectWithEvent.js"&gt;&lt;/script&gt;</span>

      &lt;link rel="stylesheet" type="text/css" media="screen" href="css/test1.css" /&gt;

   &lt;/head&gt;
   &lt;body&gt;

      &lt;h1&gt;Example #2: a draggable object with events attached&lt;/h1&gt;

      &lt;p&gt;Try to drag the red box around.  This page will tell you if the
      object is currently dragging, and will log all &lt;code&gt;dragstart&lt;/code&gt;
      and &lt;code&gt;dragstop&lt;/code&gt; events&lt;/p&gt;

<span class="hilite">      &lt;p&gt;&lt;strong&gt;Is dragging:&lt;/strong&gt; &lt;span id="dragEventNotice"&gt;no&lt;/span&gt;

      &lt;p id="eventLog"&gt;&lt;strong&gt;Event now firing:&lt;/strong&gt;&lt;br /&gt;&lt;span id="eventNotice"&gt;&lt;/span&gt;</span>

      &lt;a class="goBack" href="http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/"&gt;Go back to the User Agent Man HTML5 Drag and Drop article&lt;/a&gt;&lt;/p&gt;

      &lt;a href="#" id="toDrag" draggable="true"&gt;This is a draggable item&lt;/a&gt;

   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>In the <code>02-dragObjectWithEvent.js</code> script, the <code>dragEventNotice</code> node will be used to report whether the user is dragging the object around, and the <code>eventNotice</code> will be used to log what events the user has fired:</p>
<blockquote class="code">
<pre>var dragObject = new function () {
   var me = this;

   var dragNode;
   var eventNoticeNode, dragEventNoticeNode;

   /* runs when the page is loaded */
   me.init = function () {

      if (EventHelpers.hasPageLoadHappened(arguments)) {
         return;
      }   

      /* The node being dragged */
      dragNode=document.getElementById('toDrag');

      /* The nodes that report to the user what is happening to that node*/
      eventNoticeNode = document.getElementById('eventNotice');
      dragEventNoticeNode = document.getElementById('dragEventNotice');

      /* The drag event handlers */
<span class="hilite">      EventHelpers.addEvent(dragNode, 'dragstart', dragStartEvent);
      EventHelpers.addEvent(dragNode, 'drag', dragEvent);
      EventHelpers.addEvent(dragNode, 'dragend', dragEndEvent);</span>
   }

   /*
    * The dragstart event handler logs to the user when the event started.
    */
<span class="hilite">   function dragStartEvent(e) {
      eventNoticeNode.innerHTML =
         sprintf("&lt;strong&gt;%s&lt;/strong&gt;: Drag Event started.&lt;br /&gt;%s",
            new Date(),  eventNoticeNode.innerHTML);</span>
   }

   /*
    * The drag event reports to the user that dragging is on.
    */
<span class="hilite">   function dragEvent(e) {
      dragEventNoticeNode.innerHTML = "Currently dragging.";
   }</span>

   /*
    * The dragend event logs to the user when the event had finished *and*
    * also reports that dragging has now stopped.
    */
<span class="hilite">   function dragEndEvent(e) {
      eventNoticeNode.innerHTML =
         sprintf("&lt;strong&gt;%s&lt;/strong&gt;: Drag Event stopped.&lt;br /&gt;%s",
            new Date(), eventNoticeNode.innerHTML);
      dragEventNoticeNode.innerHTML = "Dragging stopped."
   }
}</span>

// fixes visual cues in IE and Chrome.
DragDropHelpers.fixVisualCues=true;

EventHelpers.addPageLoadEvent('dragObject.init');</pre>
</blockquote>
<p>Before we get to the drag events, a word about the coding conventions I use for this and all the other code examples in this article:</p>
<ul>
<li>the <code>var me = this </code>line ensures that the script doesn&#8217;t confuse the <code>this </code>keyword of the object with the <code>this </code>keyword inside an event handler.</li>
<li><code>EventHelpers.addPageLoadEvent()</code> (which is part of <code>EventHelpers.js</code>) will execute <code>dragObject.init</code> when the HTML has loaded.  <code>addPageLoadEvent()</code> is based on code from Dean Edwards&#8217; article <a href="http://dean.edwards.name/weblog/2005/09/busted/">The window.onload Problem &#8211; Solved!</a>.  It is similar to jQuery&#8217;s<code> $(document).ready()</code>method and prototype&#8217;s <code>dom:loaded</code> event.</li>
<li>This code uses a JavaScript version of <code>sprintf()</code> that <a href="/blog/2009/12/22/my-favourite-third-party-javascript-libraries/">I had mentioned in a previous blog post</a>.  I have used it in all the remaining examples because I think it makes the code a lot easier to read (however, it is not necessary in order to make HTML5 drag and drop work).</li>
</ul>
<p>Let&#8217;s get back to the drag events — you&#8217;ll notice that I have set the <code>dragstart</code>, <code>drag</code> and <code>dragend</code> events.  When this page is loaded, it will tell you if the draggable object is currently being dragged, and will log all <code>dragstart</code> and <code>dragstop</code> events on-screen. Click on the example link below and see for yourself:</p>
<p><a class="exampleLink" href="/tests/dragAndDrop/02-dragObjectWithEvents.html">See Example #2, a draggable object with events attached</a></p>
<h3>Step 3: Setting Events on the Target Object</h3>
<p>Step 2 showed us how we can drag an object around the screen and know when each drag starts and ends.  Now we need to drop the object. Let&#8217;s define a <strong>drop target</strong> to be <strong>an object where draggable objects can be dropped</strong>.  A drop target can have the following event handlers attached to it:</p>
<table class="dataTable" border="0">
<thead>
<tr>
<th>Event name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>dragenter</code></td>
<td>Fires when a draggable object is <strong>first dragged inside</strong> an object.</td>
</tr>
<tr>
<td><code>dragover</code></td>
<td>Fires everytime a draggable object is <strong>moved inside</strong> an object.  <strong>Note: if you want to allow the draggable object to be <em>dropped </em>inside this object, <em>you must cancel the default behaviour of this event handler.</em></strong></td>
</tr>
<tr>
<td><code>dragleave</code></td>
<td>Fires when a draggable object is <strong>dragged out</strong> of an object.</td>
</tr>
<tr>
<td><code>drop</code></td>
<td>Fired when a draggable object is <strong>dropped into</strong> an object.</td>
</tr>
</tbody>
</table>
<p><strong>If you want an object to become a drop target, you must attach both the <code>dragover</code> and <code>drop</code> events to it.</strong> You may ask &#8220;I understand why I need to implement <code>drop</code> (after all, it is one half of the term &#8220;drag and drop&#8221;) but why do I need <code>dragover</code>?&#8221;  <strong>As stated in the table above, the <code>drop</code> event will not fire unless you cancel the default behaviour of the event target&#8217;s <code>dragover</code> event</strong>.  This point is really important and <strong>your scripts will not work correctly unless you do this</strong>.</p>
<p>You may ask &#8220;Why is there even a <code>dragover</code> event in the first place?  Isn&#8217;t <code>drag</code> sufficient?&#8221; (In his article, Peter-Paul Koch <a href="http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html#link8"> asked this question a bit more emphatically that I did</a>).  The <code>dragover</code> event object does contain some useful information, such as <strong>the coordinates of the  mouse pointer inside the event target</strong>, (When I created <code>DragDropHelpers</code>, this information allowed me to fix Explorer and Chrome&#8217;s visual cue issue that I mentioned in step #1).  These coordinates are stored in the properties <code>offsetX</code> and <code>offsetY</code>, <strong>except in Firefox 3.5</strong> which keeps these values inside of the event properties <code>layerX</code> and <code>layerY</code>.  For convenience, <code>DragDropHelpers</code> includes a method called <code>getEventCoords()</code> that will use the appropriate property to get these values (<strong>Note:</strong> <code>layerX</code> and <code>layerY</code> are only accurate when the drop target&#8217;s CSS <code>position</code> propety is set to <code>relative</code>,<code> absolute</code> or <code>fixed</code>).</p>
<p>To show how to add drop functionality to your code, lets take the code from example #2 and add a drop target:</p>
<blockquote class="code">
<pre>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
   &lt;head&gt;
      &lt;title&gt;Example #3: a dragable object with a drop target&lt;/title&gt;
      &lt;script type="text/javascript" src="../../shared/js/sprintf.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/EventHelpers.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/DragDropHelpers.js"&gt;&lt;/script&gt;

<span class="hilite">      &lt;script type="text/javascript" src="js/03-dragObjectWithTargetObject.js"&gt;&lt;/script&gt;</span>

      &lt;link rel="stylesheet" type="text/css" media="screen" href="css/test1.css" /&gt;

   &lt;/head&gt;
   &lt;body&gt;

      &lt;h1&gt;Example #3: a dragable object with a drop target&lt;/h1&gt;

      &lt;p&gt;Try to drag the red box around and dropping it in the target object.&lt;/p&gt;

      &lt;p&gt;&lt;strong&gt;Is dragging:&lt;/strong&gt; &lt;span id="dragEventNotice"&gt;no&lt;/span&gt;

      &lt;p id="eventLog"&gt;&lt;strong&gt;Event now firing:&lt;/strong&gt;&lt;br /&gt;&lt;span id="eventNotice"&gt;&lt;/span&gt;
      &lt;a class="goBack" href="http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/"&gt;Go back to the User Agent Man HTML5 Drag and Drop article&lt;/a&gt;&lt;/p&gt;

      &lt;a href="#" id="toDrag" draggable="true"&gt;This is a draggable item&lt;/a&gt;
<span class="hilite">      &lt;div id="dropTarget"&gt;This is a "target" object&lt;/div&gt;</span>

   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>The drop target will be the <code>&lt;div&gt;</code> with an <code>id</code> of <code>dropTarget</code>.   The <code>03-dragObjectWithTargetObject.js</code> script is the same code in example #2 except we add two event handlers:</p>
<ul>
<li>a <code>dragover</code> event that reports where the mouse is inside <code>dropTarget</code></li>
<li>a <code>drop</code> event that reports when the drop happened.</li>
</ul>
<blockquote class="code">
<pre>var dragObject = new function () {
   var me = this;

   var dragNode, targetNode;
   var eventNoticeNode, dragEventNoticeNode;
   me.init = function () {

   	if (EventHelpers.hasPageLoadHappened(arguments)) {
   		return;
   	}	

   	dragNode=document.getElementById('toDrag');
   	targetNode=document.getElementById('dropTarget');
   	eventNoticeNode = document.getElementById('eventNotice');
   	dragEventNoticeNode = document.getElementById('dragEventNotice');

   	/* These are events for the draggable object */
   	EventHelpers.addEvent(dragNode, 'dragstart', dragStartEvent);
   	EventHelpers.addEvent(dragNode, 'drag', dragEvent);
   	EventHelpers.addEvent(dragNode, 'dragend', dragEndEvent);

   	/* These are events for the object to be dropped */
   	<span class="hilite">EventHelpers.addEvent(targetNode, 'dragover', dragOverEvent);</span>
   	<span class="hilite">EventHelpers.addEvent(targetNode, 'drop', dropEvent);</span>

   }

   function dragStartEvent(e) {
   	showMessage("Drag Event started");
   }

   function dragEvent(e) {
   	dragEventNoticeNode.innerHTML = "Currently dragging.&lt;br /&gt;";
   }

   function dragEndEvent(e) {
   	showMessage("Drag Event stopped");
   	dragEventNoticeNode.innerHTML = "Dragging stopped."
   }

<span class="hilite">   function dragOverEvent(e) {
   	var coords = DragDropHelpers.getEventCoords(e);
   	showMessage(sprintf(
   	   "Drag over event happened on node with id %s at coordinate (%d, %d)",
   	   this.id, coords.x, coords.y));
   	EventHelpers.preventDefault(e);
   }</span>

<span class="hilite">   function dropEvent(e) {
   	showMessage("Drop event happened on node with id " + this.id);
   	EventHelpers.preventDefault(e);
   }</span>

   function showMessage(message) {
   	eventNoticeNode.innerHTML =
   		sprintf("&lt;strong&gt;%s&lt;/strong&gt;: %s&lt;br /&gt;%s",
   			new Date(), message, eventNoticeNode.innerHTML);
   }

}

// fixes visual cues in IE and Chrome.
DragDropHelpers.fixVisualCues=true;

EventHelpers.addPageLoadEvent('dragObject.init');</pre>
</blockquote>
<p>(<strong>Note:</strong> <code>EventHelpers.preventDefault(e)</code> does what you&#8217;d expect: it prevents the default behavior of the event handler, similar to prototype&#8217;s <code>Event.stop()</code> or jQuery&#8217;s <code>event.preventDefault()</code>)</p>
<p><a class="exampleLink" href="/tests/dragAndDrop/03-dragObjectAndTargetObject.html">See Example #3: a dragable object with a drop target</a></p>
<p>Note that in the above example, the time that the draggable object&#8217;s <code>dragend</code> event fires and the time that the drag target&#8217;s <code>drop</code> event fires is not consistant among browsers.  Safari and Chrome fire <code>dragend</code> first, while Firefox and Internet Explorer fire <code>drop</code> first.</p>
<p>The two other drop target events, <code>dragenter</code> and <code>dragleave</code> are not absolutely necessary for every script, but let&#8217;s add these events to example #3 anyway to see how they work:</p>
<blockquote class="code">
<pre>var dragObject = new function () {
   var me = this;

   var dragNode, targetNode;
   var eventNoticeNode, dragEventNoticeNode;
   me.init = function () {

      if (EventHelpers.hasPageLoadHappened(arguments)) {
         return;
      }   

      dragNode=document.getElementById('toDrag');
      targetNode=document.getElementById('dropTarget');
      eventNoticeNode = document.getElementById('eventNotice');
      dragEventNoticeNode = document.getElementById('dragEventNotice');

      /* These are events for the draggable object */
      EventHelpers.addEvent(dragNode, 'dragstart', dragStartEvent);
      EventHelpers.addEvent(dragNode, 'drag', dragEvent);
      EventHelpers.addEvent(dragNode, 'dragend', dragEndEvent);

      /* These are events for the object to be dropped */
      EventHelpers.addEvent(targetNode, 'dragover', dragOverEvent);
      EventHelpers.addEvent(targetNode, 'drop', dropEvent);
<span class="hilite">      EventHelpers.addEvent(targetNode, 'dragenter', dragEnterEvent);
      EventHelpers.addEvent(targetNode, 'dragleave', dragLeaveEvent);</span>
   }

   function dragStartEvent(e) {
      showMessage("Drag Event started");
   }

   function dragEvent(e) {
      dragEventNoticeNode.innerHTML = "Currently dragging.&lt;br /&gt;";
   }

   function dragEndEvent(e) {
      showMessage("Drag Event stopped");
      dragEventNoticeNode.innerHTML = "Dragging stopped.";
   }

   function dragOverEvent(e) {
      var coords = DragDropHelpers.getEventCoords(e);

      showMessage(sprintf(
         "Drag over event happened on node with id %s at coordinate (%d, %d)",
         this.id, coords.x, coords.y));

      EventHelpers.preventDefault(e);
   }

   function dropEvent(e) {
      showMessage("Drop event happened on node with id " + this.id);
      EventHelpers.preventDefault(e);

   }

<span class="hilite">   function dragEnterEvent(e) {
      showMessage("Drag Enter event happened on node with id " + this.id);
   }

   function dragLeaveEvent(e) {
      showMessage("Drag Leave event happened on node with id " + this.id);
   }</span>

   function showMessage(message) {
      eventNoticeNode.innerHTML =
         sprintf("&lt;strong&gt;%s&lt;/strong&gt;: %s&lt;br /&gt;%s",
            new Date(), message, eventNoticeNode.innerHTML);
   }

}

// fixes visual cues in IE and Chrome.
DragDropHelpers.fixVisualCues=true;

EventHelpers.addPageLoadEvent('dragObject.init');</pre>
</blockquote>
<p><a class="exampleLink" href="/tests/dragAndDrop/03a-dragEnterDragLeave.html">See Example #3a: a drop target with dragenter and dragleave event handlers</a></p>
<p>(Note that in Firefox 3.5, a <code>dragleave</code> event will fire just before a <code>drop</code> event, which the other browsers don&#8217;t fire <code>dragleave</code> when dropping).</p>
<h3>Step 4: Passing Data Between the Draggable and Target Objects</h3>
<p>Once a draggable object is dropped into a drop target, the two objects can pass information between them using the drop event&#8217;s <code>dataTransfer</code> property.  This property has two methods, <code>setData()</code> and <code>getData()</code>.  In order to pass data between the two, a developer must use <code>setData()</code> during one of the draggable node&#8217;s drag events (e.g. <code>dragstart</code>).  The drop target can then receive this data during one of it&#8217;s events using the <code>getData()</code> method.</p>
<table class="dataTable" border="0">
<thead>
<tr>
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="methodName"><code>setData(dataType, data)</code></td>
<td>
<p>Sets the data that can be shared between the draggable node and the drag target.</p>
<p><strong>Parameters</strong></p>
<ul>
<li><code>dataType</code> &#8211; The type of data that is to be set.  So far, the only cross-browser dataTypes that can be set are &#8216;Text&#8217; and &#8216;Url&#8217;.</li>
<li><code>data</code> &#8211; The data that is going to be set.</li>
</ul>
</td>
</tr>
<tr>
<td class="methodName"><code>getData(dataType)</code></td>
<td>
<p>Gets the data that was previously set by <code>dataTransfer.setData()</code>.  <strong>It can also get data that was set by a <code>dataTransfer.setData()</code> call from another page, another browser window, and <em>another vendor&#8217;s web browser on the same machine</em>.</strong> It also can get data that was set by a drop event of another desktop application (for example, Windows WordPad).</p>
<p><strong>Parameters</strong></p>
<ul>
<li><code>dataType</code> &#8211; The type of data that is to be set.  So far, the only cross-browser dataTypes that can be set are &#8216;Text&#8217; and &#8216;Url&#8217;.</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p><code>setData()</code> takes one string parameter, which is the data you want to share between the draggable object and a drop target.</p>
<p>Let&#8217;s take the code from step #3 and mix it up a bit: instead of having one draggable object, let&#8217;s make four.  I have taken <a href="http://commons.wikimedia.org/wiki/File:The_Fabs.JPG">four photos of the Beatles from the Wikmedia Commons</a> and made them draggable.</p>
<blockquote class="code">
<pre>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
   &lt;head&gt;
      &lt;title&gt;Test 4: setData() and getData()&lt;/title&gt;
      &lt;script type="text/javascript" src="../../shared/js/sprintf.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/helpers.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="../../shared/js/DragDropHelpers.js"&gt;&lt;/script&gt;

<span class="hilite">      &lt;script type="text/javascript" src="js/04-setDataGetData.js"&gt;&lt;/script&gt;</span>

      &lt;link rel="stylesheet" type="text/css" media="screen" href="css/test1.css" /&gt;

   &lt;/head&gt;
   &lt;body&gt;

      &lt;h1&gt;Test 4: &lt;code&gt;setData()&lt;/code&gt; and &lt;code&gt;getData()&lt;/code&gt;&lt;/h1&gt;

<span class="hilite">      &lt;img draggable="true" src="images/george.png" alt="George Harrison" /&gt;
      &lt;img draggable="true" src="images/john.png" alt="John Lennon" /&gt;
      &lt;img draggable="true" src="images/paul.png" alt="Paul McCartney" /&gt;
      &lt;img draggable="true" src="images/ringo.png" alt="Ringo Starr" /&gt;</span>

      &lt;div id="dropTarget"&gt;&lt;span&gt;Drop an image here to find out more information about it.&lt;/span&gt;&lt;/div&gt;

   &lt;/body&gt;
&lt;/html&gt;</pre>
</blockquote>
<p>The script <code>04-setDataGetData.js</code> uses <code>dataTransfer.setData()</code> and <code>.getData()</code> to copy the <code>&lt;img&gt;</code> of the Beatle being dragged, as well as placing the <code>alt</code> attribute&#8217;s contents underneath the image.</p>
<blockquote class="code">
<pre>var dragObject = new function () {
   var me = this;

   var targetNode;
   var eventNoticeNode, dragEventNoticeNode;

   var dataTransferCommentString;

   me.init = function () {

      if (EventHelpers.hasPageLoadHappened(arguments)) {
         return;
      }   

      targetNode=document.getElementById('dropTarget');
      eventNoticeNode = document.getElementById('eventNotice');
      dragEventNoticeNode = document.getElementById('dragEventNotice');

      /* These are events for the draggable objects */
      var dragNodes = cssQuery('[draggable=true]');
      for (var i = 0; i &lt; dragNodes.length; i++) {
         var  dragNode=dragNodes[i]
         EventHelpers.addEvent(dragNode, 'dragstart', dragStartEvent);
      }

      /* These are events for the object to be dropped */
      EventHelpers.addEvent(targetNode, 'dragover', dragOverEvent);
      EventHelpers.addEvent(targetNode, 'drop', dropEvent);
   }

   function dragStartEvent(e) {
<span class="hilite">      e.dataTransfer.setData('Text',
         sprintf('&lt;img src="%s" alt="%s" /&gt;&lt;br /&gt;&lt;p class="caption"&gt;%s&lt;/p&gt;',
            this.src, this.alt, this.alt
         )
      );</span>
   }

   function dragOverEvent(e) {
      EventHelpers.preventDefault(e);
   }

   function dropEvent(e) {
<span class="hilite">      this.innerHTML = e.dataTransfer.getData('Text');</span>
      EventHelpers.preventDefault(e);
   }

}

// fixes visual cues in IE and Chrome.
DragDropHelpers.fixVisualCues=true;

EventHelpers.addPageLoadEvent('dragObject.init');</pre>
</blockquote>
<p><a class="exampleLink" href="/tests/dragAndDrop/04-setDataGetData.html">See Example #4: using setData() and getData()</a></p>
<p>As previously mentioned the data that is set in setData() can be read in other applications.  If you are in Windows, open up WordPad and drag one of the images into it.  You&#8217;ll see the data that was given to setData() during the dragstart event.</p>
<p>This interoperability with the operating system will allow developers to do some very interesting things which are out of the scope of this article.  I will, however, want to explore this in future postings.</p>
<h3>Step 5: Drag  and  Drop Effects</h3>
<p>In a traditional desktop application, you can use drag and drop to copy objects, move objects, and create links to things.  You can use the HTML5 drag and drop events to do this as well, but it would be nice to give the user visual cues to show what kind of action a draggable object can do, and what kind of action a drop target can accept.  It would also be nice to only allow &#8220;copy objects&#8221; to only drop on drop targets that are programmed to accept them.</p>
<p>These features can be implemented using <code>e.dataTransfer.effectAllowed</code> on the draggable object and <code>e.dataTransfer.dropEffect()</code>on the drop target:</p>
<table class="dataTable" border="0">
<thead>
<tr>
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>e.dataTransfer.effectAllowed</code></td>
<td>Sets the type of effect a draggable object is allowed to make.  Valid values are  <code>copy</code>, <code>move</code>, <code>link</code>, <code>copyMove</code>, <code>copyLink</code>, <code>linkMove</code>, <code>all</code>, and <code>none</code>.</td>
</tr>
<tr>
<td><code>e.dataTransfer.dropEffect</code></td>
<td>Sets the type of effect a drop target is allowed to accept.  Valid effects include <code>copy</code>, <code>move</code>, and <code>link</code>.</td>
</tr>
</tbody>
</table>
<p>When these are set correctly, drag and drop will only work when the draggable object&#8217;s <code>effectAllowed</code> and the drop target&#8217;s <code>dropEffect</code> are compatible.  To illustrate this, let&#8217;s first change the <code>dragstart</code> and <code>dragover</code> events in example #4 to do the <code>copy</code> effect:</p>
<blockquote class="code">
<pre>   function dragStartEvent(e) {
<span class="hilite">      e.dataTransfer.effectAllowed="copy";</span> 

      e.dataTransfer.setData('Text',
         sprintf('&lt;img src="%s" alt="%s" /&gt;&lt;br /&gt;&lt;p class="caption"&gt;%s&lt;/p&gt;',
            this.src, this.alt, this.alt
         )
      );
   }

   function dragOverEvent(e) {
<span class="hilite">      e.dataTransfer.dropEffect = "copy";</span>
      EventHelpers.preventDefault(e);
   }</pre>
</blockquote>
<p><a class="exampleLink" href="/tests/dragAndDrop/05-dataTransfer.html">Example #5: matching drag and drop effects</a></p>
<p>Note that unlike <a href="/tests/dragAndDrop/04-setDataGetData.html">example #4</a>, the mouse pointer has changed from the copy icon (in Windows, <img class="alignnone size-full wp-image-616" title="Windows Copy Icon" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/copyWindows.gif" alt="[Windows Copy Icon]" width="23" height="32" />) to the move icon (<img class="alignnone size-full wp-image-615" title="Windows Move Icon" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/moveWindows.gif" alt="[Windows Move Icon]" width="13" height="27" />).</p>
<p>Now let&#8217;s change the code so that the draggable object and the drop target don&#8217;t have matching effects:</p>
<blockquote class="code">
<pre>   function dragStartEvent(e) {
<span class="hilite">      e.dataTransfer.effectAllowed="copy";</span> 

      e.dataTransfer.setData('Text',
         sprintf('&lt;img src="%s" alt="%s" /&gt;&lt;br /&gt;&lt;p class="caption"&gt;%s&lt;/p&gt;',
            this.src, this.alt, this.alt
         )
      );
   }

   function dragOverEvent(e) {
<span class="hilite">      e.dataTransfer.dropEffect = "move";</span>
      EventHelpers.preventDefault(e);
   }</pre>
</blockquote>
<p><a class="exampleLink" href="/tests/dragAndDrop/05a-dataTransferNoMatch.html">See Example #5a: unmatching drag and drop effects</a></p>
<p>You&#8217;ll see that the user is not able to drop the image on the drop target.</p>
<p><strong>Update (Jan 28, 2010):</strong>  There is a documented bug in Safari and Chrome for Windows where <a href="http://code.google.com/p/chromium/issues/detail?id=14654">drag and drop will not occur if <code>effectAllowed</code> and <code>dropEffect</code> are set to <code>move</code></a>.  This bug does not occur in the Mac editions of these browsers.  </p>
</div>
<h2>A More Complex Example</h2>
<p>Let&#8217;s take all the information we have gathered and make a &#8220;real-world&#8221; script. Let&#8217;s say you were asked to create a &#8220;user entitlement&#8221; administration widget for a website.  The widget will have three entitlement catagories: &#8220;Unassigned Users&#8221;, &#8220;Restricted Users&#8221; (e.g. users who have restricted access to the website) and &#8220;Power Users&#8221; (e.g. users who would have administration access to a website):</p>
<div id="attachment_684" class="wp-caption aligncenter" style="width: 403px"><img class="size-full wp-image-684" title="permissionFormScreenshot" src="http://www.useragentman.com/blog/wp-content/uploads/2010/01/permissionFormScreenshot1.png" alt="Screenshot of the user entitlement screen we want to implement" width="393" height="185" /><p class="wp-caption-text">Screenshot of the user entitlement screen we want to implement</p></div>
<p>It should be rather easy for an administrator to drag and drop users back and forth between entitlement &#8220;buckets&#8221; in order to elevate or lower a users credentials.</p>
<p>Let&#8217;s go through the steps we established above to implement this script.</p>
<div class="steps">
<h3>Step 1: Defining a Draggable Objects</h3>
<p>First let&#8217;s take a look at the table in the HTML:</p>
<blockquote class="code">
<pre>&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Unassigned Users&lt;/th&gt;
            &lt;th&gt;Restricted Users&lt;/th&gt;
            &lt;th&gt;Power Users&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td id="unassignedUsers"&gt;
            	&lt;a href="#" draggable="true"&gt;Moe Howard&lt;/a&gt;
		&lt;a href="#" draggable="true"&gt;Curly Howard&lt;/a&gt;
		&lt;a href="#" draggable="true"&gt;Shemp Howard&lt;/a&gt;
            	&lt;a href="#" draggable="true"&gt;Larry Fine&lt;/a&gt;
	    &lt;/td&gt;

            &lt;td id="restrictedUsers"&gt;
            &lt;/td&gt;

            &lt;td id="powerUsers"&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;tfoot&gt;
	&lt;td id="unassignedUsersHelp"&gt;
	  Drag a user from this list to another list to change the
	  user's permissions.
	&lt;/td&gt;
	&lt;td id="restrictedUsersHelp"&gt;
	  Dragging user here will give this user restricted
	  permissions.
	&lt;/td&gt;
	&lt;td id="powerUsersHelp" &gt;
	  Dragging a user here will give this user power user access.
	&lt;/td&gt;
    &lt;/tfoot&gt;
&lt;/table&gt;</pre>
</blockquote>
<p>(Note that the contents in the <code>tfoot</code> node are hidden by CSS).</p>
<h3>Step 2: Setting Events on the Draggable Objects</h3>
<p>The &#8220;users&#8221; are draggable objects.  In the script, we find all these nodes using Dean Edwards&#8217; <a href="http://dean.edwards.name/my/cssQuery/">cssQuery</a> and  set <code>dragstart</code> and <code>dragend</code> event handlers on each of them (Note: cssQuery allows us to select nodes by CSS selector, similar to the built-in functionality inside jQuery).</p>
<blockquote class="code">
<pre>userNodes = cssQuery('[draggable=true]');
for (var i=0; i&lt;userNodes.length; i++) {
   EventHelpers.addEvent(userNodes[i], 'dragstart', userDragStartEvent);
   EventHelpers.addEvent(userNodes[i], 'dragend', userDragEndEvent);
}</pre>
</blockquote>
<p>It then keeps track of the current node being dragged in the object variable <code>currentlyDraggedNode</code> and makes that node transparent by making it a member of the <code>draggedUser</code> class, which the page&#8217;s stylesheet defines as transparent.</p>
<blockquote class="code">
<pre>function userDragStartEvent(e) {
   currentlyDraggedNode = this;
   currentlyDraggedNode.className = 'draggedUser';
}</pre>
</blockquote>
<p>The <code>dragend</code> event removes the transparency of the <code>currentlyDraggedNode</code>:</p>
<blockquote class="code">
<pre>function userDragEndEvent(e) {
   currentlyDraggedNode.className = '';
}</pre>
</blockquote>
<h3>Step 3: Setting Events on the Target Objects</h3>
<p>All the table cells in the <code>&lt;tbody&gt;</code> are drop targets, so we use cssQuery again to grab all those nodes and set the appropriate events.</p>
<blockquote class="code">
<pre>userListNodes = cssQuery('.userList');

for (var i=0; i&lt;userListNodes.length; i++) {
   var userListNode = userListNodes[i];
   EventHelpers.addEvent(userListNode, 'dragover', cancel);
   EventHelpers.addEvent(userListNode, 'dragleave', userDragLeaveListEvent);
   EventHelpers.addEvent(userListNode, 'drop', userDropListEvent);
   EventHelpers.addEvent(userListNode, 'dragenter', userDragOverListEvent);
}</pre>
</blockquote>
<p>The most important event is the <code>drop</code> event handler.  This event handler takes the <code>currentlyDraggedNode</code>, removes it from its current table cell (using <code>removeChild()</code>) and  drops it into the drop target (using <code>appendChild()</code>).</p>
<blockquote class="code">
<pre>function setHelpVisibility(node, isVisible) {
   var helpNodeId = node.id + "Help";
   var helpNode = document.getElementById(helpNodeId);

   if (isVisible) {
      helpNode.className =  'showHelp';
   } else {
      helpNode.className =  '';
   }
}

function userDropListEvent(e) {
   currentlyDraggedNode.parentNode.removeChild(currentlyDraggedNode);
   this.appendChild(currentlyDraggedNode);
   setHelpVisibility(this, false);
   userDragEndEvent(e);
}</pre>
</blockquote>
<p>They show the contents of the table cell below it by making it a member of the class <code>showHelp</code>.  They also</p>
<p>prevent the <code>dragover</code> default behaviour so that <code>drop</code> events will fire in the drop target.</p>
<blockquote class="code">
<pre>function userDragOverListEvent(e) {
   setHelpVisibility(this, true);
   EventHelpers.preventDefault(e);
}</pre>
</blockquote>
<p>The <code>dragleave</code> re-hides the contents of the table cell below it.</p>
<blockquote class="code">
<pre>function userDragLeaveListEvent(e) {
  setHelpVisibility(this, false);
}</pre>
</blockquote>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 4921px; width: 1px; height: 1px;">
<pre>function userDragEndEvent(e) {
   currentlyDraggedNode.className = '';
}</pre>
</div>
<h3>Steps 4 and 5</h3>
<p>We do not actually pass any data between the draggable object and the drag target — when the <code>drop</code> event occurs, the draggable object is moved from one column to another without the need of any <code>dataTransfer</code> data.  The drag and drop effects were already handled in step 3, so we are all done.</p>
<p><a class="exampleLink" href="/tests/dragAndDrop/permissionForm.html">See the above example in action</a></p>
</div>
<h2>Drag and Drop Between Frames</h2>
<p>Using the above information, it is also possible to drag and drop objects between frames (this is something that I don&#8217;t think any old school drag and drop script can do).  I made an example below, and I leave it as an exercise to the reader to go through the code and figure out how it works.</p>
<p><a class="exampleLink" href="/tests/dragAndDrop/05a-crossFrameSetData/">See the inter-frame drag and drop example in action</a></p>
<h2>Cross-Browser Issues I Have Seen</h2>
<p>These are the cross-browser issues I know of so far.  I will update this list with others I find in the future.</p>
<ul>
<li>in Firefox 3.5, a <code>dragleave</code> event will fire just before a <code>drop</code> event, which the other browsers don’t fire <code>dragleave</code> when dropping.</li>
<li>the time that the draggable object’s <code>dragend</code> event fires and the time that the drag target’s <code>drop</code> event fires is not consistant among browsers. Safari and Chrome fire <code>dragend</code> first, while Firefox and Internet Explorer fire <code>drop</code> first.</li>
<li>According to <a href="http://www.alertdebugging.com/drag-and-drop-bugs/">Francisco Tolmasky</a>, <a href="http://www.alertdebugging.com/drag-and-drop-bugs/"><code>setData()</code> cannot be called during drag events in Firefox</a>.  Hopefully this will be fixed in a future release of the browser.</li>
<li><code>DragDropHelpers</code> implements a workaround for Explorer so it can drag <em>any</em> object around. However, I did not use this functionality in any of the examples because it exposes a problem with <a href="http://lists.apple.com/archives/web-dev/2009/Jul/msg00042.html">Safari not being able to drag an object correctly when the user initiates the drag on the text inside it</a>.  This problem doesn&#8217;t happen with text inside of links, but with text inside other nodes (like a <code>&lt;div&gt;</code> tag).  I understand this problem has been fixed in the Safari nightly builds, so I left the functionality in the DragDropHelpers library for future use.</li>
<li>DragDropHelpers.js &#8220;fixes&#8221; the dragging visual cues in Explorer and Chrome by:
<ul>
<li>making a transparent and absolutely positioned clone of a draggable object when it&#8217;s <code>dragstart</code> event is fired</li>
<li>moving the cloned object near the mouse when the <code>&lt;body&gt;</code>&#8217;s <code>drag</code> event is fired.</li>
<li>destroying the clone when draggable object&#8217;s <code>dragend</code> event is fired.</li>
</ul>
<p>I didn&#8217;t turn it on by default because I am not sure when (or if) this problem will be fixed in Internet Explorer or Chrome.  I also doesn&#8217;t work well when dragging objects from one window or frame to another, since the cloned visual cue can&#8217;t jump from page to page.  Feel free to use it (or not) as you see fit.</li>
<li>As mentioned previously, because of a <a href="http://code.google.com/p/chromium/issues/detail?id=14654">bug in Webkit</a>, drag and drop will not occur if <code>effectAllowed</code> and <code>dropEffect</code>  are set to <code>move</code> in Safari 4.0.4.  Hopefully this will be fixed in a future version of Webkit.</li>
</ul>
<h2>Conclusion</h2>
<p>HTML5 drag and drop will be an important part of our front-end toolkit.  Even though the flavors that browser-vendors offer today are incomplete, it is possible to smooth out these flaws to produce useful web applications.  What I have covered here only scratches the surface &#8211; there are more properties and methods that some of browsers offer that can be used to further enhance the drag and drop experience.   But I have been working on this blog entry way to long, and my wife is giving me that &#8220;what the hell are you doing up at this hour&#8221; look, so I think I&#8217;ll stop here for now.</p>
<h2>Download</h2>
<p><code>DragDropHelpers</code>, and all code used in this article can be downloaded below.</p>
<p><a class="exampleLink" href="/downloads/DragDropHelpers-1.0a.zip">DragDropHelpers.js v.1.0a and sample code.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>My Favourite Third Party JavaScript Libraries</title>
		<link>http://www.useragentman.com/blog/2009/12/22/my-favourite-third-party-javascript-libraries/</link>
		<comments>http://www.useragentman.com/blog/2009/12/22/my-favourite-third-party-javascript-libraries/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 22:15:23 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=433</guid>
		<description><![CDATA[
Blogging has been a powerful tool for me to publicize code that I have written.  Not only can I announce code that I want to release, I am always complimented by the fact that others like to share what they read here as well. Over the years, however, I have found bits of code others [...]]]></description>
			<content:encoded><![CDATA[<div>
<div id="attachment_453" class="wp-caption alignleft" style="width: 260px"><img class="size-full wp-image-453" title="JavaScript" src="http://www.useragentman.com/blog/wp-content/uploads/2009/12/JavaScript.png" alt="&lt;span&gt;Source: remix of images created by &lt;a href=" width="250" height="188" /><p class="wp-caption-text">Source: remix of images created by Everaldo Coelho and Wikimedia Commons user S.Möller.</p></div>
<p>Blogging has been a powerful tool for me to publicize code that I have written.  Not only can I announce code that I want to release, I am always complimented by the fact that <strong>others like to share what they read here as well. </strong>Over the years, however, I have found bits of code others have written that have found irreplaceable in my web developer toolkit.  Some of them are popular, but others are either obscure or not talked about at all.  In order to give back to those who have unknowingly helped me do my job in the last decade, I am publishing the first in what hope is a series of articles about 3rd party JavaScript libraries.  If anyone else would like to add to this list, please feel free to do so in the comment area below &#8211; I&#8217;d love to hear what others find as useful as what I have listed here.</p>
<h2>Object Oriented Timeouts</h2>
<p>I start off with a script that has been around for a while but to my knowledge is hardly ever talked about.   It concerns <a title="&quot;Tutorial: JavaScript Timers with setTimeout and setInterval&quot; from elated.com" href="http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/">Timeouts</a> &#8211; which are quite important in this             day-and-age of the  			&#8220;nifty-Web-2.0-animated-fade-in-and-out-effect&#8221;. When I             starting coding JavaScript back in the mid-1990&#8217;s, <code>setTimeout()</code> and             <code>setInterval()</code> did what I needed them to do &#8211; pause the application logic for a specified amount of time. However, when I starting to use the object-oriented features of JavaScript,  			I found a few problems:</p>
<ul>
<li><code>setTimeout()</code>and <code>setInterval()</code> both lose track of scope                 when calling a method of an object</li>
<li><code>setTimeout()</code>and <code>setInterval()</code> can only pass strings                 and numbers to methods, <strong>not</strong> an                 arbitrary object.</li>
<li>the function call passed to <code>setTimeout()</code>and <code>setInterval()</code>is passed as a string.   Parameters of the function call must be inserted by using ugly string concatenation:</li>
</ul>
<blockquote class="code">
<pre>setTimeout('fadeInLayer(' + (n+50).toString() +')');</pre>
</blockquote>
<p>However, <strong>back in 2003</strong>, a user named             “algorithm” on <a href="http://www.codingforums.com/">Coding Forums</a> came up             with a great solution for <a href="http://www.codingforums.com/archive/index.php/t-10531.html"> Object Oriented Timeouts</a>. Timeouts can now be done             with objects and with a more elegant syntax:</p>
<blockquote class="code">
<pre>function AjaxDialogue() {
   var me = this;

   // declaration of Timer object.
   me.timer = new Timer(me);

   // a timeout function using the Timer object:
   me.fadeInLayer = function (n, layerOpened, onFadeInEvent){

      ....

      /*
       * This call will set the opacity level of the node layeredOpened to n
       * percent
       */
      CSSHelpers.setOpacity(layerOpened, n);

      if (n &lt; 100) {

         /*
          * setting a timeout of 10 milliseconds on the *public* method fadeInLayer() with the
          * parameters n+50, layerOpened, and onFadeInEvent.  Note only the first parameter
          * is not an object.
          */
         me.timer.setTimeout('fadeInLayer', 10, n+50, layerOpened, onFadeInEvent);

      }
   }
}</pre>
</blockquote>
<p>The question is: <strong>who <em>is</em> this &#8220;algorithm&#8221; person?</strong> This is brilliant code and should be credited             correctly.  It should also have a better home than just a forum  			posting.</p>
<h2>Calendar Widget</h2>
<p><a href="http://en.wikipedia.org/wiki/HTML5">HTML5</a> will have date input tags (i.e. <code>&lt;input type="date"             /&gt;</code>), complete will pop-up calendars, but until it is implemented by all browser vendors,             what is a developer to do when they want users to input             dates in a user friendly way? The best calendar widget I have found is <a href="http://www.dynarch.com/projects/calendar/old/">dynarch.com&#8217;s             Ex-“Coolest” DHTML Calendar</a>. Although             they have a <a href="http://localhost/bin/myTemplate.cgi/%3Cbr%20/%3E%20http://www.dynarch.com/projects/calendar/"> cooler version</a>, I like the former one more because             it was released under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser             Public License</a>, so it is free as in beer as well as             in freedom.</p>
<h2>Querystring Parsing and Ajax Form Data             Submission</h2>
<p>I always found it odd that there is no built-in method in             JavaScriptto <strong>grab </strong> <strong>form data from the query string from a web page&#8217;s URL.</strong> <a href="http://adamv.com/dev/javascript/querystring">Adam             Vandenberg&#8217;s Querystring Object</a> filled in this gap with a simple 			script that gets this job done.  Suppose your web page had the following 			URL:</p>
<blockquote class="shell">
<pre>http://me.com/mypage.html?page=3&amp;itemsPerPage=10&amp;query=Biker+Babes</pre>
</blockquote>
<p>To tell JavaScript to retrieve the value inside the CGI variable 			<code>query</code>, use the following code:</p>
<blockquote class="code">
<pre>var qs = new Querystring();
var message = qs.get('query');</pre>
</blockquote>
<p>But how about if you have <strong>data in a  			form and you want to  			submit it using Ajax</strong> instead of the traditional  			post-to-the-server-and-retrieve-from-the-server way?  Matthew Eernisse&#8217;s             <a href="http://localhost/bin/myTemplate.cgi/thirdParty.html?templateRoot=useragentman">formData2QueryString()</a> will construct a query string 			from a form so you can use with the XMLHttpRequest Object.</p>
<blockquote class="code">
<pre>var queryString = formData2QueryString(form);

req=new new XMLHttpRequest();

req.onreadystatechange(myFunc);

req.open("GET", "/path/to/ajaxCall?" + queryString, true);</pre>
</blockquote>
<h2>Logging</h2>
<p>In any language, logging and debugging are necessary when it comes to  			discovering what is wrong with your code.  While debuggers like  			<a href="http://localhost/bin/myTemplate.cgi/thirdParty.html?templateRoot=useragentman#">Firebug</a> are great for stepping into code line by 			line and understanding why an algorithm isn&#8217;t working right, it is  			sometimes more desirable to dump variables into a log, especially when trying to debug <a href="http://www.the-art-of-web.com/javascript/ajax-race-condition/">race conditions</a>.  Logging is also useful when you are too lazy to open a debugger but you don&#8217;t want your code bogged down by <code>window.alert()</code>&#8217;s</p>
<p>My favourite 			JavaScript logger is <a href="http://earthcode.com/blog/2005/12/jslog.html">Andre             Lewis&#8217; JSLog</a> . It doesn&#8217;t rely on a specific             JavaScript framework, and it also stays out of the way until I need it  			— it starts off as a             small yellow box in the top left corner of the             application&#8217;s page, and only shows up when I click on it.</p>
<h2>Ajax History and Bookmarking</h2>
<p>After Google Maps came on the scene, a few usability experts pointed out the drawbacks of a lot of &#8220;Ajax&#8221; Applications:</p>
<ul>
<li><strong>Ajax breaks bookmarking: </strong>when users click on a link that results in an Ajax call that changes the content on the screen, users may wish to bookmark the results, and will be disappointed to realize that they didn&#8217;t really bookmark the result of the Ajax call.</li>
<li><strong>Ajax breaks browser history: </strong>when users click on a link that results in an Ajax call that changes the content on the screen, they may intuitively click the back button in order return to the page&#8217;s state, ande will be frustrated when this doesn&#8217;t happen.</li>
</ul>
<p><a href="http://code.google.com/p/reallysimplehistory/">Really             Simple History (RSH): Ajax history and bookmarking             library</a>, developed by <a href="http://codinginparadise.org/">Brad Neuberg</a> and <a href="http://www.briandillard.com/">Brian             Dillard</a>, fixes these issues by storing data inside an JavaScript &#8220;cache&#8221; so that application state can be bookmarked and so that the back button can be used to return your application to an earlier state.  I have used this library on a number of Ajax heavy applications and it works extremely well.</p>
<h2>Fixing IE</h2>
<p>Although <a href="http://dean.edwards.name/IE7/">Dean             Edwards&#8217; /ie7/</a> is not perfect, it does fix a lot of CSS issues with elderly versions of IE.  I use it as one of many utilities in my toolbox when working with Internet Explorer.  It is an awesome piece of work and since Edwards is well known in the JavaScript community, the only thing I can really add that hasn&#8217;t been said before is &#8220;<a href="http://vids.myspace.com/index.cfm?fuseaction=vids.individual&amp;videoid=1276185">Rispek</a>&#8220;.</p>
<h2>sprintf()</h2>
<p>I started off as a C programmer, and when I first started coding in JavaScript, I was happy with it&#8217;s &#8220;C-like&#8221; syntax.  The thing I missed most from the C-world was (and is) JavaScript&#8217;s lack of a <a href="http://en.wikipedia.org/wiki/Printf"><code>sprintf()</code> function</a>, which makes the task of formatting strings quite easy.  <code>sprintf()</code> is more powerful and             produces more human-legable code than using the <code>+</code> JavaScript&#8217;s operator.</p>
<p><a href="http://www.klproductions.com/">K&amp;L             Productions</a> has produced a very good version <a href="http://omino.com/sw/ominoAdobeScriptsSuite/shared/sprintf.jsx"> JavaScript implementation of sprintf</a> that I use             regularly. There are others, but this one is the most complete version 			I have found and works well enough that I haven&#8217;t found a reason to  			change it. Perhaps it would be worthy  			of a future blog post to compare implementations to see which             performs the best.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/12/22/my-favourite-third-party-javascript-libraries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing: The Type Rendering Project</title>
		<link>http://www.useragentman.com/blog/2009/11/30/introducing-the-type-rendering-project/</link>
		<comments>http://www.useragentman.com/blog/2009/11/30/introducing-the-type-rendering-project/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 17:05:58 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=412</guid>
		<description><![CDATA[Although this blog wasn&#8217;t meant to be a forum on just CSS font-embedding, it is a topic of great interest to me and has been the inspiration of a few articles here (my article on JavaScript font-smoothing detection being the latest).  As a result, I have been very fortunate in meeting a lot of [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_416" class="wp-caption alignleft" style="width: 260px"><img class="size-medium wp-image-416 " title="Type Rendering Project Logo" src="http://www.useragentman.com/blog/wp-content/uploads/2009/11/r-300x300.png" alt="Type Rendering Project Logo" width="250" height="250" /><p class="wp-caption-text"><span></span></p></div>
<p>Although this blog wasn&#8217;t meant to be a forum on <em>just</em> CSS font-embedding, it is a topic of great interest to me and has been the inspiration of a few articles here (my article on <a href="/blog/2009/11/29/how-to-detect-font-smoothing-using-javascript/">JavaScript font-smoothing detection</a> being the latest).  As a result, I have been very fortunate in meeting a lot of interesting and like-minded individuals who want to make the web a better place for typography.</p>
<p>One of the more vocal ones, <a href="http://paulirish.com/">Paul Irish</a>, asked me to join a project that will allow developers to <strong>find ways to make web type look better <em>right now</em></strong>.  Other members include web font blogger Tim Brown of <a href="http://www.nicewebtype.com/">Nice Web Type</a> and Ethan Dunham of the excellent font resource <a href="http://fontsquirrel.com/">Font Squirrel</a>.  The result is <a href="http://typerendering.com/">The Type Rendering Project</a> &#8211; we’ve set some goals and would like to open up dialogue with you to fulfill them. We&#8217;re asking for your participation, and lots of expert advice, to fulfill these intentions. If you are interested and are a Twitter user, <a href="http://twitter.com/typerendering">follow us</a> &#8211;  and more importantly, <a href="http://twitter.com/home?status=I+care+about+how+type+looks+on+the+web,+so+I+follow+%40typerendering.">tell folks you care about how type looks on websites</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/11/30/introducing-the-type-rendering-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Detect Font-Smoothing Using JavaScript</title>
		<link>http://www.useragentman.com/blog/2009/11/29/how-to-detect-font-smoothing-using-javascript/</link>
		<comments>http://www.useragentman.com/blog/2009/11/29/how-to-detect-font-smoothing-using-javascript/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 19:41:50 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Fonts]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=338</guid>
		<description><![CDATA[
Interested in making web typography look better?
Read about The Type Rendering Project!

In an earlier article, I mentioned that Boing-Boing had a few issues when they wanted to use @font-face embedding inside their website.  In short, the problem was that some fonts look bad on computer monitors without font-smoothing enabled in the operating system.  [...]]]></description>
			<content:encoded><![CDATA[<div class="importantNotes">
<h3>Interested in making web typography look better?</h3>
<p><a href="/blog/2009/11/30/introducing-the-type-rendering-project/">Read about The Type Rendering Project!</a></p>
</div>
<div id="attachment_404" class="wp-caption alignleft" style="width: 260px"><img class="size-full wp-image-404 " title="fontSmoothingLeader" src="http://www.useragentman.com/blog/wp-content/uploads/2009/11/fontSmoothingLeader.png" alt="Image a remix of Wikimedia Images http://bit.ly/5LufSS and http://bit.ly/6Jjlbd" width="250" height="250" /><p class="wp-caption-text">
<div>Examples of font-smoothing and subpixel-rendering as performed by technologies like ClearType.  Image Credit: Wikimedia Commons users <a href='http://commons.wikimedia.org/wiki/File:Antialias-vrs-Cromapixel.png'>Pandries</a> and <a href='http://commons.wikimedia.org/wiki/File:ClearType02.png'>Kalan</a></div>
<p></p></div>
<p>In <a title="&quot;More @font-face in Depth&quot; article" href="http://www.useragentman.com/blog/2009/10/09/more-font-face-fun/">an earlier article</a>, I mentioned that <a title=" Boing Boing’s Redesign Uncovers the Dark Side of Web Fonts" href="http://www.webmonkey.com/blog/Boing_Boing_s_Redesign_Uncovers_the_Dark_Side_of_Web_Fonts">Boing-Boing had a few issues when they wanted to use @font-face embedding inside their website</a>.  In short, the problem was that some fonts look bad on computer monitors without font-smoothing enabled in the operating system.  This brought on a lot of discussion as to whether there was a way to detect whether or not font-smoothing was being used using JavaScript.  I initially thought there wasn&#8217;t a way, but after seeing a promising but incomplete method of detecting font-smoothing, I spent a few days devising a way to do it.</p>
<h2>Internet Explorer Does Something Easily (For a Change)</h2>
<p><a href="http://paulirish.com/">Paul Irish</a> mentioned to me and a few other colleagues that he came across <a href="http://silkworth.net/browser_os/cleartype.html">a page using an Active X control that detects font-smoothing in IE</a>.  I was so hopeful &#8230; until I realized that this only works on browsers that have come into contact with <a href="http://www.microsoft.com/typography/cleartype/tuner/tune.aspx">Microsoft&#8217;s online Cleartype Tuner</a>, which I visited with my copy of IE months before.  If a users had never visited this page, the script would fail.</p>
<p>I was more disappointed because Googling &#8220;javascript cleartype&#8221; did not point to anything useful.  However, searching for &#8220;javascript font-smoothing&#8221; pointed me to an article that told me about Internet Explorer&#8217;s <a href="http://www.java2s.com/Code/JavaScript/Window-Browser/ScreenfontSmoothingEnabled.htm">screen.fontSmoothingEnabled</a> property.  This gives us what we need &#8230; but only in Internet Explorer.  How on Earth can we detect font-smoothing in other browsers, and in non-Windows operating systems?</p>
<h2>Canvas to the Rescue</h2>
<div id="attachment_390" class="wp-caption aligncenter" style="width: 420px"><img class="size-full wp-image-390" title="aliasAndAntiAliasComparison" src="http://www.useragentman.com/blog/wp-content/uploads/2009/11/aliasAndAntiAliasComparison.png" alt="aliasAndAntiAliasComparison" width="410" height="244" /><p class="wp-caption-text">Letter &#39;O&#39; , Arial font, 32 px, rendered both without (left) and with (right) font-smoothing</p></div>
<p style="text-align: center;">
<p>I then thought about about the screenshots I made for <a href="/blog/2009/09/20/font-face-in-depth/">the @font-face in Depth article</a>.  Can a browser render a black glyph and detect if there is some sort of non-black pixel colouring around the its edges of the glyphs? <strong> A human can tell the difference</strong>:  if there are some non-black pixels around the edge of the glyph, it must be using font-smoothing.</p>
<p>But <strong>web browsers can do this too!</strong> Just have the browser draw a letter in black inside a <code>canvas</code> tag, and then have it sift through the canvas&#8217; pixels to see if there are any that are <strong>not</strong> pure black or pure white (more accurately, have the browser check the alpha channel to see if there are any semi-transparent pixels, which have a value that is not 0 or 255).    If there are no semi-transparent pixels, then the algorithm assumes that no font-smoothing is being used. I wrote an JavaScript routine that does this &#8211; it starts from co-ordinate (8,1) and scans left to right, to the bottom of the canvas (any point on near the top on the left-hand side of the canvas would have done as well).</p>
<p>The result is a JavaScript object, <code>TypeHelpers</code>, which implements this routine in one method, <code>hasSmoothing()</code>:</p>
<blockquote class="code">
<pre>var TypeHelpers = new function(){

   // I use me instead of this.  For reasons why, please read:
   // http://w3future.com/html/stories/callbacks.xml
   var me = this;

   me.hasSmoothing = function(){

      // IE has screen.fontSmoothingEnabled - sweet!
      if (typeof(screen.fontSmoothingEnabled) != "undefined") {
         return screen.fontSmoothingEnabled;
      } else {

         try {

            // Create a 35x35 Canvas block.
            var canvasNode = document.createElement('canvas');
            canvasNode.width = "35";
            canvasNode.height = "35"

            // We must put this node into the body, otherwise
            // Safari Windows does not report correctly.
            canvasNode.style.display = 'none';
            document.body.appendChild(canvasNode);
            var ctx = canvasNode.getContext('2d');

            // draw a black letter 'O', 32px Arial.
            ctx.textBaseline = "top";
            ctx.font = "32px Arial";
            ctx.fillStyle = "black";
            ctx.strokeStyle = "black";

            ctx.fillText("O", 0, 0);

            // start at (8,1) and search the canvas from left to right,
            // top to bottom to see if we can find a non-black pixel.  If
            // so we return true.
            for (var j = 8; j &lt;= 32; j++) {
               for (var i = 1; i &lt;= 32; i++) {

                  var imageData = ctx.getImageData(i, j, 1, 1).data;
                  var alpha = imageData[3];

                  if (alpha != 255 &amp;&amp; alpha != 0) {
                     return true; // font-smoothing must be on.
                  }
               }

            }

            // didn't find any non-black pixels - return false.
            return false;
         }
         catch (ex) {
            // Something went wrong (for example, Opera cannot use the
            // canvas fillText() method.  Return null (unknown).
            return null;
         }
      }
   }

   me.insertClasses = function(){
      var result = me.hasSmoothing();
      var htmlNode = document.getElementsByTagName('html')[0];
      if (result == true) {
         htmlNode.className += " hasFontSmoothing-true";
      } else if (result == false) {
            htmlNode.className += " hasFontSmoothing-false";
      } else { // result == null
            htmlNode.className += " hasFontSmoothing-unknown";
      }
   }

}

// if EventHelpers.js is included, insert the hasFontSmoothing CSS classes
if (window.EventHelpers) {
   EventHelpers.addPageLoadEvent('TypeHelpers.insertClasses')
}</pre>
</blockquote>
<p>Note the object also has an <code>insertClasses()</code> method.  This method, when run, adds a class to the <code>html</code> tag:</p>
<ul>
<li><code>hasFontSmoothing-true</code> if font-smoothing is being used</li>
<li><code>hasFontSmoothing-false</code> if it is not</li>
<li><code>hasFontSmoothing-unknown</code> if the user agent is unable to tell</li>
</ul>
<p>This makes it easy for developers who don&#8217;t want to mess with JavaScript code and just want  to use CSS.</p>
<p>Also note the <code>EventHelpers.addPageLoadEvent()</code> call at the end of the code.  This method (which is part of <code>EventHelpers.js</code>, included with the archive below) <a href="http://dean.edwards.name/weblog/2005/09/busted/">implements Dean Edwards&#8217; window.onload alternative which doesn&#8217;t wait for all the objects in the page to be loaded</a>.   I use this implementation to execute <code>TypeHelpers.insertClasses()</code> when the page loads so any font-detection CSS rules will work right away.  Please feel free to change this code to use the equivalent function call in Dojo, Prototype, jQuery, or whatever JavaScript code framework you prefer.</p>
<h2>Example #1: JavaScript Font Smoothing Detection</h2>
<p>Enough of theory &#8230; let&#8217;s look at it in practice!  To show how to detect font-smoothing with JavaScript, I created a page that, when the page is loaded, checks to see if it can tell if font-smoothing has been implemented and tells the user.  Here is the code that does this check:</p>
<blockquote class="code">
<pre>function displayInfo() {

   var message;
   var isFontSmoothingOn = TypeHelpers.hasSmoothing();
   if (isFontSmoothingOn == true) {
      message = "This browser is using a font-smoothing technology";
   } else if (isFontSmoothingOn == false) {
      message = "This browser isn't using a font-smoothing technology"
   } else {
      message = "We could not detect if font-smoothing is being used."
   }
   document.getElementById('detectInfo').innerHTML = message;

}

window.onload = displayInfo;</pre>
</blockquote>
<p><a class="exampleLink" href="/tests/fontSmoothing/">See the above code in action</a></p>
<h2>Example #2: CSS Font Smoothing Detection</h2>
<p>As implied earlier, this library can help CSS use different fonts if the browser is using a font-smoothing technology.   For example, using the following CSS will allow a browser to use the Droid Sans embedded font only if it using font-smoothing — otherwise, it will use Arial:</p>
<blockquote class="code">
<pre>@font-face {
	font-family: "Droid Sans";
	src: url("/shared/fonts/DroidSans/DroidSans.eot");
	src: local("Droid Sans"),
	     local("Droid Sans"),
	     url("/shared/fonts/DroidSans/DroidSans.ttf") format("truetype");
}

body {
	font-family: "Arial", "Helvetica", sans-serif;
}

html.hasFontSmoothing-true body {
	font-family: "Droid Sans", "Arial", "Helvetica", sans-serif;
}</pre>
</blockquote>
<p>We can also serve special content to users depending on the way fonts are rendered on their browser.  We first create content for all three scenerios (browser uses font-smoothing, browser doesn&#8217;t use font-smoothing, and the &#8220;we cannot detect&#8221; case) and wrap the content inside &lt;code&gt;div&lt;/code&gt; tags using appropriate CSS classes:</p>
<blockquote class="code">
<pre>&lt;div class="fontSmoothingMessage initiallyHidden"&gt;
    &lt;p&gt;You browser &lt;strong&gt;is&lt;/strong&gt; rendering this page
    with font-smoothing. Because of that, we will attempt
    to serve up the Droid Sans font to render this page,
    because we think it looks cool. If you are using a
    browser (such as Google Chrome) that cannot render
    downloaded True Type fonts by default, then the page
    will be rendered using Arial instead.&lt;/p&gt;
&lt;/div&gt;

&lt;div class="noFontSmoothingMessage initiallyHidden"&gt;
    Your browser &lt;strong&gt;is not&lt;/strong&gt; rendering this
    page with font-smoothing. It is for that reason we have
    decided to use the plain old Arial font to render this
    page, because it is hinted for use for displays that
    don't employ a font-smoothing technology.
&lt;/div&gt;

&lt;div class="unknownFontSmoothingMessage initiallyHidden"&gt;
    &lt;strong&gt;We are not sure&lt;/strong&gt; if your browser is
    rendering this page with a font-smoothing technology.
    It is for that reason we have decided to use the plain
    old Arial font to render this page, because it is
    hinted for use for displays that don't employ a
    font-smoothing technology.
&lt;/div&gt;</pre>
</blockquote>
<p>Note all the <code>div</code> tags are members of the class <code>initiallyHidden</code>.  This class will be used to hide all font-smoothing related content until the script kicks in.</p>
<p>However, all this will not work unless we use the following CSS code:</p>
<blockquote class="code">
<pre>.initiallyHidden {
	display: none;
}

html.hasFontSmoothing-true .fontSmoothingMessage,
html.hasFontSmoothing-false .noFontSmoothingMessage,
html.hasFontSmoothing-unknown .unknownFontSmoothingMessage {
	display: block;
}</pre>
</blockquote>
<p>Of course, this whole soltution relies on whether JavaScript being turned on in the user&#8217;s browser.  This should be kept in mind when implementing this solution.</p>
<p><a class="exampleLink" href="/tests/fontSmoothing/cssExample.html">See the above code in action</a></p>
<h2>Download</h2>
<p>All code used in this article can be downloaded below (<strong>Note:</strong> version 1.0 was missing the Droid Sans Fonts which have now been put into the archive.  Thanks to John Faulds for pointing this out).</p>
<p><a class="exampleLink" href="/downloads/TypeHelpers.zip">TypeHelpers.js v.1.0a and sample code.</a></p>
<p>With the help of <a href="http://www.nicewebtype.com">Tim Brown</a>, it was determined that the code detected font-smoothing correctly in the following browsers:</p>
<ul>
<li>Internet Explorer 6 and up on Windows XP and higher.</li>
<li>Firefox 3.5 and higher on Windows XP and higher, Mac OS X 10.4 and higher, and Ubuntu Linux 9.10 (and probably lower)</li>
<li>Chrome 3.0 on Windows XP and higher</li>
<li>Safari 4.0.3 on Windows XP and higher and Mac OS X 10.4 and higher</li>
</ul>
<p>This script <strong>cannot detect font-smoothing in any version of Opera</strong> (at the time of this writing, this includes all versions up to 10.10), since it cannot write text inside the canvas element in a way we can poll the pixels afterwards.  If anyone can find a way of making it work with Opera, please write a comment below — I&#8217;d love to be able to support this browser.</p>
<h2>Testing Caveats</h2>
<p>Testing font-smoothing in most Windows web browsers is easy since it can be turned off inside the Display control panel. However, when using Safari for Windows, it is necessary to navigate inside Safari&#8217;s <strong>Appearance</strong> preferences and set the <strong>Font-smoothing</strong> option to <strong>Windows Standard</strong>.  This is because  by default, Safari uses it&#8217;s own built-in font-rendering engine which doesn&#8217;t seem to render aliased fonts.  In Mac OS X, it seems anti-aliasing only works for fonts below a certain size, so aliased fonts don&#8217;t seem to be an issue with that operating system.  In Ubuntu Linux I have yet to find a way of shutting of font-smoothing.  If anyone knows a way, please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/11/29/how-to-detect-font-smoothing-using-javascript/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Twitter Security Issue Affects My Twitter Account.</title>
		<link>http://www.useragentman.com/blog/2009/11/21/twitter-security-issue-affects-my-twitter-account/</link>
		<comments>http://www.useragentman.com/blog/2009/11/21/twitter-security-issue-affects-my-twitter-account/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 22:05:19 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[General Announcements]]></category>
		<category><![CDATA[intrusion]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=332</guid>
		<description><![CDATA[Today has been a lovely day, I must say.  Someone has been using my account to send SPAM messages saying:
I make money online with google. i learned how here: &#8212;&#8212; 
This message was followed by a link, which I am not going to post here for obvious reasons.  I found out when two of my [...]]]></description>
			<content:encoded><![CDATA[<p>Today has been a lovely day, I must say.  Someone has been using my account to send SPAM messages saying:</p>
<blockquote><p>I make money online with google. i learned how here: &#8212;&#8212; </p></blockquote>
<p>This message was followed by a link, which I am not going to post here for obvious reasons.  I found out when two of my followers sent me a private message and gave me the heads up (thanks Paul and Sharon!).  I was away at a rummage sale at the time, but I changed my password using my phone to see if that would stop it.  I am not sure if it will, but we&#8217;ll see.</p>
<p>When I came home, I found a couple of articles that reassured me it was not just my account:</p>
<ul>
<li><a href="http://www.p2pnet.net/story/30557">Twitter ‘I make money online’ scam</a> on p2pnet.net</li>
<li><a href="http://news.cnet.com/8301-27080_3-10388715-245.html">Spammy scams surfacing on Twitter, Facebook</a> on C|Net</li>
</ul>
<p>Although this doesn&#8217;t appear to by my fault, I want to express my apologies to my followers about this.  I don&#8217;t know what caused this, but I&#8217;ll keep you posted on future posts, so I can potentially prevent this from happening to others.  I would never send you spam, and this <strong>really</strong> annoys me like you wouldn&#8217;t believe.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/11/21/twitter-security-issue-affects-my-twitter-account/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Configuring JavaScript Applications With XML</title>
		<link>http://www.useragentman.com/blog/2009/10/27/configuring-javascript-applications/</link>
		<comments>http://www.useragentman.com/blog/2009/10/27/configuring-javascript-applications/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 02:37:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=71</guid>
		<description><![CDATA[
I have been hacking JavaScript for close to 12 years now, and love it.  But just like anyone you have been enamored with for a long time, there are bound to be things that drive you crazy about the object of your affection.  Sure, your feelings are stronger than when you first met, but sometimes, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-283 alignleft whiteImage" title="configurationXML" src="http://www.useragentman.com/blog/wp-content/uploads/2009/10/configurationXML.png" alt="Remixed from an image from the Open Clip Art Library" width="250" height="89" /></p>
<p>I have been hacking JavaScript for close to 12 years now, and love it.  But just like anyone you have been enamored with for a long time, there are bound to be things that drive you crazy about the object of your affection.  Sure, your feelings are stronger than when you first met, but sometimes, after you&#8217;ve had an a disagreement after a late night of coding, you catch yourself thinking “why in the world does she do things that way!?! Ridiculous!  She is driving me crazy with her inflexibility!”  You then calm down, and realize that despite her flaws, she is still the exciting, cool and can&#8217;t-live-without-her girl she was when you first met her – maybe even more so.</p>
<p>Okay, I don&#8217;t mean to equate JavaScript with my wife (that may result with me sleeping on the couch tonight).  But sometimes the way JavaScript does things is pretty silly.  You&#8217;d figure after all these years, some of these things would have changed, but they haven&#8217;t.</p>
<h2>Long Strings in JavaScript</h2>
<p>Take for example the way that JavaScript likes to handle long, multi-line strings:</p>
<blockquote class="code">
<pre>var html = "&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Address&lt;/th&gt;&lt;th&gt;City&lt;/th&gt;" +
"&lt;th&gt;Province&lt;/th&gt;&lt;th&gt;Postal Code&lt;/th&gt;&lt;th&gt;Telephone&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;";</pre>
</blockquote>
<p>Concatenating strings is a pretty expensive operation, both in <a title=" String Performance: an Analysis" href="http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis/">memory and processing time</a>, and using concatenation  it to describe a constant string doesn&#8217;t make too much sense.  But putting this string on one line would make the code quite unwieldy to read.  Plus it looks ugly.  I may be a slob in real life (my coworkers and my family could go on for hours about that one) , but I love my code neat.</p>
<h2>Hard-Coding Values into Scripts</h2>
<p>Another problem I have with this method of defining strings is that we are hard-coding text into the script. This is not a problem unique to JavaScript by any means, but this breaks the <a title="Wikipedia article on Unobtrusive JavaScript" href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript">Structure/View/Behaviour separation</a> model that I like to follow when I code a web application.  Furthermore, if we had two pages with the same content but written in different languages (like in Canada, where a lot of sites are in English and French) we either have to have two versions of our script, or have the script broken into two parts: one with all the general code in it and one containing the language specific code.    While the latter is the more desirable of the two, it doesn&#8217;t lend itself to integrate well with some server-side web application frameworks like <a title="Java Struts home page." href="http://struts.apache.org/">Java Struts</a>.</p>
<p>Furthermore, I hate hard-coding <strong>any</strong> type of value (strings, integers, and any type of objects) directly into my scripts.  Scripts should be flexible enough to be used in any type of situation &#8211; your table pagination script may work well with having ten rows on the page at the time in one situation, but in another, you may want 15 or 20.</p>
<p>One comment I hear all the time is <strong>&#8220;Why not use JSON&#8221;?</strong> JSON is great, but because it is based on JavaScript, it is still gets ugly when manipulating long strings.</p>
<h2>Enter config.js to the Rescue</h2>
<p>In fact, it was Struts that inspired me to write the config.js JavaScript library.  If you aren&#8217;t familiar with it, Struts is a Java Framework that allows developers to configure their server-side web applications easily with a set of XML files.  It seemed natural to do the same in JavaScript, given all the DOM and XML processing routines that it has at its disposal, so I built config.js to do this task.  With this library, JavaScript developers can configure their own scripts using a block of XML.  This block of XML can be either embedded inside the HTML document (via an HTML comment) or in a separate XML file of its own.  And this configuration block can contain any number of strings, numbers, arrays or objects that a developer would need to get the job done.</p>
<p>For example, let&#8217;s say you had a JavaScript function that looked like this:</p>
<blockquote class="code">
<pre>function submitFormEvent(e){
  var amount = document.getElementById("amount").innerHTML;
  var creditCardType = document.getElementById("ccType").value;
  var month = document.getElementById("month").value;

  var configString = "Submitting this order will charge " + amount +
    " to your " + creditCardType +
    " and will be received on your " + month +
    " credit card bill.  Are you sure you want to do" +
    " this?");

  if (window.confirm(configString)) {
    window.location = "http://www.mycompany.com/myApp/chargeMe.do";
  }
  return;
}</pre>
</blockquote>
<p>As you can see, the English literals are hard-coded in the script and there is a lot of string concatenation going on.  One could refactor the script to use config.js to fix these issues  in four simple steps:</p>
<ol>
<li>Include the EventHelpers.js and config.js scripts in the &lt;head&gt; of your document (EventHelpers.js is included with the config.js archive):<br />
<blockquote class="code">
<pre>&lt;script type=”text/javascript” src=”/path/to/EventHelpers.js”&gt;&lt;/script&gt;
&lt;script type=”text/javascript” src=”/path/to/config.js”&gt;&lt;/script&gt;</pre>
</blockquote>
</li>
<li>Insert an XML block that contains the hard-coded strings in an HTML tag with an <code>id</code> of <code>config</code>:<br />
<blockquote class="code">
<pre>&lt;div id="config"&gt;
&lt;!--
&lt;config&gt;
  &lt;myApp&gt;
   &lt;confirmCharge&gt;
      &lt;text&gt;
Submitting this order will charge @amount@  to your
@creditCardType@ and will be received on your @month@
credit card bill.  Are you sure you want to do this?
      &lt;/text&gt;
      &lt;url&gt;http://www.mycompany.com/myApp/confirm.do&lt;/url&gt;
   &lt;/confirmCharge&gt;
  &lt;/myApp&gt;
&lt;/config&gt;
 --&gt;
&lt;/div&gt;</pre>
</blockquote>
</li>
<li>Refactor you code to use config.js routines:<br />
<blockquote class="code">
<pre>function submitFormEvent(e){
      var amount = document.getElementById("amount").innerHTML;
      var creditCardType = document.getElementById("ccType").value;
      var month = document.getElementById("month").value;
<strong>
      var configString = config.getScriptedValue(
          "myApp.confirmCharge.text",
          {
            amount: amount,
            creditCardType: creditCardType,
            month: month
          });

      if (window.confirm(configString)) {
          window.location = config.getValue("myApp.confirmCharge.url");
      }
</strong>
      return;
}</pre>
</blockquote>
</li>
<li>Replace any <code>window.onload</code> calls in your code with <code>config.addLoadEvent()</code> to ensure that any code that relies on config.js is initialized <strong>after</strong> the XML block is loaded into memory:<br />
<blockquote class="code">
<pre>config.addLoadEvent(exampleConfigForm.init);</pre>
</blockquote>
</li>
</ol>
<p>That&#8217;s it!  If you need to internationalize your application, use whatever internationalization framework your server side code uses &#8211; it should integrate well with config.js.  I use it with Java Struts all the time.</p>
<p><a class="exampleLink" href="/tests/config/example.html">See an example of the above code in action</a></p>
<h2>Use config.js in All Your Scripts</h2>
<p>Have more than one script on a page that you want to use config.js with?  No problem!  Add another block of XML inside the &lt;config&gt; node right after your other scripts config information:</p>
<blockquote class="code">
<pre>&lt;div id=”config”&gt;
&lt;!--
&lt;config&gt;
  &lt;myApp&gt;
   &lt;confirmCharge&gt;
      &lt;text&gt;
Submitting this order will charge @amount@  to your
@creditCardType@ and will be received on your @month@
credit card bill.  Are you sure you want to do this?
      &lt;/text&gt;
      &lt;url&gt;http://www.mycompany.com/myApp/confirm.do&lt;/url&gt;
   &lt;/confirmCharge&gt;
  &lt;/myApp&gt;

<span class="hilite">&lt;calendarWidget&gt;
  &lt;instructions&gt;Enter in a valid date after @dateBegin@&lt;/instructions&gt;
  &lt;errors&gt;
    &lt;notValid&gt;The date you entered is not valid&lt;/notValid&gt;
    &lt;holiday&gt;
Sorry, @date@ is a holiday and we won't be open
at that time.  Please try again.
    &lt;/holiday&gt;
  &lt;/errors&gt;
&lt;/calendarWidget&gt;
</span>
&lt;/config&gt;
--&gt;
&lt;/div&gt;</pre>
</blockquote>
<p>Now, all your configuration information for all your scripts can be in one place.  Programmers can now develop the code with place holders for the text, and not worry about accidentally messing up the code when marketing or customer service wants to make some textual changes.</p>
<h2>config.js can also handle HTML</h2>
<p>You can even insert full HTML inside the configuration XML block using a CDATA node:</p>
<blockquote class="code">
<pre>&lt;config&gt;
&lt;myApp&gt;
  &lt;browserWarning&gt;&lt;![CDATA[
    &lt;div class=”warning”&gt;
    As of @date@ we will &lt;strong&gt;not&lt;/strong&gt; be supporting Internet
    Explore 6 or lower.  Please &lt;a href=”/howToUpgradeIE.html"&gt;upgrade your
    installation of Internet Explorer&lt;/a&gt;, or install the latest version of one
    &lt;a href=”/otherChoices.html”&gt;the many alternative browsers available&lt;/a&gt;.
    &lt;/div&gt;
  ]]&gt;&lt;/browserWarning&gt;
  &lt;/myApp&gt;
&lt;/config&gt;</pre>
</blockquote>
<p>This makes using an HTML node&#8217;s .innerHTML property even more fun!  You longer do you have to hard-code  long chunks of HTML inside your scripts.  Try that with JSON!</p>
<h2>Framework Independent</h2>
<p>Config.js is not part of a JavaScript framework – you can use this library whether you use prototype, mootools, Dojo, jQuery or anything else that may come along.  Please feel free to make improvements and changes on it &#8211; if you submit the changes back to me, I&#8217;ll incorporate them into the next official release.</p>
<h2>More Information</h2>
<p>There is way more to config.js than is explained here.  Complete documentation for the library can be found here:<br />
<a class="exampleLink" href="/blog/config-js-–-a-javascript-cofiguration-library/">config.js manual page</a></p>
<h2>Download</h2>
<p>You can get full source here:</p>
<p><a class="exampleLink" href="/downloads/config.zip">config.js v.2.0 and example code (zip format)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/10/27/configuring-javascript-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More @font-face fun</title>
		<link>http://www.useragentman.com/blog/2009/10/09/more-font-face-fun/</link>
		<comments>http://www.useragentman.com/blog/2009/10/09/more-font-face-fun/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 00:53:36 +0000</pubDate>
		<dc:creator>zoltan</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Fonts]]></category>
		<category><![CDATA[SVG]]></category>
		<category><![CDATA[@font-face. opera. chrome]]></category>
		<category><![CDATA[anti-aliasing]]></category>
		<category><![CDATA[cleartype]]></category>
		<category><![CDATA[svg fonts]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=237</guid>
		<description><![CDATA[My first post @font-face in Depth got a huge amount of unexpected attention.  Thank you all for your comments and criticism.  Since the post, there have been quite a bit of information I have read about and thought I should share.
SVG fonts for Opera and Chrome
Jonathan Snook wrote a great article regarding Opera 10 and [...]]]></description>
			<content:encoded><![CDATA[<p>My first post <a href="/blog/2009/09/20/font-face-in-depth/">@font-face in Depth</a> got a <strong>huge</strong> amount of unexpected attention.  Thank you all for your comments and criticism.  Since the post, there have been quite a bit of information I have read about and thought I should share.</p>
<h2>SVG fonts for Opera and Chrome</h2>
<p><a href="http://www.snook.ca/">Jonathan Snook</a> wrote a great article <a href="http://www.snook.ca/archives/html_and_css/becoming-a-font-embedding-master">regarding Opera 10 and Google Chrome supporting SVG fonts</a> (Chrome can load them without any pesky command line switch!).   He mentions how to convert TrueType fonts to this format using <a href="http://xml.apache.org/batik/">Batik</a>, and that by removing all the <code>&lt;hkren&gt;</code> elements inside the file&#8217;s XML can make the font smaller than the original TrueType file.  Too bad the browsers don&#8217;t support this format.</p>
<h2>Opera&#8217;s buggy implementation</h2>
<p>I noticed after I launched my first @font-face article that Opera was not loading the fonts on my blog when users visited more than one page.  It turns out that Opera 10&#8217;s implementation of @font-face is a little buggy.  When you feed it a page with an embedded font, you may not see the embedded fonts properly, like in the screenshot below:</p>
<div id="attachment_238" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.useragentman.com/blog/wp-content/uploads/2009/10/screenshotOpera.png"><img class="size-medium wp-image-238 " title="screenshotOpera" src="http://www.useragentman.com/blog/wp-content/uploads/2009/10/screenshotOpera-300x215.png" alt="screenshotOpera" width="300" height="215" /></a><p class="wp-caption-text">Opera sometimes doesn&#39;t load the font at all, and removes other styling (click to enlarge).</p></div>
<p><a href="http://readableweb.com/opera-admits-font-face-bugs-in-opera-10/">According to Opera</a>, this happens when &#8220;specifying different weights and styles for a single font-family name&#8221;.  Håkon Wium Lie, the company&#8217;s Chief Technology Officer , <a href="http://devfiles.myopera.com/articles/751/webfonts-workaround.html">has described a work-around</a> until the company can fix the problem properly.</p>
<p>I am debating whether to implement the work around on my site, or to wait for Opera to fix the problem and patch all Opera 10 installations via auto-update (I&#8217;m leaning towards the latter).</p>
<h2>Performance Issues With Font Embedding</h2>
<p>One of the comments on the last article came from <a href="http://stevesouders.com/">Steve Souders</a> who had <a href="/blog/2009/09/20/font-face-in-depth/#comment-37">performance concerns with font-embedding</a>.  Paul Irish came back with information showing the <a href="http://paulirish.com/2009/fighting-the-font-face-fout/">when browsers load the fonts, and what they do before the font is loaded</a>.  He also shows how to use JavaScript to make the loading behaviour consistent between browsers.</p>
<p>The performance issues with font-embedding is something I am going to be keeping an eye on, especially when it comes to font-services, which the OpenType site believes will be <a href="http://opentype.info/blog/2009/07/29/why-webfont-services-are-the-future-of-fonts-on-the-web/">the future of web font distribution for commercial fonts</a>.  Although it doesn&#8217;t seem like much of an issue currently (my blog <em>seems</em> to load quickly), I don&#8217;t want to do anything that would slow down my web applications &#8211; especially if I am using them just to make the text look a little prettier.</p>
<h2>Windows XP Rendering Issues</h2>
<p>Boing-Boing had a bad experience with font-embedding.  Turns out <a href="http://www.webmonkey.com/blog/Boing_Boing_s_Redesign_Uncovers_the_Dark_Side_of_Web_Fonts">they got a lot of complaints when they decided to incorporate it into their website</a>.  The reason: some users didn&#8217;t have ClearType turned on, and the font Boing-Boing chose looked &#8220;like ass&#8221; without ClearType.</p>
<p>Below are screenshots of this site without ClearType on:</p>
<div id="attachment_250" class="wp-caption aligncenter" style="width: 449px"><img class="size-full wp-image-250" title="ieNoAA" src="http://www.useragentman.com/blog/wp-content/uploads/2009/10/ieNoAA.png" alt="ieNoAA" width="439" height="336" /><p class="wp-caption-text">Internet Explorer without ClearType</p></div>
<p style="text-align: center;">
<div id="attachment_251" class="wp-caption aligncenter" style="width: 465px"><img class="size-full wp-image-251" title="firefoxNoAA" src="http://www.useragentman.com/blog/wp-content/uploads/2009/10/firefoxNoAA.png" alt="Firefox without ClearType" width="455" height="327" /><p class="wp-caption-text">Firefox without ClearType</p></div>
<p>The article stated that there are quite a few XP computers which apparently don&#8217;t have ClearType on by default. I wonder if there are any stats to back that up. If so, then developers embed fonts into pages should test that scenario as well.  It does look different.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/10/09/more-font-face-fun/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>@font-face in Depth</title>
		<link>http://www.useragentman.com/blog/2009/09/20/font-face-in-depth/</link>
		<comments>http://www.useragentman.com/blog/2009/09/20/font-face-in-depth/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 04:04:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[@font-face]]></category>
		<category><![CDATA[embedded font]]></category>
		<category><![CDATA[eot]]></category>
		<category><![CDATA[font]]></category>
		<category><![CDATA[font-embedding]]></category>
		<category><![CDATA[fontforge]]></category>
		<category><![CDATA[otf]]></category>
		<category><![CDATA[ttf]]></category>
		<category><![CDATA[ttf2eot]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=13</guid>
		<description><![CDATA[The fact that we can now choose any font to embed inside our web pages and applications using @font-face is something to celebrate, and removes a long existing set of handcuffs placed on web designers.  This article covers how to use @font-face in all browsers, as well as some interesting little-known technical details.]]></description>
			<content:encoded><![CDATA[<div class="importantNotes">
<h3>Update (Oct 13, 2009):</h3>
<p>Please see the <a href="/blog/2009/10/09/more-font-face-fun/">follow up article</a> which explores SVG fonts,<br />
	Opera 10 issues, and more</p>
</div>
<div id="attachment_28" class="wp-caption alignleft" style="width: 250px"><a title="image Flickr page" href="http://www.flickr.com/photos/martab/1757415036/" target="_blank"><img class="size-full wp-image-28      " title="image Flickr page" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/fontintro2.jpg" alt="" width="240" height="180" /></a><p class="wp-caption-text">Photo by marta.b (Source: Flickr)</p></div>
<p>When I told one of my co-workers how excited I was that almost all the major browser vendors now supported font-embedding in their products, I got the same reaction from her that Bert from Sesame Street got when he told Ernie how <a title="Link to classic Sesame Street clip &quot;Bert's Bottlecaps&quot; via YouTube" href="http://www.youtube.com/watch?v=2Ls2vNfQxyc">exciting he thought bottle cap collecting was</a> (yes, gratuitous ridicule was involved).  Now, while I can somewhat understand her disinterest (she is not a front-end web developer, but a Java programmer), I defend my enthusiasm by stating here that fonts are a really important part of web design, and the fact that we can now theoretically choose <strong>any</strong> font to embed inside our web pages and applications is something to celebrate.</p>
<p>Sure, workarounds such as <a title="Mike Davidson article &quot;sIFR 2.0: Rich Accessible Typography for the Masses&quot;" href="http://www.mikeindustries.com/blog/sifr/">sIFR</a> and <a title="Cufón homepage" href="http://cufon.shoqolate.com/generate/">Cufón</a> have existed for quite a while now, but they have drawbacks (they both are best used only for headings, and Cufón  doesn&#8217;t do well at allowing copying and pasting its content).  If you really want to embed fonts in your webpages, I believe that @font-face is the safest, future-proof option.</p>
<h2>Why care about fonts?</h2>
<p>My Java developer colleague may not understand why fonts are important, but she is a regular reader of  <a href="http://www.newyorker.com/">The New Yorker</a>.  Even though its website doesn&#8217;t use @font-face embedding (the standard New Yorker font is embedded in site using images), the developers of the site obviously know why fonts are important:</p>
<ul>
<li><strong>Fonts identify who the content belongs to.</strong> Just take a look at the content and without looking at the URL bar, you know exactly where you are &#8211; that font is highly integrated into that organization&#8217;s identity and branding.  Replace the New Yorker font with Arial and it&#8217;ll look like any old website.</li>
<li><strong>Fonts given an emotional association to the content. </strong>The content has an air of authority because of the font it uses (after all, it looks like it was written by The New Yorker).  It is the reason why phishing sites use the fonts, colours and logos of the banks they are posing as.</li>
<li><strong>Fonts can help (or hinder) the legability of content.</strong> Scanning the content, you can tell where the article titles are, where the navigation is, and what section each of the articles belong to.  This is all because of the way fonts are used on the site.</li>
</ul>
<div id="attachment_60" class="wp-caption aligncenter" style="width: 460px"><img class="size-full wp-image-60  " title="newYorkerScreenshot" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/newYorkerScreenshot1.jpg" alt="newYorkerScreenshot" width="450" height="206" /><p class="wp-caption-text">The New Yorker&#39;s website is a great example of how to use fonts effectively on the web.</p></div>
<p style="text-align: left;">The New Yorker uses images in order to display fonts.  Using font embedding effectively would save on bandwidth, since one font download could be used for all the headings on the page.</p>
<h2>Font formats supported</h2>
<p>Firefox 3.5+ , Safari 3.1+, Opera 10+ and Internet Explorer 4.0+ all support @font-face embedding (Google&#8217;s Chrome 3.0 beta does as well, but <a href="http://opentype.info/blog/2009/04/16/google-chrome-with-webfonts-support/">users will have to start it up in a special mode to make it work</a> in the short term).  They all support the use of <a title="Wikipedia TrueType entry" href="http://en.wikipedia.org/wiki/TrueType">TrueType</a> (.ttf) and <a title="Wikipedia OpenType entry" href="http://en.wikipedia.org/wiki/OpenType">OpenType</a> (.otf) fonts &#8230; <strong>except</strong> for Internet Explorer which only supports the proprietary <a title="Wikipedia Embedded OpenType entry" href="http://en.wikipedia.org/wiki/Embedded_Open_Type">Embedded Open Type</a> (.eot) format.  There aren&#8217;t as many fonts available in this format and the tool Microsoft gives out that converts .ttf fonts to .eot, called <a href="http://www.microsoft.com/typography/WEFT.mspx">WEFT</a>, is quite frustrating to use, and even crashes on Vista.  There is, however, an excellent command-line tool, <a href="http://code.google.com/p/ttf2eot/">ttf2eot</a>, that does a much better job. Both WEFT and ttf2eot only convert TrueType to Embedded Open Type &#8211; if you want to convert an <em>OpenType</em> font to Embedded Open Type, it is necessary to use <a href="http://fontforge.sourceforge.net/">FontForge</a>, a free font-editing tool, to convert the font to TrueType first, and then use ttf2eot to convert the resultant font to .eot format.  Although this method is roundabout and results in loss of detail due to the way the font formats store information, it is the only way I know to do this conversion.</p>
<p>For more detail on how to perform .eot font conversions using ttf2eot and FontForge, check out Edward O&#8217;Connor&#8217;s great article <cite><a href="http://edward.oconnor.cx/2009/07/how-to-create-eot-files-without-microsoft-weft">How to create EOT files without Microsoft WEFT</a></cite></p>
<h2>Where to get fonts you can legally use in web pages.</h2>
<p>Although it is now technically possible to embed almost any font inside a web page, it is important to remember that if you use a commercial font for this purpose, you must have a license to do this.  Since putting a font on a website will allow anyone on the Web to download it, a lot of font foundries currently do not allow their fonts to be used for web page embedding. It is for this reason that the browser vendors have been reluctant to implement this technology into their products until recently (font embedding is part of the CSS2 specification, which has been around since 1998).</p>
<p>Luckily, there are a few sites that are sprouting up that have done the initial work for you by listing fonts that allow font embedding on web pages legally.  The ones that I have visited include:</p>
<ul>
<li><a href="http://www.fontsquirrel.com">Font Squirrel&#8217;s</a> <a href="http://www.fontsquirrel.com/fontface">@font-face page</a>, which include @font-face kits that include an .eot as well as an .otf or .ttf font.  Each kit also includes <strong></strong>a stylesheet which can be linked directly into your document so you can use the font with minimal coding.</li>
<li><a href="http://www.smashingmagazine.com/">Smashing Magazine&#8217;s</a> has an excellent article, <cite><a href="http://www.smashingmagazine.com/2007/11/08/40-excellent-freefonts-for-professional-design/">40+ Excellent Freefonts For Professional Design</a></cite></li>
<li><a href="http://kernest.com/">Kernest.com</a> hosts a whole slew of fonts that can be used for font-embedding.</li>
<li><a href="http://webfonts.info">Webfonts.info</a> has a page dedicated to <a href="http://webfonts.info/wiki/index.php?title=Fonts_available_for_%40font-face_embedding">fonts available for @font-face embedding</a>.</li>
</ul>
<p>Note that whenever you use <strong>any</strong> font, make sure you check the license that comes with it.  Some fonts, even if their license allows for font embedding, may not allow you to use it for commercial purposes.  Others may, but only for a fee.  To be safe, check the documentation that comes with the font.</p>
<h2>How to insert a font into your webpage</h2>
<p>Once you have a font that you&#8217;d like to insert into your webpage, you first have to declare it inside your CSS stylesheet:</p>
<blockquote class="code">
<pre>@font-face {
	font-family: 'Droid Sans';

        /* for IE */
	src: url('/shared/fonts/DroidSans/DroidSans.eot');

        /*
         * for non-IE: first see if the font exists locally on the browser's
         * computer.  If so, use that copy of the font.  Otherwise, load it
         * from the server
         */
	src: local('Droid Sans'),
	     url('/shared/fonts/DroidSans/DroidSans.ttf') format('truetype');
}</pre>
</blockquote>
<p>It is very important to note here that <strong>order counts</strong>.  There are variations of this CSS syntax, but I have settled on this syntax for the reasons described in Paul Irish&#8217;s article <a href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/">Bulletproof @font-face syntax</a>.</p>
<p>After you declare the font, you can use it inside any of your selectors as you would use any other font:</p>
<blockquote class="code">
<pre>body {
     font-family: "Droid Sans", "Arial", "Helvetica", sans-serif;
}</pre>
</blockquote>
<p>Note that it is still necessary to use alternative fonts &#8211; this is so that user agents that don&#8217;t support @font-face will still show an appropriate, similar looking font.</p>
<p>Some font families are contained in not just one file.  For example, Droid Sand  has a bold variant that is stored in a separate TrueType file (the .eot file used by Internet Explorer in the above example contains both the regular and bold variants).  The bold variant of Droid Sans can be declared correctly in your stylesheet like this:</p>
<blockquote class="code">
<pre>@font-face {
	font-family: 'Droid Sans';
	src: url('/shared/fonts/DroidSans/DroidSans.eot');
	src: local('Droid Sans'),
	     local('Droid Sans'),
	     url('/shared/fonts/DroidSans/DroidSans.ttf') format('truetype');
}

/* Bold declaration only for non-IE browsers */
@font-face {
	font-family: 'Droid Sans';
	src: local('Droid Sans Bold'),
	     local('Droid Sans-Bold'),
	     url('/shared/fonts/DroidSans/DroidSans-Bold.ttf') format('truetype');
	font-weight: bold;
}</pre>
</blockquote>
<h2>Browser Differences</h2>
<p>To effectively illustrate how differently browsers render embedded fonts, let&#8217;s compare them side by side:</p>
<table border="0">
<thead>
<tr>
<th></th>
<th>Safari 3</p>
<p>Windows</th>
<th>Firefox 3.5</p>
<p>Windows</th>
<th>Explorer 6</p>
<p>Windows</th>
</tr>
</thead>
<tbody>
<tr>
<th>Title of this blog post</th>
<td><img title="Screenshot Detail 1 (Safari)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/safari-font-11.png" alt="Screenshot Detail 1 (Safari)" /></td>
<td><img title="Screenshot Detail 1 (Firefox)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/firefox-font-12.png" alt="Screenshot Detail 1 (Firefox)" /></td>
<td><img title="Screenshot Detail 1 (IE)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/ie-font-11.png" alt="Screenshot Detail 1 (IE)" /></td>
</tr>
<tr>
<th>Close-up of the title of this blog post</th>
<td><img title="Screenshot Closeup 1a (Safari)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/safari-font-1-detail2.png" alt="Screenshot Closeup 1a (Safari)" /></td>
<td><img title="Screenshot Closeup 1a (Firefox)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/firefox-font-1-detail.png" alt="Screenshot Closeup 1a (Firefox)" /></td>
<td><img title="Screenshot Closeup 1a (IE)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/ie-font-1-detail.png" alt="Screenshot Closeup 1a (IE)" /></td>
</tr>
<tr>
<th>Subheading from this blog post</th>
<td><img title="Screenshot Detail 2 (Safari)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/safari-font-1-detail1.png" alt="Screenshot Detail 2 (Safari)" /></td>
<td><img title="Screenshot Detail 2 (Firefox)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/firefox-font-2.png" alt="Screenshot Detail 2 (Firefox)" /></td>
<td><img title="Screenshot Detail 2 (IE)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/ie-font-2.png" alt="Screenshot Detail 2 (IE)" /></td>
</tr>
<tr>
<th>Close-up of subheading of this blog post</th>
<td><img title="Screenshot Closeup 2 (Safari)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/safari-font-2-detail.png" alt="Screenshot Closeup 2 (Safari)" /></td>
<td><img title="Screenshot Closeup 2 (Firefox)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/firefox-font-2-detail.png" alt="Screenshot Closeup 2 (Firefox)" /></td>
<td><img title="Screenshot Closeup 2 (IE)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/ie-font-2-detail.png" alt="Screenshot Closeup 2 (IE)" /></td>
</tr>
<tr>
<th>Close-up of main text of this blog post</th>
<td><img title="Screenshot Closeup 3 (Safari)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/safari-3-detail.png" alt="Screenshot Closeup 3 (Safari)" /></td>
<td><img title="Screenshot Closeup 3 (Firefox)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/firefox-3-detail.png" alt="Screenshot Closeup 3 (Firefox)" /></td>
<td><img title="Screenshot Closeup 3 (IE)" src="http://www.useragentman.com/blog/wp-content/uploads/2009/09/ie-3-detail.png" alt="Screenshot Closeup 3 (IE)" /></td>
</tr>
</tbody>
</table>
<p>As you may see, there are some slight differences in the way that fonts are rendered in the various browsers:</p>
<ul>
<li><strong>Fonts displayed on Safari for Windows (and all browsers on the Mac) in my opinion look the nicest</strong>: they are nicely smoothed out and the text is quite easily read at smaller sizes.  This is due to the way Apple products render fonts.  <a title="Joel Spolsky article &quot;Font smoothing, anti-aliasing, and sub-pixel rendering&quot;" href="http://www.joelonsoftware.com/items/2007/06/12.html">Apple has always differed in philosophy with Microsoft on how to render fonts</a>, and this difference is quite obvious when testing pages under the Windows operating system.</li>
<li><strong>I have found that Internet Explorer does a poor job when displaying fonts converted from OpenType</strong> — the glyphs tend to be more jagged and some elements tend to be rendered thinner than they should be. GrauBlau Web, the font used in the headings of  this page, is a converted OpenType font, and you can see this effect in the close-ups above. It does not occur in the main body of the text because Droid Sans is a TrueType font.  There seems to be two reasons for this:
<ol>
<li>There was information loss when converting GrauBlau Web from OpenType to TrueType.</li>
<li>In Explorer, <a href="http://en.wikipedia.org/wiki/ClearType">ClearType</a> renders this font using subpixel anti-aliasing quite more severely than Safari, while other Windows browsers use vanilla anti-aliasing to get the job done.  A <a href="http://www.luxography.com/">friend of mine</a> pointed this out, and he said that it&#8217;s because ClearType renders TrueType (and, it seems, Embedded Open Type) fonts with subpixel anti-aliasing, but OpenType for some reason isn&#8217;t.  I don&#8217;t know the reasons why, but in this example it looks like it is true &#8211; if you look at all of the Explorer closeups,you&#8217;ll see the coloured pixels on the edge of all the glyphs, while in Firefox only Droid Sans (which is a TrueType font) has them.</li>
</ol>
</li>
<li><strong>Firefox only allows you to embed fonts that come from the same server</strong>, unless some special headers appear in the HTTP server response.  Also, unlike the other browsers, <strong>Firefox users first see the page without the embedded font <em>until</em> the font is loaded completely</strong>, at which time the fonts suddenly appear on the page. While it can be argued that this is a good thing (the user can read the content immediately without having to rely on the special font), this may not what a web designer would consider desirable.</li>
</ul>
<p>There are a few more differences, which are better outlined at the <a href="http://webfonts.info/wiki/index.php?title=Main_Page">Web Fonts</a> Wiki, which seems to keep its information up-to-date.</p>
<h2>How to choose which fonts to use</h2>
<p>Not having gone to design school, I cannot claim to be an authority on this subject, but I think it is safe to say that when choosing the fonts that you are going to use, it should be in sync with the mood and message you want readers to experience.  Chuck Green&#8217;s article, <a href="http://www.ideabook.com/tutorials/typography/type_palettes.html">Type palettes</a>, goes into more depth on this subject, and Michael Martin of Smashing Magazine has a great article about <a href="http://www.smashingmagazine.com/2009/08/20/typographic-design-survey-best-practices-from-the-best-blogs/">Typographic Design Patterns and Best Practices</a>.  Although both of these articles don&#8217;t go into font-embedding specifically, they are still relevant reading.</p>
<p>It took me a long time to decide on the fonts I have used here on my blog. When designing the layout, I was going for two things:</p>
<ol>
<li>I wanted the body text to be easy to read</li>
<li>I wanted the feeling of the whole blog to be friendly and not look like an academic paper</li>
</ol>
<p>In the end I decided to use:</p>
<ol>
<li><a href="http://www.fonts.info/info/press/free-fonts-for-font-face-embedding.htm">GrauBlau Web</a> for the headers because it is narrow (which allows more text on a line), easy on the eyes, and since it is used on headers, the user notices it right away and thinks &#8220;Hey, this looks different!&#8221;.</li>
<li><a href="http://www.droidfonts.com/info/droid-sans-fonts/">Droid Sans</a> for the main text because it was designed to be easy to read even on low resolutions and, in combination with GrauBlau Web, gave the site a nice, pleasant and friendly look.</li>
<li><a href="http://www.droidfonts.com/info/droid-sans-mono-fonts/">Droid Sans Mono</a> for the code listings since it was designed to compliment Droid Sans, and, I believe, looks a jillion times better than Courier (which everyone up to now has been forced to use due to a lack of nice looking monospace fonts installed on most computers today).</li>
</ol>
<p>Again, I didn&#8217;t go to design school, but I think for the type of site this is (a blog about web technology), it suits its purpose rather well.   I <strong>was</strong> tempted to choose more ornate fonts, but I didn&#8217;t think they suited the content.</p>
<h2>Optimizing Font Files</h2>
<p>Sometimes you may find that the font files are a little larger than you&#8217;d like.  If you open up the font file in <a href="http://fontforge.sourceforge.net/">FontForge</a>, you may find that a lot of the glyphs inside are not necessary for what you are doing (for example, if your pages are all in English, you might not want all the accented characters that the font contains).  Use FontForge to delete the glyphs you don&#8217;t need and regenerate the font &#8211; you&#8217;ll see that you save quite a few kilobytes, especially in a Unicode font with lots of Japanese and Russian characters included.</p>
<p>Again, because of licensing issues, please ensure that the font license allows you to edit the font in this manner.</p>
<h2>Conclusion</h2>
<p>What is written here is just the tip of the iceberg.  In the next few years, I expect to be reading several articles on the best way to use embedded fonts, from technical, usability, internationalization and design perspectives. Unfortunately, I also expect to see a lot of MySpace pages looking uglier than ever.  Imagine! Now, teenagers around the world can have animated backgrounds, Black Eyed Peas songs playing on load, <strong>and</strong> have that <a href="http://www.fontsquirrel.com/fonts/junkos-typewriter">crazy typewriter font</a> on the main copy.</p>
<p>My God, what have we done &#8230;.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1368px; width: 1px; height: 1px;">http://webfonts.info/wiki/index.php?title=Fonts_available_for_%40font-face_embedding</div>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/09/20/font-face-in-depth/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Optimizing PNG Files, for both Web and Print.</title>
		<link>http://www.useragentman.com/blog/2009/09/16/optimizing-png-files-for-both-web-and-print/</link>
		<comments>http://www.useragentman.com/blog/2009/09/16/optimizing-png-files-for-both-web-and-print/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 04:06:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Images]]></category>
		<category><![CDATA[firefox screengrab]]></category>
		<category><![CDATA[image optimization]]></category>
		<category><![CDATA[png. compression]]></category>

		<guid isPermaLink="false">http://www.useragentman.com/blog/?p=3</guid>
		<description><![CDATA[Optimizing images is not only important for web applications, it is also important for reducing the size of print documents. This article will show how to optimize images in the PNG format.]]></description>
			<content:encoded><![CDATA[<div id="attachment_206" class="wp-caption alignleft" style="width: 238px;"><a href="/blogs/wpdev/files/2009/02/shrinkingman.jpg"><img class="size-medium wp-image-206" src="/images/test/shrinkingman-228x300.jpg" alt="" width="228" height="300" /></a></p>
<p class="wp-caption-text">The script included in this post can shrink your images down for easy handling.</p>
</div>
<p>Optimizing images is not only important for web applications, it is also important for reducing the size of print documents (e.g. Word Documents, PDFs, etc). This size is important not only when emailing them out, but also when embedding them into documents that you will be sharing with others.</p>
<p>PNGs should be used for drawn images and screenshots (for photographs, it is better to use the JPEG file format).  It uses a lossless compression algorithm, so what you save in your graphics editor is exactly what your users will see.  It also supports features like <a href="http://en.wikipedia.org/wiki/Alpha_channel">alpha channeling</a>.</p>
<p>This article will show how to optimize images in this format.</p>
<h2>A case study: Optimizing Screenshots</h2>
<p>There are many times a web developer will need to produce screenshots of the work they do to send to clients. When I need to do this, I use the excellent <a title="Screengrab homepage." href="http://www.screengrab.org/"><span style="color: #888888;">Screengrab Firefox Addon</span></a>, since it is so easy to use. I will first talk about how to take screenshots using this tool, and in the next section, talk about how to optimize the PNG files they produce. (<strong>Note:</strong> If you need to take screenshots using Internet Explorer, I would suggest using The GIMP’s screenshot feature to do this. There is a great <a href="http://www.nwe.ufl.edu/writing/help/graphics/gimp/screenshots.shtml"> simple tutorial on how to do screenshots with the GIMP</a> at the <a href="http://www.nwe.ufl.edu/writing/"><span>The Networked Writing Environment at the University of Florida</span></a> website).</p>
<h3>Using Screengrab</h3>
<p>After you install this tool, all you have to do is right click the document you want to take a screenshot of and you will get the following menu.</p>
<div id="attachment_59" class="wp-caption aligncenter" style="width: 310px;"><a href="http://dt09101.mtsallstream.com/blogs/files/2009/02/screengrab.jpg"><br />
<img class="size-medium wp-image-59" src="/images/test/screengrab-300x132.jpg" alt="" width="300" height="132" /></a></p>
<p class="wp-caption-text">Right-click any web page<br />
to produce a screen capture of any page.</p>
</div>
<h3>How to reduce image data size</h3>
<p>I created <a href="/public/scripts/compressingImagesEffectively.zip">a script</a> that would reduce this file size as much as possible. How does this script work:</p>
<ol>
<li>It first uses <a title="The Imagemagick home page." href="http://www.imagemagick.org/script/index.php">ImageMagick </a> to reduce the amount of colour-palette inside the image to 256, since Screengrab will usually create 16-bit images (which have millions of colours).  This usually results in 25% reduction of the size of the image and the extra colours aren’t missed when these images are inside a Word Document because the physical dimensions of these images are smaller than the actual page itself.</li>
<li>It then uses two command line tools, <a title="optipng homepage. " href="http://optipng.sourceforge.net/">optipng</a> and <a title="AdvanceCOMP homepage, which advpng is a part of." href="http://advancemame.sourceforge.net/comp-readme.html"> advpng</a>, to compress the image further. It uses these programs in a variety of ways to see which is the most optimal, and saves the smallest result. This usually results to a further 30-40% reduction is data size.</li>
</ol>
<p>Together, it is possible to reduce an image to 50-70% of it’s original size. Not bad for a script done in my spare time.</p>
<p>An <a href="/public/scripts/compressingImagesEffectively.zip">archive with this script and supporting files</a> is available here. This archive includes:</p>
<ul>
<li>reduceColours: the script that reduces the images to 256 colours.</li>
<li>compressPng: the script that optimizes the PNG image</li>
<li>optimizeImagesForPrint: the script that executes reduceColours and compressPng in one step.</li>
<li>optipng.exe and advpng.exe, the actual file compressors used by compressPng.</li>
</ul>
<p>Note that in order to use this script under Windows, you must have Cygwin installed on your machine. If you don’t know how to do this, read <a title="A step-by-step how-to to installing Cygwin." href="http://www.soe.ucsc.edu/%7Eyou/notes/cygwin-install.html"> Installing Cygwin</a>. Make sure you install ImageMagick using the Cygwin installer, since is needed for the reduceColours script.</p>
<p>If you run Mac OS X, Linux, FreeBSD or any other UNIX variant, you should be able to run this script as long as you are comfortable with the command line.  Note that you will have to download optipng and advpng separately, since the archive only contains the Windows binaries of these programs.</p>
<p>To run the optimizer, use the following syntax inside a bash shell:</p>
<blockquote class="shell">
<pre>optimizeImagesForPrint &lt;imageList&gt;</pre>
</blockquote>
<p>It will create a directory called optimized that will contain all the optimized images. If you just want to reduce the images to 256 colours, or optimize 16-bit images without reducing the colours, use reduceColours and compressPng in the same manner.</p>
<h2>Conclusions</h2>
<p>Even though this article has focused on embedding PNG images into documents, the ideas here can be used when optimizing PNGs for the web.  There may be cases where you don&#8217;t want to reduce the amount of colours &#8212; feel free to change the script to do that.</p>
<p>Please let me know if you find any bugs or if you find other/better ways to optimize images.</p>
<p><a title="PNG Image Compression Script." href="/public/scripts/compressingImagesEffectively.zip"><br />
The scripts are available here in a handy zip archive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.useragentman.com/blog/2009/09/16/optimizing-png-files-for-both-web-and-print/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
