<?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>No, I am better than that! &#187; AJAX</title>
	<atom:link href="http://rickosborne.org/blog/category/programming/ajax/feed/" rel="self" type="application/rss+xml" />
	<link>http://rickosborne.org/blog</link>
	<description>Striving to subdue the mediocrity.</description>
	<lastBuildDate>Sun, 21 Aug 2011 23:27:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Adding a &#8220;Latest Tweet&#8221; widget to your site</title>
		<link>http://rickosborne.org/blog/2009/05/adding-a-latest-tweet-widget-to-your-site/</link>
		<comments>http://rickosborne.org/blog/2009/05/adding-a-latest-tweet-widget-to-your-site/#comments</comments>
		<pubDate>Tue, 12 May 2009 16:05:16 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/?p=905</guid>
		<description><![CDATA[Let&#8217;s face it: where Ben Nadel goes, many will follow. Including me. When he redesigned his site last weekend, he made his latest Twitter tweet a prominent feature above the fold. I thought that was a good idea, so I set about doing it for mine. Here&#8217;s a quick and simple way to do it [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s face it: where <a href="http://bennadel.com/">Ben Nadel</a> goes, many will follow.  Including me.  When he redesigned his site last weekend, he made his latest Twitter tweet a prominent feature above the fold.  I thought that was a good idea, so I set about doing it for mine.  Here&#8217;s a quick and simple way to do it that&#8217;ll take you less than 15 minutes.</p>
<p>I&#8217;ve done mine with an AJAX gateway so that it is added asynchronously to the page after it finishes loading.  However, you&#8217;ll see that it would be easy enough to include inline using the same framework.  You want to use a gateway not just because of cross-site AJAX issues, but also because you want to rate-limit how often you hit the Twitter API.</p>
<p>The gateway does two things: (1) fetch and cache your latest tweets, and (2) filter them to exclude tweets that wouldn&#8217;t make sense on your site.  Here&#8217;s a very simplified version of the gateway code:</p>
<pre class="coldfusion">&lt;cfsetting enablecfoutputonly="Yes"&gt;
&lt;!---
  twitter-latest.cfm
---&gt;
&lt;cfcontent type="application/xml" reset="true"&gt;
&lt;cfset username     = "yourusername"&gt;
&lt;cfset password     = "yourpassword"&gt;
&lt;cfset agent        = "youremail"&gt;
&lt;cfset apiUrl       = "http://twitter.com/statuses/user_timeline.xml?screen_name=" &amp; username&gt;
&lt;cfset timeoutHours = 0.25&gt;
&lt;cfoutput&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;/cfoutput&gt;
&lt;cflock name="twitter-latest" type="EXCLUSIVE" timeout="5"&gt;
  &lt;cfscript&gt;
  if(structKeyExists(application, "twitter-latest")) twit = application["twitter-latest"];
  else {
    twit = structNew();
    twit.lastUpdate    = createDate(1970,1,1);
    twit.lastTweet     = "";
    twit.lastTweetDate = "";
    twit.lastTweetID   = "";
    application["twitter-latest"] = twit;
  }
  needUpdate = true;
  if(structKeyExists(twit, "lastUpdate") and isDate(twit.lastUpdate) and (dateAdd("h", timeoutHours, twit.lastUpdate) gte now()) and structKeyExists(twit, "lastTweet") and isSimpleValue(twit.lastTweet) and (twit.lastTweet neq ""))
    needUpdate = false;
  &lt;/cfscript&gt;
  &lt;cfif needUpdate&gt;
    &lt;cftry&gt;
      &lt;cfhttp method="GET" url="#apiUrl#" useragent="#agent#" username="#username#" password="#password#"&gt;&lt;/cfhttp&gt;
      &lt;cfscript&gt;
      if (cfhttp.statusCode contains "200") {
        tweets = xmlParse(cfhttp.fileContent);
        statuses = xmlSearch(tweets, "/statuses/status");
        if (isArray(statuses)) {
          for(i = arrayLen(statuses); i gte 1; i = i - 1) {
            status = statuses[i];
            if (not (structKeyExists(status, "in_reply_to_user_id") and isNumeric(status["in_reply_to_user_id"].xmlText))) {
              twit.lastTweet     = xmlFormat(status.text.xmlText);
              twit.lastTweetID   = xmlFormat(status.id.xmlText);
              twit.lastTweetDate = xmlFormat(status.created_at.xmlText);
              twit.lastUpdate    = now();
            }
          } // for i
        } // if statuses
      } // if 200
      &lt;/cfscript&gt;
    &lt;cfcatch&gt;&lt;/cfcatch&gt;
    &lt;/cftry&gt;
  &lt;/cfif&gt;
&lt;/cflock&gt;
&lt;cfif structKeyExists(twit, "lastTweetDate") and structKeyExists(twit, "lastTweetID") and structKeyExists(twit, "lastTweet")&gt;
  &lt;cfoutput&gt;&lt;p twitterdate="#twit.lastTweetDate#" twitterid="#twit.lastTweetID#"&gt;#twit.lastTweet#&lt;/p&gt;&lt;/cfoutput&gt;
&lt;cfelse&gt;
  &lt;cfoutput&gt;&lt;p/&gt;&lt;/cfoutput&gt;
&lt;/cfif&gt;
&lt;cfsetting enablecfoutputonly="No"&gt;</pre>
<p>I&#8217;ve single-threaded the bulk of the code, as well as done something that many consider evil: a try/catch without any error-handling.  However, what useful thing would you do if you encountered an error?</p>
<p>My filter logic is straightforward: don&#8217;t show replies.  If I&#8217;m replying to someone, it probably wouldn&#8217;t mean anything to a random visitor on my website, so why bother showing it?</p>
<p>The AJAX code to add this to your site is even simpler.  I used jQuery, as I&#8217;ve already got it in place on my site, but the vanilla JavaScript version wouldn&#8217;t be much longer.</p>
<pre class="javascript">&lt;script language="JavaScript" defer="defer" type="text/javascript"&gt;
jQuery(document).ready(function(){
  jQuery.get('/ajax/twitter-latest.cfm', {}, function(d){
    var tb = jQuery('#twitter-body');
    if(tb.length == 0) return;
    var tweet = d.firstChild.textContent;
    tweet = tweet.replace(/(https?[:]\/\/[-A-Z0-9a-z./]+)/g, '&lt;a href="$1" rel="nofollow"&gt;$1&lt;/a&gt;');
    tweet = tweet.replace(/@([_A-Z0-9a-z]+)/g, '&lt;a href="http://twitter.com/$1" rel="nofollow"&gt;@$1&lt;/a&gt;');
    tweet = tweet.replace(/#([_A-Z0-9a-z]+)/g, '&lt;/a&gt;a href="http://search.twitter.com/search?q=%23$1" rel="nofollow"&gt;#$1&lt;/a&gt;');
    tb.html(tweet);
  }, 'xml');
});
&lt;/script&gt;</pre>
<p>The <kbd>replace()</kbd> regular expressions do a passable job of auto-linking URLs, Twitter user names, and hash tags.  The URL regex is especially fragile, but since most URLs posted on Twitter are shortened, it&#8217;s good enough.  You could add in more error-checking logic for when Twitter goes down, maybe hiding the Twitter box altogether in such cases.</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2009/05/adding-a-latest-tweet-widget-to-your-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>When is a TR not a table row?</title>
		<link>http://rickosborne.org/blog/2007/04/when-is-a-tr-not-a-table-row/</link>
		<comments>http://rickosborne.org/blog/2007/04/when-is-a-tr-not-a-table-row/#comments</comments>
		<pubDate>Fri, 13 Apr 2007 20:12:47 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/index.php/2007/04/13/when-is-a-tr-not-a-table-row/</guid>
		<description><![CDATA[The answer is: &#8220;it depends on which browser you ask&#8221;. I ran into a quirk in IE6 while debugging some AJAX-related code this afternoon, and I figured I&#8217;d share it. I had some JavaScript code that did something like this: var t = document.createElement('TABLE'); var tb = document.createElement('TBODY'); var tr = document.createElement('TR'); // create table [...]]]></description>
			<content:encoded><![CDATA[<p>The answer is: <em>&ldquo;it depends on which browser you ask&rdquo;</em>.  I ran into a quirk in IE6 while debugging some AJAX-related code this afternoon, and I figured I&#8217;d share it.  I had some JavaScript code that did something like this:</p>
<pre class="javascript">var t = document.createElement('TABLE');
var tb = document.createElement('TBODY');
var tr = document.createElement('TR');
// create table cells with just numbers in them
for (var i = 0; i &lt; 5; i++) {
	var td = document.createElement('TD');
	td.appendChild(document.createTextNode(i));
	tr.appendChild(td);
} // for i
// ... lots of other magic happens here ...
// later, upgrade those cells to links
for (var i = 0; i &lt; 5; i++) {
	var a = document.createElement('A');
	a.href = 'foo.cfm?i=' + i;
	while (tr.cells[i].childNodes.length > 0)
		a.appendChild(tr.cells[i].firstChild);
	tr.cells[i].appendChild(a);
} // for i
// add the completed row to the table body
tb.appendChild(tr);
// add the table body to the table
t.appendChild(tb);</pre>
<p>This worked wonderfully in Firefox and IE7.  But when I flipped over to IE6, it broke hard.  It would get past the line setting the <kbd>href</kbd> for the link, but the <kbd>while</kbd> loop would never execute.</p>
<p>I generally try to wait until the last second to add new elements to the DOM, on the theory that modifying them before they are part of the DOM won&#8217;t cause the browser to re-render them or even notice them.  On a whim, I moved the last two <kbd>appendChild</kbd> lines up above the second <kbd>for</kbd> loop.  Sure enough, IE6 got unbustified.</p>
<p>Apparently, the <kbd>tr</kbd> element wasn&#8217;t being promoted to being an actual table row until I added it to a table.  Before then, it was just an element that happened to have <kbd>tr</kbd> for its name.  Thus, it didn&#8217;t receive the <kbd>cells</kbd> magic until after its promotion.</p>
<p>Tricky, tricky.</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2007/04/when-is-a-tr-not-a-table-row/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Light dawns on marble head</title>
		<link>http://rickosborne.org/blog/2007/03/light-dawns-on-marble-head/</link>
		<comments>http://rickosborne.org/blog/2007/03/light-dawns-on-marble-head/#comments</comments>
		<pubDate>Mon, 26 Mar 2007 21:34:19 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Random]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[School]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/?p=138</guid>
		<description><![CDATA[Ever had one of those weeks where everything seems to be doom and gloom and you are cranky and snarky but you don&#8217;t know why? Then, out of the blue, everything just comes together and you have a moment of perfect clarity? Today was epiphany-central for me. No less than a half-dozen conversational threads over [...]]]></description>
			<content:encoded><![CDATA[<p>Ever had one of those weeks where everything seems to be doom and gloom and you are cranky and snarky but you don&#8217;t know why?  Then, out of the blue, everything just comes together and you have a moment of perfect clarity?</p>
<p>Today was epiphany-central for me.  No less than a half-dozen conversational threads over the last month ran full-steam into one another in one staggering blast of <em>&ldquo;hey! you! pay attention!&rdquo;</em>.  Do you see how many tags/categories apply to this post?  It brings <em>everything</em> together for me.</p>
<p>I have an idea for an app.  A <em>killer</em> app.  It would take a while to build, and box, and sell &#8230; but it would <strong>soooo</strong> be worth it.  Financially, professionally, and mentally.</p>
<p>And the weird thing is that <strong>I</strong> am in a strong position to do it.  I&#8217;ve had other ideas that I&#8217;ve thought <em>&ldquo;man, I wish I was better at ThingXYZ, because that&#8217;s all I&#8217;m missing&rdquo;</em>.  But for this one &#8230; I don&#8217;t have that excuse.  I <strong>could</strong> actually make it work, from start to finish.  I&#8217;d just have to commit.  That&#8217;s not a little scary, I must admit.</p>
<p>The irony here is that I was <em>just this morning</em> ranting to an audience about how bummed out it makes me that there are so few shining stars in the ColdFusion development community.  That is, not many are taking initiative to forge <strong>new</strong> paths instead of just taking what is handed to them, and challenging the idea of what you can and cannot do with ColdFusion.  I&#8217;m not looking to be a shining star, but not taking an opportunity to do something this new and this cool &#8230; would be profoundly hypocritical.</p>
<p>My first inclination is to talk about it.  Obviously, by nature, I&#8217;m not a secretive person.  But for this &#8230; I need to talk to some people and see if I&#8217;d screw myself over.  Granted, I was kindof talking out loud on <kbd>#coldfusion</kbd> on IRC when it hit me, so it&#8217;s certainly not a perfect secret.  But, better safe than sorry from here on out.  If I can talk about it, I&#8217;ll be a blogging fool for the next 3-6 months.</p>
<p>Wish me luck.</p>
<hr />
<p><strong>Clarification:</strong> I <strong>am not</strong> saying the CF community is a bunch of dolts, nor am I saying that there are no big names.  Sean C, Ray C, Mark D, and a bunch of other folks are doing some <strong>really great</strong> work.  That previous statement was just an oversimplification of a <em>very</em> long discussion.</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2007/03/light-dawns-on-marble-head/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

