<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkQFR3s8fCp7ImA9WxBVEkg.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865</id><updated>2010-02-15T12:25:16.574-06:00</updated><title>Kevin Glowacz</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://kevin.glowacz.info/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/kevinglowaczinfo" /><feedburner:info uri="kevinglowaczinfo" /><entry gd:etag="W/&quot;DEIMR308cSp7ImA9WxJaGEo.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-4826266259943094589</id><published>2009-03-07T13:55:00.002-06:00</published><updated>2009-08-09T22:56:26.379-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-09T22:56:26.379-05:00</app:edited><title>A simple irc bot in ruby</title><content type="html">&lt;p&gt;Recently it occurred to my colleagues and me that an IRC bot could benefit our chat room discussions. I looked around a bit and I couldn't find any simple ruby IRC bots to use. However, in my searching, I did find shout-bot. &lt;a href="http://github.com/sr/shout-bot"&gt;Shout-bot&lt;/a&gt; is a simple IRC "shouter" in that it connects, reports a message, and then disconnects. Using this as a starting point, I was able to create a simple bot that stays connected to a room and responds to messages.
&lt;/p&gt;

&lt;p&gt;This bot isn't very complex and is far from perfect, but it is a good starting point if you want an irc bot that responds to just a few things. You can also find this at its &lt;a href="http://github.com/kjg/simpleircbot"&gt;github repository&lt;/a&gt;.
&lt;/p&gt;

&lt;pre&gt;
#!/usr/bin/env ruby

require 'socket'

class SimpleIrcBot

  def initialize(server, port, channel)
    @channel = channel
    @socket = TCPSocket.open(server, port)
    say "NICK IrcBot"
    say "USER ircbot 0 * IrcBot"
    say "JOIN ##{@channel}"
    say_to_chan "#{1.chr}ACTION is here to help#{1.chr}"
  end

  def say(msg)
    puts msg
    @socket.puts msg
  end

  def say_to_chan(msg)
    say "PRIVMSG ##{@channel} :#{msg}"
  end

  def run
    until @socket.eof? do
      msg = @socket.gets
      puts msg

      if msg.match(/^PING :(.*)$/)
        say "PONG #{$~[1]}"
        next
      end

      if msg.match(/PRIVMSG ##{@channel} :(.*)$/)
        content = $~[1]

        #put matchers here
        if content.match()
          say_to_chan('your response')
        end
      end
    end
  end

  def quit
    say "PART ##{@channel} :Daisy, Daisy, give me your answer do"
    say 'QUIT'
  end
end

bot = SimpleIrcBot.new("irc.freenode.net", 6667, 'ChannelName')

trap("INT"){ bot.quit }

bot.run
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-4826266259943094589?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=XzgYE1L4KPQ:PvCXPSpN7AE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=XzgYE1L4KPQ:PvCXPSpN7AE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=XzgYE1L4KPQ:PvCXPSpN7AE:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=XzgYE1L4KPQ:PvCXPSpN7AE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=XzgYE1L4KPQ:PvCXPSpN7AE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=XzgYE1L4KPQ:PvCXPSpN7AE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=XzgYE1L4KPQ:PvCXPSpN7AE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/XzgYE1L4KPQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/4826266259943094589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2009/03/simple-irc-bot-in-ruby.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/4826266259943094589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/4826266259943094589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/XzgYE1L4KPQ/simple-irc-bot-in-ruby.html" title="A simple irc bot in ruby" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://kevin.glowacz.info/2009/03/simple-irc-bot-in-ruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cBRH09cCp7ImA9WxJaFU4.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-1824965506952188028</id><published>2008-12-09T23:30:00.007-06:00</published><updated>2009-08-06T00:04:15.368-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-06T00:04:15.368-05:00</app:edited><title>Coda Plug-in: Remove Trailing Whitespace</title><content type="html">&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; &lt;em&gt;Erik Hinterbichler has written a much better native plugin called &lt;a href="http://erikhinterbichler.com/software/white-out/"&gt;White Out&lt;/a&gt;. I highly recommend using that one instead of this one.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've been using &lt;a href="http://www.panic.com/coda/"&gt;Coda&lt;/a&gt; to do all of my programming for quite some time now. One thing I wish it had, though, is the ability to remove trailing white space from lines when the file is saved.&lt;/p&gt;

&lt;p&gt;With Coda 1.6 they added the ability to create &lt;a href="http://www.panic.com/coda/developer/howto/plugins.php"&gt;plug-ins&lt;/a&gt;, and with the release of 1.6.1 a few days ago they have added the ability to manipulate the whole document with plug-ins. After hearing this I decided to write my own to take care of that pesky trailing white space issue. Coda doesn't have the ability to have plug-ins run upon file save, but it's the best I could do with what they provide and what I know how to do.&lt;/p&gt;

&lt;p&gt;You can download the plug-in here:&lt;/p&gt;

&lt;p style="text-align: center;"&gt;
&lt;a href="http://glowacz.info/remove_trailing_whitespace_1.0.zip" style="text-decoration: none;"&gt;&lt;img src="http://glowacz.info/coda_plugin.png" /&gt;&lt;/a&gt;
&lt;br/&gt;&lt;a href="http://glowacz.info/remove_trailing_whitespace_1.0.zip"&gt;Remove Trailing Whitespace v1.0&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Here is the code I used to write it. The $$IP$$ stuff is so that the insertion point remains where it was before the code is run. If I leave it out, the insertion point goes to the end of the file. You can also visit its &lt;a href="http://github.com/kjg/remove_trailing_whitespace"&gt;github repository&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
#!/usr/bin/ruby

ip_line = ENV['CODA_LINE_NUMBER'].to_i
ip_index = ENV['CODA_LINE_INDEX'].to_i

$stdin.each_line do |line|
  line.rstrip!

  if $stdin.lineno == ip_line
    ip_index = line.length if (line.length) &amp;lt; ip_index
    line = line.insert(ip_index, "$$IP$$")
  end

  print line
  print ENV['CODA_LINE_ENDING']
end
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-1824965506952188028?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=BRXSuSKRDz0:2pWJcBaouwM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=BRXSuSKRDz0:2pWJcBaouwM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=BRXSuSKRDz0:2pWJcBaouwM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=BRXSuSKRDz0:2pWJcBaouwM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=BRXSuSKRDz0:2pWJcBaouwM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=BRXSuSKRDz0:2pWJcBaouwM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=BRXSuSKRDz0:2pWJcBaouwM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/BRXSuSKRDz0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/1824965506952188028/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2008/12/coda-plugin-remove-trailing-whitespace.html#comment-form" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/1824965506952188028?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/1824965506952188028?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/BRXSuSKRDz0/coda-plugin-remove-trailing-whitespace.html" title="Coda Plug-in: Remove Trailing Whitespace" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">13</thr:total><feedburner:origLink>http://kevin.glowacz.info/2008/12/coda-plugin-remove-trailing-whitespace.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04GQn04fyp7ImA9WxRaEU0.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-6938892424191298626</id><published>2008-12-04T18:47:00.003-06:00</published><updated>2008-12-12T13:25:23.337-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-12T13:25:23.337-06:00</app:edited><title>Yet Another Reason Jeff Atwood Has No Common Sense</title><content type="html">&lt;p&gt;I'll admit it -- I do read &lt;a href="http://www.codinghorror.com"&gt;Jeff Atwood&lt;/a&gt; and &lt;a href="http://joelonsoftware.com/"&gt;Joel Spolsky&lt;/a&gt;. When they announced &lt;a href="http://stackoverflow.com"&gt;stack overflow&lt;/a&gt;, I was intrigued and signed up for the beta. They only accept OpenID, so I decided to create a new blogger site: kevinglowacz.blogspot.com. I played around a little and it seemed like a nice concept.&lt;/p&gt;

&lt;p&gt;About a month later I decided to start utilizing my blog. I bought this domain name (glowacz.info) and setup my blogspot account to redirect to kevin.glowacz.info. Well this means when I try to log in to stack overflow with kevinglowacz.blogspot.com it redirects and logs me in as kevin.glowacz.info. That's fine, I'd like my OpenID to be my domain anyway. I just didn't want to lose what I had done with my other account.&lt;/p&gt; 

&lt;p&gt;I &lt;a href="http://stackoverflow.com/questions/321817"&gt;looked&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/53598"&gt;around&lt;/a&gt; and &lt;a href="http://stackoverflow.com/questions/191016"&gt;saw&lt;/a&gt; that others had also had circumstances where their OpenID changed and they were able to get their accounts merged by emailing Jeff. I shot an email over to Jeff Atwood explaining my situation and asked him to change the OpenID on my old account to my new OpenID. I also purposefully did nothing (except post a question asking to merge my accounts) with my new account so he wouldn't have to merge anything -- he'd just have to change the OpenID on my old account.&lt;/p&gt;

&lt;p&gt;However, instead of just changing the OpenID on my old account, Jeff took all of my questions and answers from my old account and attached them to my new account. Because of this I lost all of my profile info, my "Member for x days" data, and my esteemed "Beta Badge".&lt;/p&gt;

&lt;p&gt;Now I don't know how they have their database set up over at stack overflow, but I have to imagine that changing the OpenID associated with my old account would have to be easier than moving all my questions and answers over to my new account. I even specifically asked for the associated OpenID to be changed instead of asking for the accounts to be merged. Clearly, Jeff Atwood has no common sense.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-6938892424191298626?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=Peijv-efaD8:ti-R8nfWj7M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=Peijv-efaD8:ti-R8nfWj7M:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=Peijv-efaD8:ti-R8nfWj7M:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=Peijv-efaD8:ti-R8nfWj7M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=Peijv-efaD8:ti-R8nfWj7M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=Peijv-efaD8:ti-R8nfWj7M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=Peijv-efaD8:ti-R8nfWj7M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/Peijv-efaD8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/6938892424191298626/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2008/12/yet-another-reason-jeff-atwood-has-no.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/6938892424191298626?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/6938892424191298626?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/Peijv-efaD8/yet-another-reason-jeff-atwood-has-no.html" title="Yet Another Reason Jeff Atwood Has No Common Sense" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://kevin.glowacz.info/2008/12/yet-another-reason-jeff-atwood-has-no.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMHQn8_cCp7ImA9WxRUEUg.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-4614667226302629405</id><published>2008-11-19T22:40:00.002-06:00</published><updated>2008-11-19T23:20:33.148-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-19T23:20:33.148-06:00</app:edited><title>Dynamic Delicious Share Link for Blogger</title><content type="html">&lt;p&gt;I was working on adding share links to my blog posts and I discovered that both &lt;a href="http://digg.com/tools/integrate"&gt;Digg&lt;/a&gt; and &lt;a href="http://www.reddit.com/buttons"&gt;reddit&lt;/a&gt; have pretty nice dynamic share buttons with instruction on how to use them. These buttons show the number of diggs or up-votes obtained by the article if they have already been submitted.&lt;/p&gt;

&lt;p&gt;While &lt;a href="http://delicious.com/help/savebuttons"&gt;delicious&lt;/a&gt; also has some nice buttons, the one that shows the number of times an article has been bookmarked does not allow for a url to be specified. It only works for the location of the page it is on. This means I can't put it at the bottom of each post and have it work when multiple posts are displayed.&lt;/p&gt;

&lt;p&gt;After looking around, I found a &lt;a href="http://woork.blogspot.com/"&gt;site&lt;/a&gt; that uses the Delicious API to grab the total post count. The code he uses though is not very optimized, so I wrote my own. He was also using his own version of the Delicious button and is slightly outdated. This following code uses the button from the Delicious site that pops up a javascript window and includes my code to add the bookmark count next to the link.&lt;/p&gt;

&lt;p&gt;In your blogger template, place the following code somewhere inside the head tag:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script type='text/javascript'&amp;gt;
  function print_delicious_data(data){
    var urlinfo = data[0] || {};
    if (!urlinfo.total_posts) return;
    document.write(urlinfo.total_posts + " save");
    if(urlinfo.total_posts!=1) document.write("s");
  }
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Put the rest inside &amp;lt;div class="post-footer"&amp;gt;&lt;/p&gt;

&lt;pre&gt;
&amp;lt;a expr:href='"http://delicious.com/save?url="+data:post.url + "&amp;amp;amp;title=" + data:post.title' 
   expr:onclick='
    "window.open(
      \"http://delicious.com/save?v=5&amp;amp;amp;noui&amp;amp;amp;jump=close&amp;amp;amp;url=\" + 
        encodeURIComponent(\"" + data:post.url + "\") + \"&amp;amp;amp;title=\" +
        encodeURIComponent(\"" + data:post.title + "\"),
        \"delicious\",\"toolbar=no,width=550,height=550\"
    ); return false;"'
&amp;gt;Bookmark this on Delicious&amp;lt;/a&amp;gt;


&amp;lt;script expr:src='"http://feeds.delicious.com/v2/json/urlinfo?url=" +
data:post.url + "&amp;amp;amp;callback=print_delicious_data"'/&amp;gt;

&lt;/pre&gt;

&lt;p&gt;Just for fun, here is the code I use for the Digg and reddit buttons.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script type='text/javascript'&amp;gt;
  digg_url = '&amp;lt;data:post.url/&amp;gt;';
  digg_title = '&amp;lt;data:post.title/&amp;gt;';
  digg_topic = 'programming';
  digg_skin = 'compact';
  digg_window = 'new';
&amp;lt;/script&amp;gt;
&amp;lt;script src='http://digg.com/tools/diggthis.js' type='text/javascript'/&amp;gt;

&amp;lt;script type='text/javascript'&amp;gt;
  reddit_url='&amp;lt;data:post.url/&amp;gt;';
  reddit_title='&amp;lt;data:post.title/&amp;gt;';
  reddit_newwindow='1';
&amp;lt;/script&gt;
&amp;lt;script src='http://www.reddit.com/button.js?t=1' type='text/javascript'/&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-4614667226302629405?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=jUBErNTrOus:JBctlz22ku4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=jUBErNTrOus:JBctlz22ku4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=jUBErNTrOus:JBctlz22ku4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=jUBErNTrOus:JBctlz22ku4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=jUBErNTrOus:JBctlz22ku4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=jUBErNTrOus:JBctlz22ku4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=jUBErNTrOus:JBctlz22ku4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/jUBErNTrOus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/4614667226302629405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2008/11/dynamic-delicious-share-link-for.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/4614667226302629405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/4614667226302629405?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/jUBErNTrOus/dynamic-delicious-share-link-for.html" title="Dynamic Delicious Share Link for Blogger" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://kevin.glowacz.info/2008/11/dynamic-delicious-share-link-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMGQH45cSp7ImA9WxRVFk0.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-5614940323116253834</id><published>2008-11-13T11:30:00.007-06:00</published><updated>2008-11-13T12:20:21.029-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-13T12:20:21.029-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>Multiple asynchronous jQuery forms OR Making jQuery objects work for you</title><content type="html">&lt;p&gt;There are times when I find the need to put multiple forms on a page. Lets say for example I have a couple of surveys for my users. I want them to be able to participate in all of the surveys, but I don't want to make them hit the back button to fill out the subsequent forms. This, of course, can be done pretty easily with with ajax. Using both &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and the &lt;a href="http://www.malsup.com/jquery/form/"&gt;Forms Plugin&lt;/a&gt;, this is just a single line of javascript.&lt;/p&gt;

&lt;pre&gt;$("form").ajaxForm();&lt;/pre&gt;

&lt;p&gt;That was easy enough. All my forms will submit via ajax now. While this will work, it isn't quite enough. Users like feedback, and right now they wont even know that anything happened.&lt;/p&gt;

&lt;p&gt;I like to use a submit button (html button as opposed to input type="submit") that has an image that changes to a spinner when the form is submitted. I also disable the buttons while the form is submitting. (There is a &lt;a href="http://particletree.com/features/rediscovering-the-button-element/"&gt;nice tutorial&lt;/a&gt; on styling buttons this way.)&lt;/p&gt;

&lt;p&gt;The forms plugin gives us a nice beforeSubmit() function. It is similar to jQuery's ajax beforeSend(), but provides different input parameters. I will take advantage of the second parameter here -- the form object. This will swap out the submit button's image with a spinner image and disable the buttons before the XHR request is sent.&lt;/p&gt;

&lt;pre&gt;
var spinner = new Image();
spinner.src = "/path/to/spinner.gif";

$("form").ajaxForm({
  beforeSubmit: function(data, $form, opts){
    $form.find('button').attr('disabled', 'disabled');
    $form.find('button img').replaceWith($(spinner).clone());
  }
});
&lt;/pre&gt;

&lt;p&gt;Okay, great. We don't want to spin forever though, so we should change the images back when the request is done processing. I reset my buttons in the complete callback. You can use the success callback if you'd like, but if the form submission returns an error code then your button will be spinning and disabled forever.&lt;/p&gt;

&lt;p&gt;The problem with both the 'complete' and the 'success' callbacks is they don't give you the form object like the beforeSubmit callback does. If you just have one form on the page this isn't really a big issue because you can just use jQuery to select the form again via $('form') within the callback. I have multiple forms on my page though. If the second form is submitted before the first form completes, then both forms will be reset when the first one finishes.&lt;/p&gt;

&lt;p&gt;I need a way to know which form submission is completing inside the callback. I can do this by storing the form in the jQuery.ajax() options object. Inside any of the callback functions 'this' refers to the options object, so it actually quite convenient.&lt;/p&gt;
&lt;pre&gt;
var spinner = new Image();
spinner.src = "/path/to/spinner.gif";

$("form").ajaxForm({
  beforeSubmit: function(data, $form, opts){
    this.$form = $form;
    this.$buttonImage = $form.find('button img');
    $form.find('button').attr('disabled', 'disabled').find('img').replaceWith( $(spinner).clone() );
  },
  complete: function(){
    this.$form.find('button').removeAttr('disabled').find('img').replaceWith(this.$buttonImage);
  }
});
&lt;/pre&gt;

&lt;p&gt;I do think it is a little shady to be modifying jQuery objects. If for some reason they decide to add a $form property in the future and I upgrade my jQuery then obviously my code will overwrite that property. I think the benefits outweigh the risk though.&lt;/p&gt;

&lt;p&gt;In my fully tricked out forms, I'll even add my own functions to the object to make things easier. Here is code for some forms that have both a save and cancel button and has server side validations. Fields that are invalid are passed back in the response. This will also display both success and error messages after submission. I have our server generate a 422 (Unprocessable Entity) on invalid forms. jQuery doesn't automatically extract the response data for in the error call back, but it provides the XHR object so it is pretty easy to extract it myself.&lt;/p&gt;
&lt;pre&gt;
$("form").ajaxForm({
  resetForm: true,
  beforeSubmit: function(data, $form){
    this.$form = $form;
    this.$saveButton = $form.find('button.save');
    this.$saveButtonImage = this.$saveButton.find('img');
    this.$saveButton.attr('disabled', 'disabled').find('img').replaceWith($(loadingImage).clone());
  },
  clearMessages: function(){
    this.$form.find('.invalid').andSelf().removeClass('invalid');
    this.$form.find('.errors, .success').remove();
  },
  complete: function(){
    this.$saveButton.removeAttr('disabled').find('img').replaceWith(this.$saveButtonImage)
  },
  success: function(){
    this.clearMessages();
    this.$form.prepend('&amp;lt;div class="success"&amp;gt;&amp;lt;p class="heading"&amp;gt;Your submission has been recorded.&amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;');
    this.$form.find(".success")[0].scrollIntoView();
  },
  error: function(XHR){
    this.clearMessages();
    var $form = this.$form;

    if(XHR.status == 422){
      var data = eval("(" + XHR.responseText + ")");

      if(typeof(data['invalid_fields']) != "undefined") {
        var error_box = '&amp;lt;div class="errors"&amp;gt;&amp;lt;p class="heading"&amp;gt;There were errors processing your submission.&amp;lt;/p&amp;gt;&amp;lt;ol&amp;gt;';

        $.each(data['invalid_fields'], function(id, errors){
          $form.find('.form_field_'+id).addClass('invalid');
          $.each(errors, function(){
            error_box += '&amp;lt;li&amp;gt;' + this + '&amp;lt;/li&amp;gt;';
          });
        });

        error_box += '&amp;lt;/ol&amp;gt;&amp;lt;/div&amp;gt;';
        $form.prepend(error_box);
        $form.find(".errors")[0].scrollIntoView();
      }
    }
  }
});
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-5614940323116253834?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=-GnvPGImzAA:ci07CfdkIxE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=-GnvPGImzAA:ci07CfdkIxE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=-GnvPGImzAA:ci07CfdkIxE:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=-GnvPGImzAA:ci07CfdkIxE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=-GnvPGImzAA:ci07CfdkIxE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=-GnvPGImzAA:ci07CfdkIxE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=-GnvPGImzAA:ci07CfdkIxE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/-GnvPGImzAA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/5614940323116253834/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2008/11/multiple-asynchronous-jquery-forms-or.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/5614940323116253834?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/5614940323116253834?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/-GnvPGImzAA/multiple-asynchronous-jquery-forms-or.html" title="Multiple asynchronous jQuery forms OR Making jQuery objects work for you" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://kevin.glowacz.info/2008/11/multiple-asynchronous-jquery-forms-or.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYBSXg4eyp7ImA9WxRVEE4.&quot;"><id>tag:blogger.com,1999:blog-8724832710205544865.post-7485241891186546815</id><published>2008-11-06T18:33:00.005-06:00</published><updated>2008-11-06T22:45:58.633-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-06T22:45:58.633-06:00</app:edited><title>Because All the Cool Kids are Doing It</title><content type="html">So here it is -- my very own website. I've mostly been keeping to myself on the internet up until now, but I suppose it is about time that I got a little more social. So much information is exchanged on personal websites these days and so I figured I might as well share my experiences as well.

This will mostly be a blog about my programming experiences, but I'm sure it'll be nice to have a place to just vent my thoughts too. I guess we'll see how it goes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8724832710205544865-7485241891186546815?l=kevin.glowacz.info' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=wpRjw_int3A:Z16W-f-sqeE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=wpRjw_int3A:Z16W-f-sqeE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=wpRjw_int3A:Z16W-f-sqeE:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=wpRjw_int3A:Z16W-f-sqeE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=wpRjw_int3A:Z16W-f-sqeE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/kevinglowaczinfo?a=wpRjw_int3A:Z16W-f-sqeE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/kevinglowaczinfo?i=wpRjw_int3A:Z16W-f-sqeE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/kevinglowaczinfo/~4/wpRjw_int3A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://kevin.glowacz.info/feeds/7485241891186546815/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://kevin.glowacz.info/2008/11/because-all-cool-kids-are-doing-it.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/7485241891186546815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8724832710205544865/posts/default/7485241891186546815?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kevinglowaczinfo/~3/wpRjw_int3A/because-all-cool-kids-are-doing-it.html" title="Because All the Cool Kids are Doing It" /><author><name>Kevin</name><uri>http://www.blogger.com/profile/12148640481055084339</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="12398211118540516589" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://kevin.glowacz.info/2008/11/because-all-cool-kids-are-doing-it.html</feedburner:origLink></entry></feed>
