﻿<?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>Travis Miller</title>
	<atom:link href="http://www.electrumdigital.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.electrumdigital.com</link>
	<description>Web Developer for Hire</description>
	<lastBuildDate>Mon, 25 Jan 2010 17:32:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hiding Wordpress page links</title>
		<link>http://www.electrumdigital.com/2010/01/hiding-wordpress-page-links/</link>
		<comments>http://www.electrumdigital.com/2010/01/hiding-wordpress-page-links/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 17:23:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=306</guid>
		<description><![CDATA[When developing a custom Wordpress theme, it's necessary to provide prev/next navigation wherever there might be more than one page of posts: the main index, search results pages, and archive pages, for example.
posts_nav_link() provides the simplest way to do this—it automatically displays either or both of the links, as needed. If you need more control [...]]]></description>
			<content:encoded><![CDATA[<p>When developing a custom Wordpress theme, it's necessary to provide prev/next navigation wherever there might be more than one page of posts: the main index, search results pages, and archive pages, for example.</p>
<p><a href="http://codex.wordpress.org/Template_Tags/posts_nav_link" class="external">posts_nav_link()</a> provides the simplest way to do this—it automatically displays either or both of the links, as needed. If you need more control over the markup, <a href="http://codex.wordpress.org/Template_Tags/next_posts_link" class="external">next_posts_link()</a> and <a href="http://codex.wordpress.org/Template_Tags/previous_posts_link" class="external">previous_posts_link()</a> let you display them independently.</p>
<p><span id="more-306"></span></p>
<p>Typical usage goes something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager-prev&quot;</span>&gt;&lt;?php next_posts_link<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'&amp;laquo; Older Entries'</span><span style="color: #66cc66;">&#41;</span>; ?&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager-next&quot;</span>&gt;&lt;?php previous_posts_link<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Newer Entries &amp;raquo;'</span><span style="color: #66cc66;">&#41;</span>; ?&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></div></div>

<p>But there's a problem here. What if a single page of results is being displayed? Wordpress will render an empty pager:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager-prev&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pager-next&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></pre></div></div>

<p>In my latest Wordpress theme (the one you're looking at right now), this was throwing off my layout in some browsers. Despite enormous progress in browser standardization, there are still inconsistencies in the way browsers handle empty elements. Some will reserve vertical space for the element; some won't. Some will respect any margins that have been specified for the element; some won't.</p>
<p>Ideally, we simply wouldn't render a pager at all if one isn't needed.</p>
<p>Surprisingly, Wordpress doesn't offer a simple way to determine whether the current query result spans multiple pages. There's <a href="http://codex.wordpress.org/Conditional_Tags#A_Paged_Page" class="external">is_paged()</a>, but it always returns false for the first page of results, so it won't work.</p>
<p>Fortunately, <a href="http://codex.wordpress.org/Function_Reference/WP_Query" class="external">$wp_query</a> provides the information we need:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">found_posts</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'posts_per_page'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// show pager</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This seems to work well so far!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2010/01/hiding-wordpress-page-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New look! Same great taste!</title>
		<link>http://www.electrumdigital.com/2010/01/new-look-same-great-taste/</link>
		<comments>http://www.electrumdigital.com/2010/01/new-look-same-great-taste/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 02:33:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Site News]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=304</guid>
		<description><![CDATA[If you've been here before, you'll notice that things just got a bit spiffier.
There are still some layout quirks in Internet Explorer—I'm working on it.
Let me know what you think!
]]></description>
			<content:encoded><![CDATA[<p>If you've been here before, you'll notice that things just got a bit spiffier.</p>
<p>There are still some layout quirks in Internet Explorer—I'm working on it.</p>
<p>Let me know what you think!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2010/01/new-look-same-great-taste/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Check out my new Flash game site</title>
		<link>http://www.electrumdigital.com/2009/11/check-out-my-new-flash-game-site/</link>
		<comments>http://www.electrumdigital.com/2009/11/check-out-my-new-flash-game-site/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 16:09:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Site News]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=272</guid>
		<description><![CDATA[If you find yourself with a few minutes to kill, check out Plastic Lounge, my new Flash gaming site. There are already hundreds of free games available, and I have hundreds more to add as time allows.
Honest feedback is always welcome—it helps me to provide a better site. Hope you find something you like!
]]></description>
			<content:encoded><![CDATA[<p>If you find yourself with a few minutes to kill, check out <a href="http://www.plasticlounge.com/">Plastic Lounge</a>, my new Flash gaming site. There are already hundreds of free games available, and I have hundreds more to add as time allows.</p>
<p>Honest feedback is always welcome—it helps me to provide a better site. Hope you find something you like!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/11/check-out-my-new-flash-game-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The $300,000,000 Button</title>
		<link>http://www.electrumdigital.com/2009/10/the-300000000-button/</link>
		<comments>http://www.electrumdigital.com/2009/10/the-300000000-button/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 17:19:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Design & User Experience]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=267</guid>
		<description><![CDATA[If you think that usability, information architecture, and user experience design are made-up disciplines for lily-gilding aesthetes, with little practical bearing on your Web site, think again.
Jared Spool explains how changing one button in a site's checkout process increased sales by $300 million per year. (He doesn't name the retailer in the article, but it [...]]]></description>
			<content:encoded><![CDATA[<p>If you think that usability, information architecture, and user experience design are made-up disciplines for lily-gilding aesthetes, with little practical bearing on your Web site, think again.</p>
<p>Jared Spool <a href="http://www.uie.com/articles/three_hund_million_button/">explains how changing one button in a site's checkout process</a> increased sales by $300 million per year. (He doesn't name the retailer in the article, but it starts with "A" and ends with "mazon.com".)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/the-300000000-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ellipses and interrobangs and em-dashes, oh my!</title>
		<link>http://www.electrumdigital.com/2009/10/ellipses-and-interrobangs-and-em-dashes-oh-my/</link>
		<comments>http://www.electrumdigital.com/2009/10/ellipses-and-interrobangs-and-em-dashes-oh-my/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 23:06:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Design & User Experience]]></category>
		<category><![CDATA[entities]]></category>
		<category><![CDATA[typography]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=150</guid>
		<description><![CDATA[Typography is one of the most overlooked aspects of Web design—and I'm not talking about fonts, kerning, and x-heights. I'm talking about proper use of glyphs—the individual letters, numerals, and (especially) punctuation marks that make up all written text. There are proper and improper ways to use each glyph&#8212;and even large, well-funded websites often get [...]]]></description>
			<content:encoded><![CDATA[<p>Typography is one of the most overlooked aspects of Web design—and I'm not talking about fonts, kerning, and x-heights. I'm talking about proper use of glyphs—the individual letters, numerals, and (especially) punctuation marks that make up all written text. There are proper and improper ways to use each glyph&#8212;and even large, well-funded websites often get it wrong.</p>
<p>This isn't surprising—even if a site's designer is trained in the specialized discipline of typography (which is unlikely), the person who actually marks up the content (or pastes it into the content management system) probably isn't. But the fact remains that poor typography is one of the most common and most easily avoided blemishes on the web.</p>
<p><span id="more-150"></span>
<p>Am I being pedantic? You may think so—but I encourage you to hear me out and give it a try. I think your pages will read more easily, and look more professional and consistent. Even if readers aren't consciously aware of the typographical subtleties, they <em>do</em> increase a text's ability to communicate—that's why the conventions were devised in the first place.</p>
<p>Rather than reinventing the wheel, I'll simply point you to <a href="http://www.alistapart.com/articles/emen/">A List Apart's excellent article</a> on the subject, with a few addenda of my own:</p>
<ul>
<li>
<p>As the <acronym title="A List Apart">ALA</acronym> article explains, a hyphen is not an em-dash or an en-dash. The hyphen is <em>also</em> not a minus sign&#8212;there's a separate glyph for that. It's <code class="html">&#38;#8722;</code>.</p>
<p>Similarly, the lowercase letter x is not a multiplication symbol&#8212;that's <code class="html">&#38;#215;</code>.</p>
<p>These glyphs are designed to align well with numerals and with each other. Here's the vernacular version:</p>
<p>
<blockquote>9 + 3 - 4 x 2</p></blockquote>
<p>And here's the correct version:</p>
<p>
<blockquote>9 + 3 &#8722; 4 &#215; 2</p></blockquote>
<p>Which one looks best to you?</p>
<p>(If you're looking for the division symbol, that's <code class="html">&#38;#247;</code>.)</p>
</li>
<li>
<p>When marking up vulgar fractions (<span lang="la">i.e.</span>, those in which the numerator and denominator are separated by a diagonal line, as in "1&#8260;2"), use the fraction slash (<code class="html">&#38;#8260;</code>) rather than the regular slash.</p>
</li>
<li>
<p>If you're using Windows, you can type exotic characters by holding down Alt and typing the character's <a href="http://en.wikipedia.org/wiki/Windows-1252#Codepage_layout">four-digit code</a> on the keypad. For example, Alt+0151 produces an em-dash.</p>
</li>
<li>
<p>If you're marking up foreign words (or English words, for that matter) which contain diacritics (commonly known as "accent marks"), then <em><a href="http://www.elizabethcastro.com/html/extras/entities.html#html">include the diacritics</a></em>! They aren't just there for decoration&#8212;they're part of the word's spelling, and if you get them wrong, you've misspelled the word as surely as if you'd substituted one letter for another. It's "jalape&#241;o", not "jalapeno"; "saut&#233;", not "saute"; "f&#234;te", not "fete".</p>
</li>
</ul>
<p>Granted, useful content and a solid technical foundation are more critical to a site's success than proper use of em-dashes—but every whole is the sum of a thousand details, and good typographical habits will become second nature after a short while.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/ellipses-and-interrobangs-and-em-dashes-oh-my/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Password Security for Web Applications 101</title>
		<link>http://www.electrumdigital.com/2009/10/password-security-for-web-applications-101/</link>
		<comments>http://www.electrumdigital.com/2009/10/password-security-for-web-applications-101/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 22:34:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=223</guid>
		<description><![CDATA[User registration and login is a standard feature on interactive Web sites, and passwords are the standard way to protect those accounts. But a password is only effective as long as it's kept secret—and you might not be doing everything you can to protect yours.
Let's say you've finished building the HTML and the server-side validation [...]]]></description>
			<content:encoded><![CDATA[<p>User registration and login is a standard feature on interactive Web sites, and passwords are the standard way to protect those accounts. But a password is only effective as long as it's kept secret—and you might not be doing everything you can to protect yours.</p>
<p>Let's say you've finished building the <acronym title="HyperText Markup Language">HTML</acronym> and the server-side validation code for your registration form, and you're now ready to write the code which stores the user's information (probably in a database). How should you handle the password?</p>
<p><span id="more-223"></span></p>
<p>The most obvious approach is to store it as just another column in the user table, with no special consideration. Many novice developers do exactly this—after all, you need access to the database to view the contents of the user table, so the passwords are protected, right?</p>
<p>But what happens when an attacker <em>gains</em> access to your database—for example, by guessing or intercepting your phpMyAdmin password? They have instant access to all of your user's passwords without even trying.</p>
<p>(Perhaps your application is trivial, and your users' accounts don't provide access to anything sensitive—who <em>cares</em> if an attacker gets their passwords? Well, many people use the same password for <em>all</em> of their accounts—email, bank accounts, and so forth. Our hypothetical attacker might not be able to do much damage on <em>your</em> site—but if the email addresses and passwords he just obtained allow him to gain access to other, more sensitive accounts, then you have a problem.)</p>
<p>Encrypting the password before storing it in the database is the obvious solution to this problem. Simply run it through your favorite encryption algorithm, and save the encrypted version; when the user logs in, just decrypt it to check the entered password.</p>
<p>This is also the <em>wrong</em> solution to the problem. An attacker who has access to your database probably has access to your file system, as well—which means they can easily find your encryption code and any keys it may use. Your encryption is useless in this case.</p>
<p>(Whatever you do, don't write your own home-brew encryption function, or run the password through a series of different encryption algorithms and arbitrary transformations, thinking this will make it more secure. It won't. In fact, this approach may leave telltale mathematical traces in the ciphertext which will make it <em>easier</em> for a skilled attacker to compromise your system. Leave the design of encryption algorithms to the experts.)</p>
<p>A better method is to <a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function">hash</a> the password, rather than encrypting it. Hashing is a form of one-way encryption: converting a password to a hash is easy, but reconstituting the password from the hash is mathematically impossible. Think of a trap door, or running a steak through a meat grinder—once something has gone through a hash function, it can't go back.</p>
<p>(Since the original string can't be reconstituted, hashing technically <em>isn't</em> encryption, no matter what anyone may tell you. I merely described it as such for illustrative purposes.)</p>
<p>But if we aren't storing the password in a way that can be decrypted, how can we check it when the user tries to log in?</p>
<p>Simple: hash the password entered on the login form, and compare that to the hashed password stored in the database. If the two hashes are the same, we know that the user entered the correct password.</p>
<p>(Incidentally, this is why many systems can't tell you your password when you forget it—they don't <em>know</em> your password. They only know its hash value. These systems typically handle forgotten passwords by asking you to choose a new one. Any system which <em>is</em> capable of providing your password on demand must be using some kind of reversible encryption—or, God forbid, storing it in plaintext—and should be considered less secure.)</p>
<p>PHP's <code class="php"><a href="http://php.net/md5">md5()</a></code> function is the standard hash function used for this purpose, but I prefer the more cryptographically robust <a href="http://php.net/sha1">sha1()</a>.</p>
<p>This is a lot better than our original system, and it's good enough for many applications. But our system still has a weakness.</p>
<p>Again, assume that an attacker has access to our database (and therefore our password hashes). Though he can't convert the hashes back into passwords, he knows that most people choose plain English words, or minor combinations and permutations thereof, for their passwords.</p>
<p>It's easy to generate a table of English words and their corresponding hashes (known as a <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow table</a>). With this in hand, an attacker simply has to compare your password hashes to the rainbow table until he finds a match. There are even <a href="http://gdataonline.com/seekhash.php">pregenerated rainbow tables</a> online.</p>
<p>(This is why good systems encourage you—or even <em>force</em> you—to choose complex passwords which don't appear in dictionaries. Generating a hash table based on an English dictionary is easy; generating one for every possible password-length string of ASCII characters is effectively impossible.)</p>
<p>For kicks, I once ran about 15,000 real-world password hashes (from a system I administrated) against the above-linked rainbow table. I was able to crack about two-thirds of them. Clearly, this is a serious vulnerability for any system which needs high security.</p>
<p>Fortunately, there's a simple and elegant solution: <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29">salt</a> your passwords before hashing them, by concatenating them with a randomly generated string.</p>
<p>For example, let's say the user has chosen "ravens" as their password. If we simply hash this, it will be vulnerable to even the most basic rainbow attack.</p>
<p>So, instead, we'll generate a random string, four to ten characters long. (This is arbitrary; a few characters is sufficient.) This is known as the salt. (For convenience, I like to restrict my salts to printable ASCII characters.) Let's say our random-salt-generating function returns this:</p>
<p><code>^p]K~7</code></p>
<p>We prepend the salt to the password, and get:</p>
<p><code>^p]K~7ravens</code></p>
<p>Finally, we hash that string, and store the hash <em>and</em> the salt in the database. To check login passwords, we simply repeat the process (retrieving the original salt from the database, rather than generating it anew), and compare the hashes as before.</p>
<p>We've effectively turned a vulnerable, low-strength password into a strong one. Yes, our attacker can see the salt, and he could generate a rainbow table based on English words prefixed with that salt. But since the salt is different for every user, he'd have to generate a separate rainbow table <em>for every user</em>. The costs in time and storage space are prohibitive.</p>
<p>All of this may seem complex at first, but you're really only dealing with two database fields (the hash and the salt) and a couple of functions: one to generate a random salt, and one which accepts a plaintext password and a salt and computes the hash. Here's some sample code.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> generate_salt<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #990000;">rand</span><span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$salt</span> <span style="color: #339933;">.=</span> <span style="color: #990000;">chr</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">rand</span><span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">33</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">126</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$salt</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> hash_password<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$password</span><span style="color: #339933;">,</span> <span style="color: #000088;">$salt</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$password</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// for user registration, do something like this</span>
<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> getPasswordFromRegistrationForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$users_pw_salt</span> <span style="color: #339933;">=</span> generate_salt<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$users_pw_hash</span> <span style="color: #339933;">=</span> hash_password<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$password</span><span style="color: #339933;">,</span> <span style="color: #000088;">$users_pw_salt</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// store $users_pw_salt and $users_pw_hash; forget $password</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// and for user login, do this</span>
<span style="color: #000088;">$users_pw_salt</span> <span style="color: #339933;">=</span> getUsersPasswordSaltFromDatabase<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$users_pw_hash</span> <span style="color: #339933;">=</span> getUsersPasswordHashFromDatabase<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$entered_password</span> <span style="color: #339933;">=</span> getPasswordFromLoginForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> hash_password<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$entered_password</span><span style="color: #339933;">,</span> <span style="color: #000088;">$users_pw_salt</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$users_pw_hash</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// the correct password was entered</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// the password was incorrect</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/password-security-for-web-applications-101/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conditional comments for iPhone</title>
		<link>http://www.electrumdigital.com/2009/10/conditional-comments-for-iphone/</link>
		<comments>http://www.electrumdigital.com/2009/10/conditional-comments-for-iphone/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 19:31:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Browser Issues]]></category>
		<category><![CDATA[XHTML & CSS]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[safari]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=217</guid>
		<description><![CDATA[You're probably familiar with IE's conditional comments. They allow us to feed special code to that special browser to overcome its many bugs and deficiencies.
Is there something similar for iPhone? Not exactly, but we can achieve the same end:

&#60;!--[if !IE]&#62;&#60;!--&#62;
	&#60;link media=&#34;only screen and (max-device-width: 480px)&#34; href=&#34;iphone.css&#34; type=&#34;text/css&#34; rel=&#34;stylesheet&#34; /&#62;
&#60;!--&#60;![endif]--&#62;


Some versions of IE will apply stylesheets [...]]]></description>
			<content:encoded><![CDATA[<p>You're probably familiar with <acronym title="Internet Explorer">IE</acronym>'s <a href="http://www.quirksmode.org/css/condcom.html">conditional comments</a>. They allow us to feed special code to that special browser to overcome its many bugs and deficiencies.</p>
<p>Is there something similar for iPhone? Not exactly, but we can achieve the same end:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--[if !IE]&gt;&lt;!--&gt;</span>
	<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">media</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;only screen and (max-device-width: 480px)&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;iphone.css&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #808080; font-style: italic;">&lt;!--&lt;![endif]--&gt;</span></pre></div></div>

<p><span id="more-217"></span></p>
<p>Some versions of <acronym title="Internet Explorer">IE</acronym> will apply stylesheets regardless of the <code class="html">media</code> attribute, so the conditional comments are here merely to tell <acronym title="Internet Explorer">IE</acronym> <em>not</em> to use this code.</p>
<p>As for the value of the <code class="html">media</code> attribute: not all browsers understand the "only" keyword; they will simply ignore this line. Of those that <em>do</em> understand it, the only one width a max-device-width of 480px is the iPhone.</p>
<p>(So I'm told. I'm taking all of this on faith. But it seems to work.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/conditional-comments-for-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulating HTML5&#039;s placeholder attribute with jQuery</title>
		<link>http://www.electrumdigital.com/2009/10/simulating-html5s-placeholder-attribute-with-jquery/</link>
		<comments>http://www.electrumdigital.com/2009/10/simulating-html5s-placeholder-attribute-with-jquery/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 20:51:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[AJAX & JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[placeholder]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=191</guid>
		<description><![CDATA[I recently discussed the placeholder attribute in HTML5. Today, I needed exactly such a behavior for a site I'm working on, so I knocked together a reusable, unobtrusive solution with jQuery.

Simply include this code (and jQuery, of course) on your page, and assign the placeholder text as the title attribute of the control. Example:

&#60;input type=&#34;text&#34; [...]]]></description>
			<content:encoded><![CDATA[<p>I recently <a href="http://www.electrumdigital.com/2009/10/forms-in-html5/">discussed</a> the <code class="html">placeholder</code> attribute in <acronym title="HyperText Markup Language">HTML</acronym>5. Today, I needed exactly such a behavior for a site I'm working on, so I knocked together a reusable, unobtrusive solution with jQuery.</p>
<p><span id="more-191"></span></p>
<p>Simply include this code (and jQuery, of course) on your page, and assign the placeholder text as the <code class="html">title</code> attribute of the control. Example:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;keywords&quot;</span> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Search&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>The script also assigns the class <code class="css">placeholder</code> to the control when the placeholder text is present, so you can style it differently if you like (for example, you may wish to gray out the text).</p>
<p>The code:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * Unobtrusively set up placeholder behaviors on all text inputs for which
 * the title attribute has been set. The title text will be used as the
 * placeholder text.
 * @author Travis Miller
 * @link http://www.electrumdigital.com/
 */</span>
$<span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;input[type=text][title]&quot;</span><span style="color: #009900;">&#41;</span>
        .<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            showPlaceholder<span style="color: #009900;">&#40;</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// initialize each control on page load</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>
        .<span style="color: #000066;">blur</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            showPlaceholder<span style="color: #009900;">&#40;</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>
        .<span style="color: #000066;">focus</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> $input <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> $input.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> $input.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;title&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                $input.<span style="color: #660066;">removeClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;placeholder&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                $input.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">function</span> showPlaceholder<span style="color: #009900;">&#40;</span> $input <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> placeholderText <span style="color: #339933;">=</span> $input.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;title&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> $input.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">&quot;&quot;</span> <span style="color: #339933;">||</span> $input.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> placeholderText <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            $input.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;placeholder&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            $input.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>placeholderText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/simulating-html5s-placeholder-attribute-with-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forms in HTML5</title>
		<link>http://www.electrumdigital.com/2009/10/forms-in-html5/</link>
		<comments>http://www.electrumdigital.com/2009/10/forms-in-html5/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 18:19:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[XHTML & CSS]]></category>
		<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=163</guid>
		<description><![CDATA[The HTML5 spec continues to grind inexorably toward publication. I've just spent a while with the latest draft, and at least with respect to forms, I like what I see. Here's a roundup.

(Most of these features are in "Last call for comments" status, so it's likely they'll make the final spec, but everything you're about [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://dev.w3.org/html5/spec/">The <acronym title="HyperText Markup Language">HTML</acronym>5 spec</a> continues to grind inexorably toward publication. I've just spent a while with the latest draft, and at least with respect to <a href="http://dev.w3.org/html5/spec/forms.html#forms">forms</a>, I like what I see. Here's a roundup.</p>
<p><span id="more-163"></span></p>
<p>(Most of these features are in "Last call for comments" status, so it's likely they'll make the final spec, but everything you're about to read is subject to change.)</p>
<ul>
<li>
<p>A couple of the new features are little more than <abbr title="User Interface">UI</abbr> sugar, but they're welcome nonetheless. The <code class="html"><a href="http://dev.w3.org/html5/spec/Overview.html#attr-fe-autofocus">autofocus</a></code> attribute does what it says on the tin. The <code class="html"><a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-placeholder">placeholder</a></code> attribute will display a hint value in a control&#8212;<abbr lang="la" title="exempli gratia">e.g.</abbr>, "you@example.com" in an email field&#8212;which will disappear when the control receives focus.</p>
<p>No more crappy little scripts just to implement these simple <abbr title="User Interface">UI</abbr> behaviors&#8212;a few keystrokes, and you're done!</p>
</li>
<li>
<p>The <code class="html"><a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-autocomplete">autocomplete</a></code> attribute (already implemented by some browsers, including Firefox) will allow us to control whether the browser attempts autocompletion of a particular field. Disabling autocompletion is useful when you don't want a particular value (such as a bank customer's username) to be easily discoverable, or when dealing with a one-time entry (such as a <acronym title="Completely Automated Public Turing Test to Tell Computers and Humans Apart">CAPTCHA</acronym>) where it makes little sense to remember the input value.</p>
<p>Its natural partner is the <code class="html"><a href="http://dev.w3.org/html5/spec/Overview.html#the-list-attribute">list</a></code> attribute, which will allow us to suggest possible values for the control. Presumably user agents will be free to implement this as type-ahead autocompletion (<span lang="fr">&#224; la</span> Google), as a <a href="http://en.wikipedia.org/wiki/Combo_box">combo box</a>, or in any other way they see fit.</p>
</li>
<li>
<p>There's a whole slew of new <code class="html">&lt;input /&gt;</code> types, including <a href="http://dev.w3.org/html5/spec/Overview.html#date-state">calendars</a>, <a href="http://dev.w3.org/html5/spec/Overview.html#color-state">color pickers</a>, <a href="http://dev.w3.org/html5/spec/Overview.html#number-state">numbers</a>, <a href="http://dev.w3.org/html5/spec/Overview.html#e-mail-state">email addresses</a>, and <a href="http://dev.w3.org/html5/spec/Overview.html#url-state"><acronym title="Uniform Resource Locator">URL</acronym>s</a>, among <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-type">others</a>.</p>
<p>This dovetails nicely with <a href="http://dev.w3.org/html5/spec/forms.html#constraint-validation">the new form validation model</a>, which<br />
(in addition to enforcing syntax for values such as email addresses and <acronym title="Uniform Resource Locator">URL</acronym>s) will allow us to <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-required">require a value</a>, test it against <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-pattern">an arbitrary regular expression</a>, and restrict numeric values to <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-min">a specified range</a> and/or <a href="http://dev.w3.org/html5/spec/Overview.html#attr-input-step">a specified granularity</a>.</p>
</li>
<li>
<p><a href="http://dev.w3.org/html5/spec/interactive-elements.html#menus">Menus</a>, of both the standard and context varieties.</p>
<p>Individual menu items (and buttons, and other <acronym title="User Interface">UI</acronym> elements) will be associated with <code class="html"><a href="http://dev.w3.org/html5/spec/interactive-elements.html#the-command">&lt;command&gt;</a></code> elements. Presumably&#8212;I haven't thoroughly reviewed this part yet&#8212;triggering a menu item or other control will fire a DOM event on the associated command; client-side scripts can register event listeners on the command element, and respond without knowing or caring which element originally triggered the request.</p>
</li>
</ul>
<p>In short, <acronym title="HyperText Markup Language">HTML</acronym>'s role as a document markup language is expanding to include <em>interface</em> markup as well. This is probably as it should be&#8212;there are few pages on the modern web (aside from W3C recommendations and documents repurposed from print) which the existing standards can describe without strain.</p>
<p>Many of the things we now code in JavaScript will be supported natively by browsers&#8212;we'll have to write less code, and users will get a faster, richer, more responsive, and more uniform experience. On the other hand, browsers will continue to grow in size and complexity—especially with the just-in-time JavaScript compilation featured in the latest generation, they're looking less and less like document readers, and more and more like runtime environments for applications.</p>
<p>There will undoubtedly be bugs to contend with in the first generation of <acronym title="HyperText Markup Language">HTML</acronym>5 browsers, but hopefully browser makers have learned the lessons of <acronym title="Internet Explorer 6">IE6</acronym>, and will at least <em>attempt</em> to comply with the spec. We still have a few years before the standard is finalized and widely supported, but (especially once <acronym title="Cascading Style Sheets Level 3">CSS3</acronym> follows suit) it's going to offer some interesting possibilities.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/10/forms-in-html5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Toward Better Buttons</title>
		<link>http://www.electrumdigital.com/2009/09/toward-better-buttons/</link>
		<comments>http://www.electrumdigital.com/2009/09/toward-better-buttons/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 22:31:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[XHTML & CSS]]></category>
		<category><![CDATA[semantic markup]]></category>

		<guid isPermaLink="false">http://www.electrumdigital.com/?p=111</guid>
		<description><![CDATA[I see this a lot:

&#60;input type=&#34;submit&#34; class=&#34;button&#34; value=&#34;Save Changes&#34; /&#62;

Because the &#60;input /&#62; element can represent many things other than a button&#8212;and because many browsers still don't support attribute selectors, such as input[type=button]&#8212;the author has added class="button" for the sole purpose of giving the stylesheet something to match on.
May I suggest a better way?


&#60;button type=&#34;submit&#34;&#62;Save [...]]]></description>
			<content:encoded><![CDATA[<p>I see this a lot:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Save Changes&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Because the <code class="html">&#60;input /&#62;</code> element can represent many things <em>other</em> than a button&#8212;and because many browsers still don't support attribute selectors, such as <code class="css">input[type=button]</code>&#8212;the author has added <code class="html">class="button"</code> for the sole purpose of giving the stylesheet something to match on.</p>
<p>May I suggest a better way?</p>
<p><span id="more-111"></span></p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">button</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span>&gt;</span>Save Changes<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">button</span>&gt;</span></pre></div></div>

<p>Now our stylesheet can simply use the selector <code class="css">button</code>, and we don't have to add any extra classes to our markup. Overall, it makes for cleaner, more concise, and more semantically descriptive code.</p>
<p>That one isn't so bad, but this one is:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;image&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button.gif&quot;</span> <span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Save Changes&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>This is technically valid under <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> 1.0 Transitional, but not under <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> 1.0 Strict, and it's a bad idea in either case.</p>
<p>Why? Because it couples semantics with presentation, and that's exactly the sort of thing <acronym title="Cascading Style Sheets">CSS</acronym> exists to prevent. If the client later decides to replace <code>button.gif</code> with <code>newbutton.jpg</code>&#8212;or wants to change all image buttons to text buttons&#8212;you'll have to edit every page to make the change.</p>
<p>Instead, use this markup:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">button</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span>&gt;</span>Save Changes<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">button</span>&gt;</span></pre></div></div>

<p>...and use your favorite <a href="http://css-tricks.com/css-image-replacement/"><acronym title="Cascading Style Sheets">CSS</acronym> image replacement</a> technique to <a href="http://www.alistapart.com/articles/understandingprogressiveenhancement/">progressively enhance</a> the document for graphical user agents. I typically use something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">button<span style="color: #6666ff;">.submit</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* to suppress default button styling */</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* to suppress default button styling */</span>
    <span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000;">&quot;button.gif&quot;</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">128px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">24px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">text-indent</span><span style="color: #00AA00;">:</span> <span style="color: #933;">-9999px</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* to hide the plain text */</span>
    <span style="color: #000000; font-weight: bold;">outline</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* suppress the dotted hairline border */</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Now you'll only have to edit one file&#8212;the stylesheet. Yes, we've re-introduced classes, but in this case it actually <em>helps</em> us separate concerns. You can define a base <code class="css">button</code> style, and then define styles for <code class="css">button.submit</code>, <code class="css">button.cancel</code>, <code class="css">button.delete</code>, <code class="css">button.help</code>, and so on&#8212;each one pulling in the appropriate <code class="css">background-image</code> and specifying the appropriate dimensions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.electrumdigital.com/2009/09/toward-better-buttons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
