<?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>Boomtown Internet Group &#187; Applications Programming</title>
	<atom:link href="http://www.boomtownig.com/blog/topics/applications-programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.boomtownig.com/blog</link>
	<description>Blog</description>
	<lastBuildDate>Wed, 21 Jul 2010 18:57:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Magento – Claims to be the fastest growing ecommerce platform!</title>
		<link>http://www.boomtownig.com/blog/magento-%e2%80%93-claims-to-be-the-fastest-growing-ecommerce-platform/517/</link>
		<comments>http://www.boomtownig.com/blog/magento-%e2%80%93-claims-to-be-the-fastest-growing-ecommerce-platform/517/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 15:20:36 +0000</pubDate>
		<dc:creator>Sue McCrossin</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=517</guid>
		<description><![CDATA[We plan to try Magento in January 2010 because it seems more robust than SquirrelCart.  The following posts explains our reasons for using Magento ecommerce. ]]></description>
			<content:encoded><![CDATA[<p>Our company uses many types of ecommerce platforms for various customers, and we particularly like working with the PHP open source ecommerce system called SquirrelCart by Lighthouse Development.  We also work with Oscommerce, WordPress Ecommerce Module, Zend Cart and X-Cart, and we are always open to new carts that will make programming an ecommerce system cheaper and easier for our customers to maintain.  In the coming year we have decided to give Magento a try due to a few shortcomings in SquirrelCart that we believe Magento will correct by default.</p>
<p>We’ve done a bit of research on Magento already, and found that while it is very powerful and flexible, there is very little documentation and some people have found that the layers of programming and thousands of files are tricky to customize, and this makes it take up to 5 times longer to customize.  In addition, I have read that the cart runs slowly, requires at least a semi-dedicated server, and can be costly to host as the number of products increases.</p>
<p>Magento allows for multiple stores to use one cart, an obvious savings to our clients.  It also allows for multiple product images so that customers can get a really good look at what they are purchasing.  It also allows coupons and different pricing for customer groups.  Google checkout, PayPal, and PayPal Pro are all integrated, and there is a one-page checkout process.</p>
<p>As far as SEO goes, this cart has the ability to add unique titles and descriptions and keyword rich URLs on pages, just like Squirrelcart.  It also has a nice CMS which allows your customers to add informational pages which can be used for SEO as well.</p>
<p>You can download the cart for free from http://www.magentocommerce.com, and there is also a fully supported enterprise edition of the cart for just under $9,000 for larger businesses that want to integrate their carts and inventory systems. The cart is coded with the latest PHP 5 object oriented standards and uses the Zend framework.</p>
<p>Check back to our blog in early January after we complete our first Magento ecommerce website, when we will review our coding experiences using the software.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/magento-%e2%80%93-claims-to-be-the-fastest-growing-ecommerce-platform/517/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>6 Very Useful (and SEO Friendly) jQuery Website Animation Techniques</title>
		<link>http://www.boomtownig.com/blog/6-seo-friendly-jquery-techniques/511/</link>
		<comments>http://www.boomtownig.com/blog/6-seo-friendly-jquery-techniques/511/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 14:53:00 +0000</pubDate>
		<dc:creator>Erica Ronchetti</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[Boomtown News]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Website Design]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[website animation]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=511</guid>
		<description><![CDATA[How do I animate my website while still keeping it SEO friendly?
When most people visit websites, they assume the animated material is Flash.  That’s not always the case.  Due to the growing popularity of JavaScript frameworks, there are now a variety of exciting options for incorporating animations and animated material into your website that don’t...]]></description>
			<content:encoded><![CDATA[<p><strong>How do I animate my website while still keeping it SEO friendly?</strong></p>
<p>When most people visit websites, they assume the animated material is Flash.  That’s not always the case.  Due to the growing popularity of JavaScript frameworks, there are now a variety of exciting options for incorporating animations and animated material into your website that don’t involve Flash, which can’t be read by search engines.</p>
<p>You want your website to be creative and interactive, but you also want to show up in the SERPS.  You don’t have to sacrifice any optimization with jQuery.  It serves as an excellent tool for front-end developers to present information to the end user in more interesting ways.  The fact that jQuery website animation uses JavaScript to manipulate DOM objects, (represented with HTML and styled with CSS) makes it easy to stay SEO friendly because you can reveal and hide content from the user with effects, but still keep the same page markup for search crawlers.</p>
<p><strong>If you’re interested in jQuery animation for your website, check out these 6 cool website animation techniques:</strong></p>
<p>1.   <strong> jQuery Cycle:</strong> <strong><a href="http://malsup.com/jquery/cycle/" target="_blank">http://malsup.com/jquery/cycle/</a> </strong> <em> </em></p>
<p><em>A great way to display your images!</em></p>
<p>This useful plugin can be used to create slideshows of images without the need for Flash.  You can use this to display a gallery of images and choose the manner you’d like the images to transition.  Effects include <strong>Shuffle</strong>, <strong>Zoom, Fade, Turn Down, Curtain</strong>, and <strong>Scroll</strong>.</p>
<p>Boomtown uses this jQuery animation here: <strong><a href="www.boomtownig.com " target="_blank">www.boomtownig.com </a></strong></p>
<p>2.   <strong> jQuery Accordion:</strong> <strong><a href="http://jqueryui.com/demos/accordion/" target="_blank">http://jqueryui.com/demos/accordion/</a></strong> <em> </em></p>
<p><em>Manage your content.<br />
</em><br />
The jQuery Accordion can help you display lots and lots of content in a condensed form that&#8217;s still visible to search engines, but doesn&#8217;t overload users&#8217; senses.  <strong> </strong></p>
<p><strong>RCD Technology</strong> uses the accordion plugin to successfully manage their content:  <a href="http://www.rcdtechnology.com" target="_blank"><strong>http://www.rcdtechnology.com</strong></a></p>
<p>3.  <strong>Form Validation:</strong> <a href="http://jquery.malsup.com/form/ " target="_blank"><strong>http://jquery.malsup.com/form/ </strong></a></p>
<p><em>Doing client-side form validation is made much easier with the jQuery forms plugin.</em></p>
<p>Widely regarded as one of the best jQuery plugins, Form Validation involves doing things like checking that all required fields were filled out and, if so, were they filled out to a required specification (e.g. correctly formatted phone numbers or dates), enabling you to get the information you need.</p>
<p>4.   <strong>Superfish: </strong> <a href="http://users.tpg.com.au/j_birch/plugins/superfish/#examples" target="_blank"><strong>http://users.tpg.com.au/j_birch/plugins/superfish/#examples</strong></a></p>
<p><em>Create a cross-browser multi-level horizontal or vertical navigation.</em></p>
<p>The jQuery Superfish plugin is great for managing drop down and multi-level navigation.  With the Superfish navigation plugin, you’ll be able to showcase and direct visitors to the many webpages your site has to offer.</p>
<p>It&#8217;s used for the navigation in the orange top menu of the Boomtown site and blog:  <a href="www.boomtownig.com " target="_blank"><strong>www.boomtownig.com </strong></a></p>
<p>5.   <strong>Subtle Animation Effects:</strong> <a href="http://www.rcdtechnology.com/rfid-applications/partners-customers/ " target="_blank"><strong>http://www.rcdtechnology.com/rfid-applications/partners-customers/ </strong></a></p>
<p><em>Create subtle animation effects for page items and images. </em> (You can view these by mousing over the partner logos).</p>
<p>The creation of these effects for page items adds different movement to images.</p>
<p>6.   <strong>Or you can use any of the widgets in the jQuery UI to enhance user experience:</strong><br />
<a href="http://jqueryui.com/demos/" target="_blank"><strong>http://jqueryui.com/demos/</strong></a></p>
<p>We hope these 6 tools will inspire you to explore all that jQuery has to offer—there are numerous other plugins and website animation techniques as well.  Learn more about jQuery and what it can do for your website!</p>
<p><strong><br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/6-seo-friendly-jquery-techniques/511/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Bash Shell Script to do Multiple Whois Lookups</title>
		<link>http://www.boomtownig.com/blog/a-bash-shell-script-to-do-multiple-whois-lookups/507/</link>
		<comments>http://www.boomtownig.com/blog/a-bash-shell-script-to-do-multiple-whois-lookups/507/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 16:40:04 +0000</pubDate>
		<dc:creator>Clay Simmons</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=507</guid>
		<description><![CDATA[On a recent project, I was given a list of about 30 domains to redirect to a new site.  I needed to get a handle on where the domains were registered and where the DNS was hosted.  I could have spent a lot of time typing &#8220;whois domain-name.com&#8221; into the terminal of my Mac, or...]]></description>
			<content:encoded><![CDATA[<p>On a recent project, I was given a list of about 30 domains to redirect to a new site.  I needed to get a handle on where the domains were registered and where the DNS was hosted.  I could have spent a lot of time typing &#8220;whois domain-name.com&#8221; into the terminal of my Mac, or write a shell script to do the lookups for me and write the results to a file that I could quickly examine.  I already had all the domains in a text file.  Here&#8217;s what I did:</p>

<div class="wp_syntax"><div class="code"><pre class="sh" style="font-family:monospace;">#!/bin/bash
for domain in `cat domains.txt`
do
   echo $domain
   `whois $domain &amp;gt;&amp;gt; whois-results.txt`
done</pre></div></div>

<p>You could take this a step further and do some regular expression matching to only get the lines of interest, but this needed to be quick and dirty.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/a-bash-shell-script-to-do-multiple-whois-lookups/507/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating an exit survey using jQuery and Zend Framework</title>
		<link>http://www.boomtownig.com/blog/creating-an-exit-survey-using-jquery-and-zend-framework/466/</link>
		<comments>http://www.boomtownig.com/blog/creating-an-exit-survey-using-jquery-and-zend-framework/466/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 19:36:06 +0000</pubDate>
		<dc:creator>Clay Simmons</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=466</guid>
		<description><![CDATA[One of our clients was looking at his Google Analytics data and noticed that he was getting a high bounce rate on his site&#8217;s contact page.  Naturally, he wanted to know why, so he asked us to create an exit survey that pops up when a user navigates away from the page.  So,...]]></description>
			<content:encoded><![CDATA[<p>One of our clients was looking at his Google Analytics data and noticed that he was getting a high bounce rate on his site&#8217;s contact page.  Naturally, he wanted to know why, so he asked us to create an exit survey that pops up when a user navigates away from the page.  So, for example, when a user comes to the contact page, then clicks away to another page, they&#8217;re presented with a dialog box that looks like this:</p>
<p><img class="aligncenter wp-image-478" title="exit-survey-screenshot" src="http://www.boomtownig.com/blog/wp-content/uploads/exit-survey-screenshot.jpg" alt="exit-survey-screenshot" /></p>
<h3>Outline of Components</h3>
<ol>
<li>Adding a unique id to the body tag of each page in the zend framework project</li>
<li>A modal dialog using jQuery UI that displays the exit survey</li>
<li>An AJAX call to our Zend Framework controller that logs the survey results</li>
<li>A script that runs from the crontab to email the survey results on a daily basis</li>
</ol>
<h3>Directory Structure of Zend Framework Project</h3>
<p>Here&#8217;s what the directory structure of my Zend Framework project looks like. Htdocs is the web root and all of the application files are in the FTP root, safely prevented from being accessed via the web in a folder called app_jsc.</p>
<p><img class="alignnone size-full wp-image-479" title="jsc-directory-tree" src="http://www.boomtownig.com/blog/wp-content/uploads/jsc-directory-tree.jpg" alt="jsc-directory-tree" width="272" height="467" /></p>
<p>You&#8217;ll notice that the Zend Framework library is mysteriously missing.  I keep this at the same directory level as app_jsc and htdocs because I might want to run multiple apps on this hosting account.</p>
<h3>Add a Unique id to Each Page&#8217;s Body Tag</h3>
<p>I like to add an id to the body tag of each of the pages in my Zend Framework projects.  For example:</p>
<p>This comes in handy if you need to target css or javascript to certain pages only.  In the app_jsc/views/layouts/main.phtml, put this code:</p>
<p>I have a controller plugin called ViewSetup that I use to execute certain code during the dispatch cycle.  Setting up and registering controller plugins can vary depending on which version of Zend Framework you&#8217;re using, so I won&#8217;t cover how to specifically do that in this post, but you should be familiar with how this works.  In the dispatchLoopStartup() of my plugin, I put this code that assigns a value to bodyId and passes it to the view:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> dispatchLoopStartup<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// Get the name of the controller and action of this request</span>
  <span style="color: #000088;">$controllerName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getControllerName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$actionName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getActionName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Get static instance of ViewRenderer helper</span>
  <span style="color: #000088;">$viewRenderer</span> <span style="color: #339933;">=</span> Zend_Controller_Action_HelperBroker<span style="color: #339933;">::</span><span style="color: #004000;">getStaticHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ViewRenderer'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$viewRenderer</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>initView<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$view</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$viewRenderer</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>view<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Assign value to the bodyId and pass it to the view</span>
  <span style="color: #000088;">$view</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>bodyId <span style="color: #339933;">=</span> <span style="color: #000088;">$controllerName</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$actionName</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>So, on the home page of the site, the HTML will look like:</p>
<h3>jQuery UI Custom Build</h3>
<p>First, we need to head over to <a href="http://www.jqueryui.com/">jQuery UI</a> and get the components we&#8217;ll need to construct the modal dialog.  I want to download a custom version of the jQuery UI that contains only the components I really need for the exit survey.  The UI demo pages are really good about specifying the dependencies needed for each widget to work.  The jQuery Dialog widget needs UI Core, UI Draggable, and UI Resizeable.  The last two are only necessary if I want the dialog to be resizeable or draggable (surprise).  I might want this, so I&#8217;m going to include them in the custom build I specify on the <a href="http://www.jqueryui.com/download">download page</a>.  On this page, I specify that I want the Cupertino theme. I check the UI Core, Draggable and Resizeable from the Interactions, the Dialog widget, and all of the effects because I might want to apply one when the dialog appears.  They aren&#8217;t necessary for this to work though.</p>
<p>When you build your own download package, jQuery is going to give you a zip file containing a css folder, a js folder, and another folder called development-bundle.  I only need what&#8217;s in the css and js folders.  The css folder will contain a folder with your theme name and, inside of that, the themed css file and an images folder.  I&#8217;m just going to drop the cupertino folder into my public css folder (I call mine &#8220;c&#8221; for short) in my project.  I&#8217;ll also drop the files from the js folder into my public js folder in my project.  I need to place some code in app_jsc/views/layouts/main.phtml to make sure the css files and js files are included in my project.</p>
<p>Code to place in the head tag to include the css and javascript files:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;!-- First we need jquery --&gt;
&lt;script src=&quot;/js/jquery-1.3.2.min.js&quot; type=&quot;text/javascript&quot;&gt;&lt;!--mce:0--&gt;&lt;/script&gt;
&nbsp;
&lt;!-- the custom jquery-ui javascript --&gt;
&lt;script src=&quot;/js/jquery-ui-1.7.2.custom.min.js&quot; type=&quot;text/javascript&quot;&gt;&lt;!--mce:1--&gt;&lt;/script&gt;
&nbsp;
&lt;!-- the javascript where I put all of my DOM ready code --&gt;
&lt;script src=&quot;/js/init.js&quot; type=&quot;text/javascript&quot;&gt;&lt;!--mce:2--&gt;&lt;/script&gt;
&nbsp;
...
&nbsp;
&lt;!-- Main site stylesheet --&gt;
&nbsp;
&lt;!-- custom jquery-ui stylesheet --&gt;</pre></div></div>

<p>Now, you can get all fancy and use <a href="http://framework.zend.com/manual/en/zend.view.helpers.html">Zend Framework&#8217;s headScript, headLink, and headStyle helpers</a> to append everything somewhere up the request dispatch cycle, but this is just a simple website that doesn&#8217;t use any logic to append certain styles or javascript.  Every page gets everything, so let&#8217;s just keep it simple for now.</p>
<h3>The HTML for the Modal Dialog</h3>
<p>The HTML for the exit survey needs to go on the contact page (app_jsc/views/scripts/contact-us/index.phtml) and stay hidden until we call the dialog() method on it.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div id=&quot;survey&quot; style=&quot;display: none;&quot; title=&quot;Before you go...&quot;&gt;
&nbsp;
Would you mind telling us why you're leaving this page?
&lt;form id=&quot;survey-form&quot; accept-charset=&quot;utf-8&quot; method=&quot;post&quot;&gt;
&lt;input name=&quot;reasons&quot; type=&quot;radio&quot; value=&quot;Don't want to leave email&quot; /&gt; &lt;span class=&quot;reason&quot;&gt;You want to contact us, but don’t want to leave your email address&lt;/span&gt;
&lt;input name=&quot;reasons&quot; type=&quot;radio&quot; value=&quot;CAPTCHA trouble&quot; /&gt; &lt;span class=&quot;reason&quot;&gt;You want to contact us, but had trouble with captcha verification&lt;/span&gt;
&lt;input name=&quot;reasons&quot; type=&quot;radio&quot; value=&quot;Got her by accident&quot; /&gt; &lt;span class=&quot;reason&quot;&gt;You got to this page by accident&lt;/span&gt;
&lt;input name=&quot;reasons&quot; type=&quot;radio&quot; value=&quot;No interest in contacting&quot; /&gt; &lt;span class=&quot;reason&quot;&gt;You have no interest in contacting us&lt;/span&gt;
  &lt;/form&gt;&lt;/div&gt;</pre></div></div>

<h3>The Javascript</h3>
<p>I like to put all of my DOM ready and onload code in a file called init.js and then include that on every page.  I can hook page-specific javascript code on the unique body id that I&#8217;ve already set up.  Here&#8217;s my init.js file:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</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: #006600; font-style: italic;">// Check the radio button associated with the label</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'span.reason'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</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: #660066;">prev</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input:first'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'checked'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">true</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: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// Bind function to the click events of the navigation links</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#contact-us-index #topnav a, #contact-us-index #navigation a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// Prevent the browser from loading the page the user tried to visit</span>
    e.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Save the URL of where the user wanted to go</span>
    destination <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: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Show the exit survey</span>
    showExitSurvey<span style="color: #009900;">&#40;</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: #339933;">;</span>
&nbsp;
<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> showExitSurvey<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#survey'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">dialog</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    width<span style="color: #339933;">:</span> <span style="color: #CC0000;">500</span><span style="color: #339933;">,</span>
    bgiframe<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    modal<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #000066;">close</span><span style="color: #339933;">:</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: #009900;">&#40;</span><span style="color: #3366CC;">'#survey'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">dialog</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'destroy'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>  <span style="color: #006600; font-style: italic;">// Destroy the dialog.  Allows it to appear again if closed.</span>
    buttons<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;Continue &amp;gt;&amp;gt;&quot;</span> <span style="color: #339933;">:</span> log_answer <span style="color: #009900;">&#125;</span>                  <span style="color: #006600; font-style: italic;">// Add a continue button that logs the answer when clicked</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> log_answer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    type<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;POST&quot;</span><span style="color: #339933;">,</span>
    url<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;/contact-us/abandon/format/text&quot;</span><span style="color: #339933;">,</span>
    data<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#survey-form&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">serialize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    dataType<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;text&quot;</span><span style="color: #339933;">,</span>
    complete<span style="color: #339933;">:</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: #009900;">&#40;</span>location<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #339933;">,</span>destination<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>
  <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The comments pretty well explain what is going on here, but lets discuss the basic flow.  I like for the text associated with a radio button or check box on a form to select the radio button or checkbox when clicked, so that&#8217;s what my first bit of code does.  When the text in the span tag is clicked, the first previous radio button sibling is checked.</p>
<p>Next, I&#8217;m going to assign a function to the click event of the page navigation links.  Notice, I&#8217;m using my bodyId hook to only bind the click event to navigation links on the contact page.  When the user clicks on a link, I want to stop the browser from taking them to the page they wanted, so I call preventDefault() on the click event.  I&#8217;ll need to know where the user was going in order to redirect them after they fill out the exit survey, so I save the destination for later.</p>
<p>Finally, we call the showExitSurvey() function. This defines our jQuery modal dialog.  The close option has a function associated with it that destroys the dialog box.  If the user clicks on the X in the top right corner of the dialog to close it and then clicks on a link to leave the contact page again, this allows the dialog to reappear.  I&#8217;m only defining one button on this dialog because I want to make it as simple as possible.  I don&#8217;t want to force the user to enter an answer.  They should just be able to hit the continue button and get on with what they were doing.  The continue button has a callback associated with it, log_answer.  Let&#8217;s take a look at that function.</p>
<p>The log_answer() function is where we build the AJAX call to our script that processes the survey.  I&#8217;m simply sending the data as a POST request to our controller.  I serialize the data from the form and tell jQuery to expect the AJAX response in plain text.  When the AJAX request is complete, I forward the user on to where they wanted to go in the first place.  I like to use the complete option instead of success.  The complete event fires after the success and error events of the request.  It&#8217;s pretty much the last event to be fired during the AJAX request cycle, so you can be sure that everything is done.  In a more complex setup, you could have other things happen during the success and error events before redirecting, but here, I just want it to fail silently and let the user get on with their browsing.</p>
<h4>A Word About When a User Closes the Browser Window</h4>
<p>It would be nice to administer the survey when the user tries to close their browser window.  Unfortunately, there is no good cross-browser way that I know of (commenters, got any ideas?) to implement this.  Gmail users have seen something similar to this when they try to close the browser window before finishing a new email.  It will say something like, &#8220;Are you sure you want to leave this page?&#8221; warning us that our changes will be lost.  This topic (the onbeforeunload event) has been covered in great detail by many other bloggers.  Check out <a href="http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript">Patrick Hunlock&#8217;s great article on the matter</a>, for example.  The bottom line is that, while it is possible to display a confirm message to prevent changes from being lost when we close a browser window, it is another matter entirely to collect data from a form and send the results to an asynchronous processing script.</p>
<h3>The Controller</h3>
<p>I need to tell my controller which actions can respond to AJAX requests.  You do this by making use of the AjaxContext action helper.  In this example, I&#8217;m using plain text as the AJAX response, so I&#8217;ll need to define this as a new context.  I could easily have used xml or json as the response type.  These are built in context types in Zend Framework, but this will give us an opportunity to see how to define a new context type for a controller action in Zend Framework.  First, I need to get the AjaxContext helper, add my new context, then associate that context with the abandonAction() in my controller.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ContactUsController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$ajaxContext</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>_helper<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getHelper<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AjaxContext'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$ajaxContext</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>addContext<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span>
      <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'suffix'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'text'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'header'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'
          Content-Type'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'text/plain'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>addActionContext<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'abandon'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'text'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>initContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>What we&#8217;re doing here is using the addContext method to define our new &#8216;text&#8217; context.  After we define it, we can tell the controller that the abandon action can respond to XMLHttpRequests with this new context.  The client request will be to /contact-us/abandon/format/text.  You could just as easily say /contact-us/abandon?format=text.</p>
<h4>View Scripts</h4>
<p>First, let&#8217;s add the view scripts needed for the abandon action.  Create two new files:</p>
<pre>app_jsc/
  views/
    scripts/
      contact-us/
        abandon.phtml
        abondon.text.phtml
</pre>
<p>The first file, abandon.phtml, will be rendered if you type http://www.domain-name.com/contact-us/abandon/ into a browser.  You don&#8217;t really need this file if you don&#8217;t care that an error is thrown should someone go to the URL.  The second file, abandon.text.phtml, is the context-specific view script that will be rendered only if the controller detects an XMLHttpRequest (in other words, AJAX) to the abandon action.  Note, that if you try to put http://www.domain-name.com/contact-us/abandon/format/text into the browser, the controller will still render the abandon.phtml view script because it&#8217;s not an AJAX request.</p>
<p>Here&#8217;s what&#8217;s in my abandon.text.phtml and my abandon.phtml file.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">response ?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></div></div>

<h4>The abandonAction()</h4>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ContactUsController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> abandonAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Bail if it wasn't a POST request</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>_request<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>isPost<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>view<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>response <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;false&quot;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Fetch the post variables into a local array</span>
    <span style="color: #000088;">$post</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>_request<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getPost<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// If they selected nothing, reason set as no-reason, otherwise</span>
    <span style="color: #666666; font-style: italic;">// it's set as the reason they selected</span>
    <span style="color: #000088;">$reason</span> <span style="color: #339933;">=</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'reasons'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>  ? <span style="color: #0000ff;">&quot;No reason given&quot;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$post</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'reasons'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Set up a new logger that writes to a file</span>
    <span style="color: #666666; font-style: italic;">// Log the reason</span>
    <span style="color: #000088;">$logger</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Log<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$writer</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Log_Writer_Stream<span style="color: #009900;">&#40;</span>APP_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;/logs/contact-abandon-log.txt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$logger</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>addWriter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$writer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$logger</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>log<span style="color: #009900;">&#40;</span><span style="color: #000088;">$reason</span><span style="color: #339933;">,</span>Zend_Log<span style="color: #339933;">::</span><span style="color: #004000;">INFO</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Tell the view that we're finished</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>view<span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>response <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;done&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The first thing that happens here is the action just bails out if we don&#8217;t have a HTTP POST request.  Then we&#8217;re going to use Zend_Log to create our log file.  Passing a string to Zend_Log_Writer_Stream will always try to open a file in append mode or create the file if it doesn&#8217;t exist.  So our log will just build and build each time this action is called.</p>
<p>Note that I did not call disableLayout() anywhere.  That&#8217;s because the AjaxContext helper disables this for us.  An AJAX request to this action will only render the code and text in the abandon.text.phtml view script.</p>
<p>So, now we&#8217;re logging people&#8217;s responses when they leave our fabulous page.  Now to set up the script that will email the results daily.</p>
<h3>The Emailer Script</h3>
<p>I want a script that will check the contents of the log, email me the results, then clear out the log for the next day&#8217;s data.</p>
<pre>app_jsc/
  cron_scripts/
    email-results-of-log.php
</pre>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Add zf library files to include path and require mailer</span>
<span style="color: #990000;">ini_set</span><span style="color: #009900;">&#40;</span>
  <span style="color: #0000ff;">'include_path'</span><span style="color: #339933;">,</span><span style="color: #990000;">ini_get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'include_path'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span>
  PATH_SEPARATOR <span style="color: #339933;">.</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;/the/relative/path/to/your/zf_library_files&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend/Mail.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get the contents of the log file</span>
<span style="color: #000088;">$filename</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/absolute/path/to/your/application/app_jsc/logs/contact-abandon-log.txt&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$contents</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Bail out if there is nothing to report</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contents</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</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;">// Empty the log file</span>
<span style="color: #000088;">$handle</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'w'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$handle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Now send the mail</span>
<span style="color: #000088;">$body_html</span> <span style="color: #339933;">=</span> <span style="color: #990000;">nl2br</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$contents</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Mail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>setFrom<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'info@thedomain.com'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">&quot;Some Name&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>addTo<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'person@test.com'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Your Name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>setSubject<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Reasons People Abandoned Contact Page - '</span> <span style="color: #339933;">.</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>setBodyHtml<span style="color: #009900;">&#40;</span><span style="color: #000088;">$body_html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mail</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>send<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Pretty simple really.  The only tricky part is making sure you add the Zend Framework library files to your include path.  Then you can use Zend_Mail as a standalone component.  That&#8217;s one of the things I like about Zend Framework.  The ability to use parts of it as needed in your standalone scripts.</p>
<h3>Schedule the Emailer to Run Automatically With Cron</h3>
<p>I want my emailer script to send me the log file results every morning at 8:30am.  That means executing this script from cron.  Cron is just a task scheduler for unix/linux.  If you&#8217;re not familiar with it, <a href="http://en.wikipedia.org/wiki/Cron">check it out</a>, but chances are, if you&#8217;ve gotten this far in this article, you&#8217;re probably aware of it.  You&#8217;ll need to work with your web host to find out how to edit your crontab.  In this hosting environment, I have shell access, which allows me to use lots of powerful command line tools on the server.  To edit my crontab, I type:</p>
<pre>crontab -e</pre>
<p>Now, in goes the following:</p>
<pre>30 8 * * * php app_jsc/cron_scripts/email-results-of-abandon-log.php
</pre>
<p>Save the changes to your crontab.  This will execute the command, &#8220;php app_jsc/cron_scripts/email-results-of-abandon-log.php,&#8221; in my user&#8217;s home directory every day at 8:30am.  The email you receive every day should look something like this:</p>
<pre>2009-11-30T15:30:43-05:00 INFO (6): No reason given
2009-11-30T15:43:04-05:00 INFO (6): Didn't want to leave email address
</pre>
<p>Obviously, if you&#8217;re site&#8217;s really busy, the log will grow quite large and maybe you&#8217;ll want to come up with a better way of examining the data.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/creating-an-exit-survey-using-jquery-and-zend-framework/466/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fix WP Post Thumbnail JSON Response Parse Errors</title>
		<link>http://www.boomtownig.com/blog/fixing-wp-post-thumbnail-plugin-json-response-parse-errors/411/</link>
		<comments>http://www.boomtownig.com/blog/fixing-wp-post-thumbnail-plugin-json-response-parse-errors/411/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 03:46:51 +0000</pubDate>
		<dc:creator>Clay Simmons</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=411</guid>
		<description><![CDATA[I&#8217;ve been using Stanley Yeoh&#8217;s great WP Post Thumbnail plugin for quite some time now.  It provides an easy to use interface for cropping and editing post thumbnails for use in your custom WordPress themes.  He&#8217;s recently released a beta version of the plugin for testing with the latest 2.8 release of WordPress.
UPDATE: It appears...]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Stanley Yeoh&#8217;s <a href="http://www.seoadsensethemes.com/wordpress-wp-post-thumbnail-plugin/">great WP Post Thumbnail plugin</a> for quite some time now.  It provides an easy to use interface for cropping and editing post thumbnails for use in your custom WordPress themes.  He&#8217;s recently released a beta version of the plugin for testing with the latest 2.8 release of WordPress.</p>
<h4><span style="color: #ff0000;">UPDATE: It appears this is broken again when upgrading to WordPress version 2.9.2.  Currently working on a fix.</span></h4>
<h2>The Problem</h2>
<p>I was developing a custom WordPress theme for a client in a shared hosting environment when I ran into a problem with the WP Post Thumbnail (WPPT) plugin.  When editing a post in the WordPress admin, the loading spinner image next to the Preset1 tab never disappeared.  It just kept spinning and spinning.  To troubleshoot, I enabled the console panel in Firebug to examine the AJAX request/response data.  As is common in the AJAX paradigm, the response is sent back to the requesting page as JSON.  But the Firebug console reported a JSON parse error when trying to evaluate the AJAX response.</p>
<p>WPPT makes use of PHP&#8217;s json_encode() and json_decode() functions to encode/decode data.  The <a href="http://us2.php.net/manual/en/ref.json.php">JSON extension</a> is bundled with PHP &gt;= 5.2.0 by default, but a lot of shared hosting environments have older versions of PHP where these functions are unavailable.  The WPPT plugin accounts for this and bundles its own versions of the functions to be used should native PHP functions be unavailable.  In <em>wp-content/plugins/wp-post-thumbnail/wppt.php</em>, it checks for the presence of the JSON extension and includes it&#8217;s own file if it doesn&#8217;t exist:</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: #339933;">!</span><span style="color: #990000;">function_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'json_encode'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
	<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/includes/json.php'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Unfortunately, the functions bundled with this plugin do not produce 100% valid JSON and you&#8217;ll still get the parse error.  So what to do?</p>
<h2>A Real Replacement For json_encode() and json_decode()</h2>
<p>For a true json_encode() equivalent, I turned to PHP PEAR.  There is a Services_JSON package available.  You can <a href="http://pear.php.net/package/Services_JSON">donwload this package</a> and get the source code or just <a href="http://mike.teczno.com/JSON/JSON.phps">copy and paste the code here</a>.  Simply replace the code in the <em><em>wp-content/plugins/wp-post-thumbnail/</em>json.php</em> file with this code.  But you&#8217;re not done yet.  Keep reading.</p>
<h2>Avoid Conflicts With Other WordPress Plugins</h2>
<p>There are other WordPress plugins that use this code for their own json_encode() substitutes.  <a href="http://wordpress.org/extend/plugins/twitter-tools/">Twitter Tools</a> is one.  If you have Twitter Tools installed and include this code with the WPPT plugin, your whole WordPress installation will break because you&#8217;ll be declaring the classes Services_JSON and Services_JSON_Error in two places which isn&#8217;t allowed.  To avoid this, I namespaced the class names in the json.php file by prepending Wppt_ to the class names.</p>
<p>Do a search and find all instances of these lines:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Services_JSON
<span style="color: #000000; font-weight: bold;">class</span> Services_JSON_Error</pre></div></div>

<p>Replace with these respectively:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Wppt_Services_JSON
<span style="color: #000000; font-weight: bold;">class</span> Wppt_Services_JSON_Error</pre></div></div>

<h2>Final Step</h2>
<p>Add the following code at the end of the <em>wp-content/plugins/wp-post-thumbnail/includes/json.php</em> file so that when the WPPT plugin calls json_encode() or json_decode(), these functions will be called:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$json</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Wppt_Services_JSON<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$json</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>encode<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> <span style="color: #990000;">json_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$json</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Wppt_Services_JSON<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$json</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>decode<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>That should do it.  The WPPT plugin should work without any errors.  One thing to note is that any subsequent plugins that rely on the PHP&#8217;s JSON extension will also use the functions you just defined above.  I&#8217;m willing to live with this since the Services_JSON package is vetted by virtue of being part of PEAR.  Should the client&#8217;s web host decide to version up PHP, all plugins will start using the native JSON functions and mine will simply fade into obscurity.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/fixing-wp-post-thumbnail-plugin-json-response-parse-errors/411/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Cross-browser Rounded Corner Solution</title>
		<link>http://www.boomtownig.com/blog/a-cross-browser-rounded-corner-compromise-solution/310/</link>
		<comments>http://www.boomtownig.com/blog/a-cross-browser-rounded-corner-compromise-solution/310/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 12:25:04 +0000</pubDate>
		<dc:creator>Jamey Hoff</dc:creator>
				<category><![CDATA[Applications Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Website Design]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=310</guid>
		<description><![CDATA[After much trial and error, deliberation, research, and head banging on my desk, I&#8217;ve finally come up with a solution to the programmer&#8217;s age-old cross-browser rounded corners dilemma that works for me. The dilemma, of course, is that it&#8217;s the year 2009 and rounded corners can be implemented in EVERY modern-day browser except our friend...]]></description>
			<content:encoded><![CDATA[<p>After much trial and error, deliberation, research, and head banging on my desk, I&#8217;ve finally come up with a solution to the programmer&#8217;s age-old cross-browser rounded corners dilemma that works for me. The dilemma, of course, is that it&#8217;s the year 2009 and rounded corners can be implemented in EVERY modern-day browser except our friend Internet Explorer. Even the most recent incarnation of IE (v8) STILL doesn&#8217;t support native rounded corners in CSS!</p>
<p>After dealing with rounded corner images, CSS hacks, javascript hacks, and extraneous markup hacks for years, I decided it was time to put this thing to rest and come up with a solution that works for every design I&#8217;m translating into CSS, no matter where the rounded corners appear (nav bar, floating divs, on images, on background images, etc&#8230;)</p>
<p>If you know anything about me you know that I&#8217;m a stickler for semantic markup and clean code in general. XHTML and CSS that validate. So you&#8217;ll get an idea of my frustration level with this rounded corner issue when you hear that the solution I&#8217;ve settled upon doesn&#8217;t validate CSS. Yes that&#8217;s right. However I&#8217;m sleeping just fine and I&#8217;m quite happy that this solution is keeping me from spending 20 hours to create a style sheet!</p>
<p>So what is it you ask?</p>
<p>In short, I&#8217;m using native CSS rounded corner support for all browsers except IE&#8230; and for IE I&#8217;m implementing the BEST javascript-based rounded corner solution I&#8217;ve found to date: <a href="http://www.dillerdesign.com/experiment/DD_roundies/" target="_blank">DD_roundies</a>. So in my CSS I use the standard Gecko and Webkit syntax for achieving my rounded corners. I then use conditional comments to include the DD_roundies solution for any version of IE. It&#8217;s that simple.</p>
<p>I&#8217;ve tried EVERY single rounded corner javascript library out there. I&#8217;m not kdding&#8230; at least 20 different solutions. None work as well in IE as DD_roundies. In fact, conditional comments aren&#8217;t even 100% necessary since DD_roundies won&#8217;t invoke on any browser except the IE&#8217;s! So in the end I get a style sheet that validates EVERYTHING except the border-radius properties, and a design that can include rounded corners almost anywhere I desire. It&#8217;s a sacrifice I&#8217;m willing to live with.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/a-cross-browser-rounded-corner-compromise-solution/310/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Social Bookmarking Submission URLs</title>
		<link>http://www.boomtownig.com/blog/social-bookmarking-submission-urls/257/</link>
		<comments>http://www.boomtownig.com/blog/social-bookmarking-submission-urls/257/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 19:39:49 +0000</pubDate>
		<dc:creator>Jamey Hoff</dc:creator>
				<category><![CDATA[Applications Programming]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=257</guid>
		<description><![CDATA[A recent project I worked on required that I implement 8-10 &#8220;social bookmarking&#8221; links. You know the cryptic little links or icons you see on many sites that say &#8220;share this on [random site here]?&#8221; Share this on Facebook, Twitter, Reddit, Digg, Myspace, etc. Nowadays they’re on everyone’s blog and they’re making their way onto...]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:Compatibility> <w:BreakWrappedTables /> <w:SnapToGridInCell /> <w:WrapTextWithPunct /> <w:UseAsianBreakRules /> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]-->A recent project I worked on required that I implement 8-10 &#8220;social bookmarking&#8221; links. You know the cryptic little links or icons you see on many sites that say &#8220;share this on [random site here]?&#8221;<span> </span>Share this on Facebook, Twitter, Reddit, Digg, Myspace, etc.<span> </span>Nowadays they’re on everyone’s blog and they’re making their way onto “normal” web sites as well.<span> </span>For good reason too because they&#8217;re an excellent way for you to share a web page or article that you find interesting with your social network of choice.  Check out the little &#8220;Share and Enjoy&#8221; section at the bottom of this post&#8230; that&#8217;s what I&#8217;m talking about!</p>
<h2 class="MsoNormal">Submission URLs</h2>
<p class="MsoNormal">These social bookmarking links are powered by &#8220;submission URLs.&#8221; This is simply a web address (URL) specific to the social bookmarking web site, to which you can &#8220;submit” or &#8220;share&#8221; your article or web page.<span> </span>Each site has it’s own URL that they’ve setup.<span> </span>Programmers like me just make sure that on every page of the site, the little icon for sharing this page on Facebook (or whatever site I choose) links to Facebook properly using the submission URL.<span> </span>So in short, Jane Doe visits my site, finds an incredibly interesting article and wants to share it with her family who all have Facebook accounts.<span> </span>She clicks on my “Share this on Facebook” icon and she’s redirected to the Facebook site (by the submission URL) and after she logs in, uses Facebook’s interface for posting my article to her profile.<span> </span>Done!</p>
<h2 class="MsoNormal">So what’s the problem?</h2>
<p class="MsoNormal">Well there are literally HUNDREDS of social bookmarking sites out there.<span> </span>Everyday more are created while others are gaining in popularity.<span> </span>Well that’s a lot of submission URLs for me to find if I want to make social bookmarking available on my site!<span> </span>Would you believe that it took me and a coworker several HOURS to find a resource that simply compiled a bunch of submission URLs?!<span> </span>And we’re two able-bodied, internet-savvy people.<span> </span>I was shocked at how difficult it was to track down submission URLs for this project.<span> </span>And going directly to each social bookmarking site wasn’t much help!<span> </span>It seems as though this information is buried deeply in help documentation.<span> </span>Why??</p>
<p class="MsoNormal"><span> </span></p>
<h2 class="MsoNormal">The solution</h2>
<p class="MsoNormal">Fortunately we eventually stumbled upon two web sites that were of the most help:<br />
<!--[endif]--></p>
<ul style="margin-top: 0in;" type="disc">
<li class="MsoNormal">Kevin      van Zonneveld’s <a href="http://kevin.vanzonneveld.net/techblog/article/list_of_social_bookmarking_sites/">“List      of social bookmarking sites”</a></li>
<li class="MsoNormal">Jquery’s      <a href="http://keith-wood.name/bookmark.html">Bookmark plug-in</a>!</li>
</ul>
<p class="MsoNormal">I was able to easily find submission URLs for the 8-10 sites I needed, directly from these sites or by viewing source.<span> </span>Nice!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/social-bookmarking-submission-urls/257/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft adCenter join hands with Wall Street Journal Digital Network for Content Ads</title>
		<link>http://www.boomtownig.com/blog/adcenter-content-ads/66/</link>
		<comments>http://www.boomtownig.com/blog/adcenter-content-ads/66/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 13:35:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Applications Programming]]></category>

		<guid isPermaLink="false">http://www.boomtownig.com/blog/?p=66</guid>
		<description><![CDATA[
Microsoft announced on Tuesday, January 29, 2008, on the adCenter Official Blog that  Microsoft adcenter and The Wall Street Journal Digital Network reached an agreement in which Microsoft will become the exclusive provider of contextual and paid search advertisements for The Wall Street Journal Digital Network (WSJDN). Wall Street Journal Digital Network includes many...]]></description>
			<content:encoded><![CDATA[<div class="content">
<p>Microsoft announced on Tuesday, January 29, 2008, on the <a href="http://adcenterblog.spaces.live.com/Blog/cns%2185E824269AB8C30D%21645.entry">adCenter Official Blog</a> that  Microsoft adcenter and The Wall Street Journal Digital Network reached an agreement in which Microsoft will become the exclusive provider of contextual and paid search advertisements for The Wall Street Journal Digital Network (WSJDN). Wall Street Journal Digital Network includes many popular websites including WSJ.com, Barrons.com, Marketwatch.com, allthingsd.com and other sites.</p>
<p>Wall Street Journal Digital Network (WSJDN) reaches worldwide viewers of over 20 million users &amp; serves over 330 million page views per month. This agreement marks an exciting increase in reach and significance for adCenter customers bidding on financial services keywords. Contextual advertising will automatically begin on the WSJDN starting in February 2008. Now Microsoft adCenter customer can extend their ads to the WSJDN in February, 2008. Timing for Paid Search advertising on WSJDN is still being determined by Microsoft.</p>
<p>Microsoft also mentions many content tips at there official blog. Here are some of them:</p>
<ul>
<li>Increasing your bids to position your ads to appear.</li>
<li>Monitor your ROI with conversion tracking.</li>
<li>Write compelling ad copy.</li>
<li>Contextual ads reach targeted audiences.</li>
</ul>
<p>Now advertiser can list there business on high traffic editorial pages &#8211; ad space that was completely reserved for limited advertisers. You may find more information about this <a href="http://adcenterblog.spaces.live.com/Blog/cns%2185E824269AB8C30D%21645.entry">here</a>.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.boomtownig.com/blog/adcenter-content-ads/66/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
