<?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>Web 3.0, 6 Bladed Razors, 7 Minute Abs &#187; History</title>
	<atom:link href="http://www.zachleat.com/web/tag/history/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zachleat.com/web</link>
	<description></description>
	<lastBuildDate>Fri, 09 Dec 2011 21:53:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Emulating onhashchange without setInterval</title>
		<link>http://www.zachleat.com/web/onhashchange-without-setinterval/</link>
		<comments>http://www.zachleat.com/web/onhashchange-without-setinterval/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 06:00:13 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Back Button]]></category>
		<category><![CDATA[History]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=143</guid>
		<description><![CDATA[There is one limitation that all of the major JavaScript browser history management plugins have to hack around: How to tell when there is a change to the location.hash? Sure, you can tell when you&#8217;re modifying the hash yourself, but what if the user hits the back/forward button? YUI&#8217;s History component and Really Simple History [...]]]></description>
			<content:encoded><![CDATA[<p>There is one limitation that all of the major JavaScript browser history management plugins have to hack around:  How to tell when there is a change to the <code>location.hash</code>?  Sure, you can tell when you&#8217;re modifying the hash yourself, but what if the user hits the back/forward button?</p>
<p><a href="http://developer.yahoo.com/yui/history/">YUI&#8217;s History component</a> and Really Simple History both use setInterval with an internal variable to compare and find changes.  But this isn&#8217;t really an optimal solution.  As proper front end engineers, we should avoid timeouts as much as possible.  Internet Explorer 8 will have an <a href="http://msdn.microsoft.com/en-us/library/cc288209(VS.85).aspx">onhashchange event</a> that clients will be able to subscribe to.  That will be nice.  But surely, a cross browser solution without the use of setInterval exists.</p>
<p><strong>Look, a cross browser solution without the use of setInterval:</strong></p>
<ol>
<li>On initialization, we load an iframe onto the page that is positioned absolutely at -500px,-500px so the user can&#8217;t see it. It is a skeleton page that only needs cross browser code to add an &#8220;<code>onscroll</code>&#8221; event, and to be able to calculate the scrolled position of the iframe itself.  For my example, I use jQuery and the dimensions plugin to accomplish this, but it could easily be trimmed down to only the bare essentials (or ported to a different library).</li>
<li>To add an AJAX history entry into the browser&#8217;s history under an assigned hash string, we first add a <code>&lt;a name="hashString"&gt;hashString&lt;/a&gt;</code> to the <code>&lt;body&gt;</code> tag of the iframe.  Using css to increase the size of the a tag proportional to the iframe&#8217;s height, we can guarantee scrolling will happen.</li>
<li>Then, we change the <code>location.hash</code> of the iframe to point to that <code>&lt;a&gt;</code> tag.  This will scroll the iframe to the content, and create a new entry in the browser&#8217;s <code>history</code> object.</li>
<li>Inside the iframe, we have our <code>onscroll</code> event that fires when the scrolling in the previous step took place.  (Minor IE-related workaround: The browser&#8217;s <code>history</code> object is changed, but the hash property doesn&#8217;t when attempting to read it later.  Instead, we find the <code>&lt;a&gt;</code> that matches up with the scrollY/pageOffsetY property inside of the iframe, and retrieve the matching hash from the <code>&lt;a&gt;</code> tag.)</li>
</ol>
<p>The nice thing about this approach is that you don&#8217;t even need a history manager anymore.  This little iframe will do all of your dirty work for you.  And it will even maintain your history alongside any other iframe browsing on the page.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li>Can serve as back button support and full AJAX history manager.</li>
<li>Page Weight: the test page and iframe HTML files together weigh in at 2.76 KB.  That includes the non-jQuery JavaScript needed to do everything.</li>
<li>Cross browser: Tested in FF3, IE7, IE6, Opera 9.5, (not Safari &#8212; see below)</li>
</ul>
<p><strong>Limitations:</strong></p>
<ul>
<li>No bookmarking support.  We aren&#8217;t changing the top hash, we&#8217;re changing the iframe hash, so these aren&#8217;t bookmarkable.</li>
</ul>
<p><strong>Sample Example:</strong></p>
<ul>
<li>
<a href="http://www.zachleat.com/Projects/history/">My Test Page</a></li>
<li><a href="http://www.zachleat.com/Projects/history/history.zip">Download the test page (2 HTML files, and jQuery 1.2.6 and dimensions)</a></li>
</ul>
<p><strong>Update</strong>: Given time for more rigorous testing, it doesn&#8217;t look like Safari supports this approach.  So, until WebKit fixes <a href="https://bugs.webkit.org/show_bug.cgi?id=9166">#9166</a>, we&#8217;ll have to stick to timers in Safari.  A more pragmatic programmer than I might hack around this approach by exploiting <a href="https://bugs.webkit.org/show_bug.cgi?id=19202">#19202</a>, but that certainly wouldn&#8217;t be a long term solution.  I&#8217;ve also updated the test page above, at <a href="http://dean.edwards.name/">Dean Edwards</a> humble request, to support dynamic client size text size changes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/onhashchange-without-setinterval/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

