<?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>BIT Consultants &#187; Code Snippets</title>
	<atom:link href="http://www.bitconsultants.net/category/development/code-snippets/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bitconsultants.net</link>
	<description></description>
	<lastBuildDate>Sat, 28 Jan 2012 02:19:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Javascript Querystring Parameters</title>
		<link>http://www.bitconsultants.net/2011/javascript-querystring-parameters/</link>
		<comments>http://www.bitconsultants.net/2011/javascript-querystring-parameters/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 22:39:37 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=486</guid>
		<description><![CDATA[Hi all, just wrote up a javascript object to parse url parameters. You can take parameters out of the querystring or the url hash. Usage Script]]></description>
			<content:encoded><![CDATA[<p>Hi all, just wrote up a javascript object to parse url parameters. You can take parameters out of the querystring or the url hash.</p>
<p>Usage</p>
<pre class="brush: jscript; title: Code Example; notranslate">
//assuming <a href="http://www.example.com/index/?foo=bar&#038;baz=baa#test=true" rel="nofollow">http://www.example.com/index/?foo=bar&#038;baz=baa#test=true</a>

url.href;
//returns <a href="http://www.example.com/index/?foo=bar&#038;baz=baa#test=true" rel="nofollow">http://www.example.com/index/?foo=bar&#038;baz=baa#test=true</a>

url.path
//return /index/?foo=bar&amp;baz=baa#test=true

url.get('foo');
//returns 'bar'

url.get('test');
//returns true
</pre>
<p>Script</p>
<pre class="brush: jscript; title: Code Example; notranslate">
var url = (function(){
	var _href = location.href;
	var _path = location.pathname;
	var _qs = location.search.replace(/\?/, '');
	var _hash = location.hash.replace(/\#/, '');

	var _parse = function(string){
		var params = string.split('&amp;');
		var holder = [];

		for(var i = 0; i &lt; params.length; i++){
				var temp 	= params[i].split('=');
				var key 	= temp[0];
				var val 		= temp[1];
				holder[key] = val;
		}
		return holder;
	};

	var _qs_params 	= _parse(_qs);
	var _hash_params = _parse(_hash);

	return {
		href:_href,
		path:_path,
		get:function(name){
			var retval = null;
			if(_qs_params[name] !== undefined){
				retval = _qs_params[name];
			} else if(_hash_params[name] !== undefined) {
				retval = _hash_params[name];
			}
			return retval;
		},
		go:function(loc){
			location.href = loc;
		},
		back:function(item){
			if(item !== undefined){
				item = -1;
			}
			history.go(item);
		}
	};
})();
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2011/javascript-querystring-parameters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XAMPP ulimit error on Mac OSX</title>
		<link>http://www.bitconsultants.net/2011/xampp-ulimit-error-on-mac-osx/</link>
		<comments>http://www.bitconsultants.net/2011/xampp-ulimit-error-on-mac-osx/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 22:59:39 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Troubleshooting]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[OSX]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=372</guid>
		<description><![CDATA[If you are running XAMPP on Mac and can&#8217;t start apache, you are likely getting an unhelpful error message. If the message is blank, it could be<a href="http://www.bitconsultants.net/2011/xampp-ulimit-error-on-mac-osx/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p>If you are running XAMPP on Mac and can&#8217;t start apache, you are likely getting an unhelpful error message. If the message is blank, it could be because one of your local websites doesn&#8217;t have a logs folder; it could also be a hostname issue. If you are getting an error regarding ulimit and have tried the other fix on the web (commenting out the three lines related to ulimit in /Applications/XAMPP/xamppfiles/bin/apachectl) then your problem is likely related to hostname binding.</p>
<p>Check your error log at:</p>
<pre class="brush: bash; title: Code Example; notranslate">
tail -f /Applications/XAMPP/xamppfiles/logs/error_log
</pre>
<p>Start apache and see if you get an error regarding nodename or hostname</p>
<p>In terminal again, run the following command:</p>
<pre class="brush: bash; title: Code Example; notranslate">
ping $(hostname)
</pre>
<p>If you get no response, then your hostname is not bound to your IP address, and apache doesn&#8217;t like that. Here is how you fix it:</p>
<pre class="brush: bash; title: Code Example; notranslate">
echo &quot;127.0.0.1 &quot; $(hostname) | pbcopy
</pre>
<p>Open your /etc/hosts file and paste your clipboard contents in, restart apache and it should be working fine.</p>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2011/xampp-ulimit-error-on-mac-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simplified Interface to HTML5 local storage</title>
		<link>http://www.bitconsultants.net/2010/simplified-interface-to-html5-local-storage/</link>
		<comments>http://www.bitconsultants.net/2010/simplified-interface-to-html5-local-storage/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 06:00:45 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=336</guid>
		<description><![CDATA[Documentation &#038; Sandbox: http://rmcvey.github.com/jsper Cart example: http://rmcvey.github.com/jsper/cart_example.html I decided it was time to dive into the HTML5 local storage API the other night, knowing that it has<a href="http://www.bitconsultants.net/2010/simplified-interface-to-html5-local-storage/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p><strong>Documentation &#038; Sandbox:</strong> <a href="http://rmcvey.github.com/jsper">http://rmcvey.github.com/jsper</a><br />
<strong>Cart example:</strong> <a href="http://rmcvey.github.com/jsper/cart_example.html">http://rmcvey.github.com/jsper/cart_example.html</a><br />
<br />
I decided it was time to dive into the HTML5 local storage API the other night, knowing that it has a lot of potential. There are a few  problems inherent to using it, the biggest problem being lack of support in older browsers (and to a lesser degree that it is not implemented exactly the same across browsers). The other major problem I have with localStorage is that you can only store strings. I have found a few classes that help with localStorage, but I have problems with them too because:</p>
<ul>
<li>they utilize browser plugins like Flash</li>
<li>are enormously cumbersome to use with too many configuration options,</li>
<li>and once again, only store strings. </li>
<li>no unit tests</li>
<li>buggy</li>
<li>did I mention they are cumbersome to use and only hold strings????</li>
</ul>
<p>So, I have set out to resolve these grievances and have come quite close with jsper.  JSPER is a wrapper class around local storage that provides a more friendly api to localStorage using simple get and set methods:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
jsper.set('foo', {bar:'baz',boz:{bez:'biz'}});
//jsper.get returns the type of object you gave it; in this case, an object
var my_object = jsper.get('foo');

jsper.set('arr', ['a', 'b', 'c', 'd']);
// returns an array
var my_array = jsper.get('arr');
</pre>
<p>In addition to automatic serialization/deserialization, there are a number of other useful methods, most of which (non-getters) are chainable, overloaded and accept callbacks. Jstore allows you to inspect the current storage engine, force a different storage engine (including session-lifetime storage).</p>
<p>Iterating over a collection</p>
<pre class="brush: jscript; title: Code Example; notranslate">
// set an array in storage
jsper.set('an_array', ['This', 'is', 'pretty', 'cool']);
var message = &quot;&quot;;
// perform iteration, data is the stored value and index is numerical index
jsper.each('an_array', function(data, index){
   message += &quot; &quot;+data;
});
console.log(message);//outputs: &quot;This is pretty cool&quot;
</pre>
<p>Lots more information @github: <a href="http://github.com/rmcvey/jsper">http://github.com/rmcvey/jsper</a><br />
Also, I made it into a jquery plugin if you are into that sort of thing: <a href="http://plugins.jquery.com/project/jsperdb"></p>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2010/simplified-interface-to-html5-local-storage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Validating Data with Enhanced Declarative Data Integrity Rules</title>
		<link>http://www.bitconsultants.net/2010/validating-data-using-tuples-stored-in-column-comments/</link>
		<comments>http://www.bitconsultants.net/2010/validating-data-using-tuples-stored-in-column-comments/#comments</comments>
		<pubDate>Sat, 08 May 2010 05:48:09 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=255</guid>
		<description><![CDATA[Visit us at our new Google Code project page: http://code.google.com/p/metadata-validator/ Problem Definition Data validation and integrity assurance are complex subjects that have strong opinions tied to the<a href="http://www.bitconsultants.net/2010/validating-data-using-tuples-stored-in-column-comments/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p><strong>Visit us at our new Google Code project page: <a href="http://code.google.com/p/metadata-validator/">http://code.google.com/p/metadata-validator/</a></strong></p>
<h2>Problem Definition</h2>
<p>Data validation and integrity assurance are complex subjects that have strong opinions tied to the way they are implemented. Some strongly feel that the database can handle validation using the column&#8217;s attributes (size, data type, etc) and TRIGGERS/STORED PROCEDURES can provide means to enforce complex business rules. This is true, but there are many caveats and arguments against this approach. Should a data source be performing logic? According to <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/triggers.htm#g22503">Oracle&#8217;s website</a>:</p>
<p style="padding-left: 30px;">&#8220;<em>Although triggers are useful for customizing a database, use them only when necessary. Excessive use of triggers can result in complex interdependencies, which can be difficult to maintain in a large application</em>&#8220;</p>
<p>Those in opposition to this approach feel that it is not the job of the database to perform logic, only to store data. So, who is right?<br />
How should data validation be handled? Triggers or code? Honestly, both is usually the practice. The current implementations of Declarative Data Integrity Rules in the database marketplace give us simple rules to validate against (again: size, data type, nullable, etc) and if we don&#8217;t validate data in our code prior to insertion the database errors out. Though mindless and tedious, it is a straightforward task to code validation prior to executing SQL in your programming language.</p>
<p>I think that both opinions are correct, but both approaches are inadequate. Logic <strong><em>should </em></strong>be separated from data. However, rules about data stored in your database are really metadata. Why should programmers have to tweak code every time the table changes? Why should DBAs have to worry that programmers validation is insufficient and not have any control over the data integrity? I believe the database should dictate to us, in specific terms, what it is expecting. In addition, programmers and DBAs should be able to work together to formulate the data validation and that is should be in only one place.</p>
<h2>Current Practice</h2>
<p>Most of the time, a DBA will create a table with data type, length, unique and referential constraints. These rules are enforced by the database, programmers are handed back an error message which has to be parsed into a friendly error. In some shops, STORED PROCEDURES and TRIGGERS are used to validate data prior to insertion. As we pointed out above, this is not an encouraged practice and makes a data source a logic engine.</p>
<p>Let&#8217;s say we have a table defined as such:</p>
<pre class="brush: sql; title: Code Example; notranslate">

id INT(8) NOT NULL,
name VARCHAR(40),
zip_code VARCHAR(10)
</pre>
<p>Programmers take the constraints defined above (i.e. &#8220;INT&#8221;, &#8220;NOT NULL&#8221;, 40, etc) and write up code validation for each of those columns. If DBAs alter the number of columns or the metadata of any one of the columns, the code needs to be updated accordingly. Conversely, if the programmers don&#8217;t properly validate the raw data in code, we could easily end up with &#8220;NOTAZIP&#8221; in our zip_code field. In this way, the technologies are seemingly blind of each other except for a tin-can phone that can pass simple messages back and forth. This is not a knock against the technology, they were made to be platform independent (in terms of interfacing) and not necessarily to know everything about each other.  This is the price we have to pay for an exceedingly friendly means of storing and retrieving data.</p>
<h2>Proposed Solution</h2>
<p>Utilizing dynamic functions, JSON and metadata stored in column comments of my database I was able to validate data against any table with only one validation class (that isn&#8217;t very long!). I have yet to see a column or table comment be anything slightly useful (if anything at all). Up until two days ago, every time I saw the field to insert a comment in phpmyadmin  I would think &#8220;I guess that&#8217;s a nice feature&#8230;&#8221;, and then move on. Then I realized that using (in MySQL) SHOW FULL COLUMN FROM {TABLE}, I can get that comment&#8217;s value back. And using my programming language (PHP), I could do the following:</p>
<pre class="brush: php; title: Code Example; notranslate">

$data = json_decode($comment);
</pre>
<p>I now am holding an object created from metadata to do what I will with.</p>
<p>The initial data I inserted into a column COMMENT was a minified representation of this:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
'{	&quot;insert_helpers&quot;: {
		&quot;functions&quot;: {
			&quot;func1&quot;:{
				&quot;name&quot;:&quot;strtotime&quot;,
				&quot;params&quot;:{
					&quot;param1&quot;:&quot;+20 years&quot;
				}
			},
			&quot;func2&quot;:{
				&quot;name&quot;:&quot;str_replace&quot;,
				&quot;params&quot;:{
					&quot;param1&quot;:&quot;!!&quot;,
					&quot;param2&quot;:&quot;!&quot;,
					&quot;param3&quot;:&quot;@this&quot;,
				}
			}
		}
	},
	&quot;validators&quot;: {
		&quot;maxlength&quot;:&quot;10&quot;,
		&quot;minlength&quot;:&quot;2&quot;,
		&quot;patterns&quot;:{
			&quot;pattern1&quot;:{
				&quot;pattern&quot;:&quot;[^0-9]&quot;,
				&quot;example&quot;:&quot;This is data without numbers&quot;
			}
		}
	}
}'
</pre>
<p>This was then validated with code very similar to this:</p>
<pre class="brush: php; title: Code Example; notranslate">
/**
*
* NOTE: I have not tested this code
* I typed directly it into notepad++ for your reading,
* not for executing, if it works, great!
*
*/
$json 				= json_decode($comment);
$helper_functions 	        = $json-&gt;{'insert_helpers'};
$validators			= $json-&gt;{'validators'};
$errors				= array();

//$row_value = $result['field'];
foreach($helper_functions as $function)
{
	$params = array();
	foreach($function-&gt;{'params'} as $param)
	{
		//insert row value
		if($param == '@this')
		{
			$param = str_replace(&quot;@this&quot;, $row_value, $param);
		}
		array_push($params, $param);
	}
	if(is_callable($function-&gt;{'name'})
	{
		$row_value = call_user_func_array($function-&gt;{'name'}, $params);
	}
}

if(is_object($validators))
{
	if(is_object($validators-&gt;{'minlength'})
	{
		if(sizeof($row_value) &lt; $validators-&gt;{'minlength'})
		{
			array_push($errors, &quot;$row_value is not long enough&quot;);
		}
	}
	if(is_object($validators-&gt;{'maxlength'})
	{
		if(sizeof($row_value) &gt; $validators-&gt;{'maxlength'})
		{
			array_push($errors, &quot;$row_value is too long&quot;);
		}
	}
	if(is_object($validators-&gt;{'patterns'})
	{
		foreach($validators-&gt;{'patterns'} as $pattern)
		{
			if(preg_match(&quot;/$pattern-&gt;{'pattern'}/&quot;, $row_value))
			{
				array_push($errors, &quot;$row_value is not in correct format [example: $pattern-&gt;{'example'}&quot;);
			}
		}
	}
}
</pre>
<p>If you didn&#8217;t pick it up by reading through the code, these functions couldn&#8217;t care less what table you are dealing with and the same set of code works against any and all columns. In addition, the validation rules (JSON) can be handed to the client side code to perform validation prior to reaching the server. All major databases have a comment column and most modern programming languages allow behavior like the example I posted.</p>
<p>I will post my php class that facilitates this process soon.</p>
<p>Anxious to hear people&#8217;s thoughts.</p>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2010/validating-data-using-tuples-stored-in-column-comments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Geocoding with Google Maps and the Zend Framework</title>
		<link>http://www.bitconsultants.net/2010/geocoding-with-google-maps-and-the-zend-framework/</link>
		<comments>http://www.bitconsultants.net/2010/geocoding-with-google-maps-and-the-zend-framework/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 17:51:40 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[Maps]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=231</guid>
		<description><![CDATA[Download Example Files: Zip RAR Maps are a great way to engage your users and visualize data, but it can be a little tricky to setup. Here<a href="http://www.bitconsultants.net/2010/geocoding-with-google-maps-and-the-zend-framework/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<h3><strong>Download Example Files</strong>:</h3>
<p> <a href="http://www.bitconsultants.net/examples/gmap.zip">Zip</a> <a href="http://www.bitconsultants.net/examples/gmap.rar">RAR</a><br />
<hr />
Maps are a great way to engage your users and visualize data, but it can be a little tricky to setup. Here I will walk you through the steps needed to get a map up and running.<br />
<script type="text/javascript">// <![CDATA[
 google_ad_client = "pub-4761320180230999"; /* 468x15, created 5/5/10 */ google_ad_slot = "9379654790"; google_ad_width = 468; google_ad_height = 15;
// ]]&gt;</script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script></p>
<h3>Sign Up</h3>
<p>Apply for a Google Maps API Key (free) here using your domain without a subdomain or www (this will allow you to use key with or without www and on subdomains): <a href="http://code.google.com/apis/maps/signup.html" rel="nofollow">http://code.google.com/apis/maps/signup.html</a></p>
<h3>Configuration</h3>
<p>Put the API key in your configuration file (application.ini, config.ini, etc.) like this:</p>
<pre class="brush: php; title: Code Example; notranslate">
[google]
google_map_key =  YOUR_KEY
</pre>
<h3>Bootstrapping</h3>
<p><del datetime="2011-01-08T03:34:24+00:00">In your index.php file, add the following code:</del><br />
As a concerned user pointed out, that is terrible practice and was a remnant of my first tinkerings with ZF. You should place this code in your Bootstrap.php file:</p>
<pre class="brush: php; title: Code Example; notranslate">
protected function initGoogle(){
	defined('CONFIG_PATH') or define('CONFIG_PATH', APPLICATION_PATH . '/configs/application.ini');
	Zend_Registry::set('google',  new Zend_Config_Ini(CONFIG_PATH, 'google'));
}
</pre>
<p>This will add your api key to the registry so that it can be accessed throughout your application.</p>
<h3>Model</h3>
<p>In your models directory, create a new class called &#8216;Geocoder.php&#8217;. This will be the file that contains the application logic for retreiving coordinates on a given location.</p>
<p><strong>models/Geocoder.php</strong></p>
<pre class="brush: php; title: Code Example; notranslate">

class Geocoder{
    protected $key;

    public function __construct($api_key)
    {
        $this-&gt;key = $api_key;
    }

    public function _getGeocodedLatitudeAndLongitude($address)
    {
        $client = new Zend_Http_Client();
        $client-&gt;setUri($this-&gt;getGeocodingUri());
        $client-&gt;setParameterGet('q', urlencode($address))
               -&gt;setParameterGet('output', 'json')
               -&gt;setParameterGet('sensor', 'false')
               -&gt;setParameterGet('key', $this-&gt;key);

        $result = $client-&gt;request('GET');
        $response = Zend_Json_Decoder::decode($result-&gt;getBody(),
                    Zend_Json::TYPE_OBJECT);
        return $response;
    }

    public function getCoordinates($address)
    {
        $response = $this-&gt;_getGeocodedLatitudeAndLongitude($address);
        if(isset($response-&gt;Placemark[0]-&gt;Point-&gt;coordinates[1])){
             return array(
                'lat' =&gt; $response-&gt;Placemark[0]-&gt;Point-&gt;coordinates[1],
                'lon' =&gt; $response-&gt;Placemark[0]-&gt;Point-&gt;coordinates[0]
            );
        } else {
			return null;
		}
    }

    private function getGeocodingUri()
    {
        return 'http://maps.google.com/maps/geo';
    }
}
?&gt;
</pre>
<h3>Usage</h3>
<p>Alright, that was pretty easy. Now we just have to implement this in our controller. Here is a sample model that uses the Geocoder class to return geotagged User objects.<br />
<strong>models/User.php</strong></p>
<pre class="brush: php; title: Code Example; notranslate">
class User extends Zend_Db_Table_Abstract{
	protected $_name = 'users';
	protected $key;
	protected $geocoder;

	public function init()
	{
		$this-&gt;key = Zend_Registry::get('google')-&gt;google_map_key;
		$this-&gt;geocoder = new Geocoder($this-&gt;key);

	}
	public function getUsersAndGeocode()
	{
		$result = $this-&gt;fetchAll();

		$users    = $result-&gt;_toArray();
		foreach($users as $user)
		{
			$address = &quot;{$user['address']} {$user['city']} {$user['state']} {$user['zip']}&quot;;

			$latlon = $this-&gt;geocoder-&gt;getCoordinates($address);
			if($latlon)
			{
				$user['lat'] = $latlon['lat'];
				$user['lon'] = $latlon['lon'];
			}
		}
		return $users;
	}

}
?&gt;
</pre>
<p>The controller part is a little too easy. We will setup a reference to our user table and create a map action. Within the map action we get all of users and geocode them. We pass that collection to our view. This file should be located here:<br />
<strong>controllers/UserController.php</strong></p>
<pre class="brush: php; title: Code Example; notranslate">
class UserController extends Zend_Controller_Action{
	protected $user_table;
	public function init()
	{
		//database connectivity stuff is up to you

		$this-&gt;user_table = new User();
	}
	public function mapAction()
	{
		$this-&gt;view-&gt;api_key = Zend_Registry::get('google')-&gt;google_map_key;
		$users = $this-&gt;user_table-&gt;getUsersAndGeocode();
		$this-&gt;view-&gt;users = $users;
	}
}
?&gt;
</pre>
<p>And finally, the view. Here we will create our map div, load the Google Maps API (don’t forget to sub out your key in the script src). We are using a custom marker here (personIcon); you can add your own image here by changing the path to your image. I recommend the image be pretty small with a transparent background. Given our current setup, this file would be located at this path:<br />
<strong>views/scripts/user/map.phtml</strong></p>
<pre class="brush: php; title: Code Example; notranslate">
&lt;div id=&quot;map&quot;&gt;

&lt;noscript&gt;
&lt;center&gt;
&lt;strong&gt;To view the map feature, you need to have Javascript enabled. If you are unsure about how to turn Javascript support on, please&lt;/p&gt;
&lt;p&gt;read Google's instructions found here: &lt;a href=&quot;https://www.google.com/support/adsense/bin/answer.py?hl=en&amp;amp;answer=12654&quot; target=&quot;_blank&quot;&gt;LINK&lt;/a&gt;&lt;/strong&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;/noscript&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps?file=api&amp;amp;amp;v=2&amp;amp;amp;sensor=false&amp;amp;amp;key=&lt;?=$this-&gt;api_key?&gt;&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
 //Sorry, I love jquery! If you don't use window.onload = function(){initialize();}
    $(document).ready(function(){
        initialize();
    });
var map;
var personIcon;
function initialize() {
    if(GBrowserIsCompatible){

        map = new google.maps.Map2(document.getElementById(&quot;map&quot;));
        map.setUIToDefault();
        map.setCenter(new google.maps.LatLng('48.858001709', '2.29460000992'), 4);

        personIcon            = new GIcon();

		/**
		* Change this marker to be a small transparent custom image
		*
		*/
        personIcon.image      = '/img/common/custom_marker.png';
        personIcon.shadow     = &quot;http://www.google.com/mapfiles/shadow50.png&quot;;
        personIcon.iconSize   = new GSize(32,32);
        personIcon.shadowSize = new GSize(37,34);

        personIcon.iconAnchor = new GPoint(9,34);
        personIcon.infoWindowAnchor = new GPoint(9,2);
    }
    addOverlays(map);
}

function personMarker(point, index, dto){
 //set our marker to be the custom icon we created
    markerOptions = {icon:personIcon};
    var marker = new GMarker(point, markerOptions);

/**
 * This is the content in the info bubble
 */
    GEvent.addListener(marker, 'click', function(){
       marker.openInfoWindowHtml(
            '&lt;h3&gt;&lt;a href=&quot;/profile/view/'+dto.user_id+'&quot;&gt;'+dto.user_first+' '+ dto.user_last+'&lt;/a&gt;&lt;/h3&gt;'+
            dto.user_address+' '+dto.user_city+' '+dto.user_state+' '+dto.user_zip
        );

    });
    return marker;
}
/*
* Here is where we loop through our users and create new markers for each

*/
function addOverlays(map){
    &lt;?php
  $geo = $this-&gt;users-&gt;_toArray();
        $size = sizeof($geo);

 ?&gt;
    &lt;? for($i = 0; $i &lt; $size; $i++): ?&gt;
                var latLon = new GLatLng(&lt;?php echo $geo[$i]['lat'];?&gt;, &lt;?php echo $geo[$i]['lon'];?&gt;);

                map.addOverlay(personMarker(latLon, &lt;?=$i?&gt;, &lt;?=Zend_Json::encode($geo[$i])?&gt;));
    &lt;?php endfor; ?&gt;
}
&lt;/script&gt;
</pre>
<p>Post a comment if you have any questions</p>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2010/geocoding-with-google-maps-and-the-zend-framework/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>jQuery Tabs Keyboard Shortcuts</title>
		<link>http://www.bitconsultants.net/2009/jquery-tabs-keyboard-shortcuts/</link>
		<comments>http://www.bitconsultants.net/2009/jquery-tabs-keyboard-shortcuts/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 02:49:50 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=240</guid>
		<description><![CDATA[I have integrated jQuery&#8217;s UI tabs into a number of my projects and have had to significantly modify the code to achieve some goals (like being able<a href="http://www.bitconsultants.net/2009/jquery-tabs-keyboard-shortcuts/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p>I have integrated jQuery&#8217;s UI tabs into a number of my projects and have had to significantly modify the code to achieve some goals (like being able to easily add and remove tabs. One of the simpler thing I have done with the tabbed interface is let users navigate them using keyboard shortcuts. Here is a simple snippet I use to allow users to select a tab using alt+number. I use the js-hotkeys plugin found <a href="http://www.google.com/url?sa=t&amp;source=web&amp;ct=res&amp;cd=4&amp;ved=0CBUQFjAD&amp;url=http%3A%2F%2Fcode.google.com%2Fp%2Fjs-hotkeys%2F&amp;ei=s__US4njBcKB8gb807DlDw&amp;usg=AFQjCNGt_wU-gT73jN7XAqGDx6vfWymgSQ&amp;sig2=P7ja4dADKQ_JLe3DYOycYQ" target="_blank">here</a></p>
<pre class="brush: xml; title: Code Example; notranslate">
&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;Keyboard Tabs&lt;/title&gt;
		&lt;link rel=&quot;stylesheet&quot; href=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css&quot; type=&quot;text/css&quot; /&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;http://js-hotkeys.googlecode.com/files/jquery.hotkeys-0.7.9.min.js&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot;&gt;
			$(document).ready(function(){
                //initialize tabs
				$tabs = $('#tabs').tabs();
                //create a reference to our document
				var this_document = $(document);
                //nothing fancy, just iterate over a number set and generate the shortcuts
				$.each([1,2,3,4,5,6,7,8,9], function(index){
					this_document.bind('keydown', 'alt+'+index, function(e){
						 $tabs.tabs('select', (index - 1));
						 e.preventDefault();
					 });
				});
			});
		&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div class=&quot;demo&quot;&gt;

		&lt;div id=&quot;tabs&quot;&gt;
			&lt;ul&gt;
				&lt;li&gt;&lt;a href=&quot;#tabs-1&quot;&gt;Nunc tincidunt&lt;/a&gt;&lt;/li&gt;
				&lt;li&gt;&lt;a href=&quot;#tabs-2&quot;&gt;Proin dolor&lt;/a&gt;&lt;/li&gt;
				&lt;li&gt;&lt;a href=&quot;#tabs-3&quot;&gt;Aenean lacinia&lt;/a&gt;&lt;/li&gt;
			&lt;/ul&gt;
			&lt;div id=&quot;tabs-1&quot;&gt;
				&lt;p&gt;Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.&lt;/p&gt;
			&lt;/div&gt;
			&lt;div id=&quot;tabs-2&quot;&gt;
				&lt;p&gt;Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.&lt;/p&gt;
			&lt;/div&gt;
			&lt;div id=&quot;tabs-3&quot;&gt;
				&lt;p&gt;Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.&lt;/p&gt;
				&lt;p&gt;Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.&lt;/p&gt;
			&lt;/div&gt;
		&lt;/div&gt;

		&lt;/div&gt;&lt;!-- End demo --&gt;

		&lt;div style=&quot;display: none;&quot; class=&quot;demo-description&quot;&gt;

		&lt;p&gt;Click tabs to swap between content that is broken into logical sections.&lt;/p&gt;
		&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>If you missed the part that did the shortcuts, here it is again:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
$(document).ready(function(){
                //initialize tabs
				$tabs = $('#tabs').tabs();
                //create a reference to our document
				var this_document = $(document);
                //nothing fancy, just iterate over a number set and generate the shortcuts
				$.each([1,2,3,4,5,6,7,8,9], function(index){
					this_document.bind('keydown', 'alt+'+index, function(e){
						 $tabs.tabs('select', (index - 1));
						 e.preventDefault();
					 });
				});
			});
</pre>
<p>That&#8217;s it! If you have any questions, please post!</p>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2009/jquery-tabs-keyboard-shortcuts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Actionscript 2.0: Centered Popup Window</title>
		<link>http://www.bitconsultants.net/2009/actionscript-2-0-centered-popup-window/</link>
		<comments>http://www.bitconsultants.net/2009/actionscript-2-0-centered-popup-window/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 05:31:31 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=136</guid>
		<description><![CDATA[Centered popup for Actionscript 2.0]]></description>
			<content:encoded><![CDATA[<p>At some point we all need a centered popup windows. Here is a useful Actionscript 2.0 function to help get a popup window, that allows for some customization based on input parameters. Check the actual implementation at the bottom. It is also worth mentioning here, that no AS popup script will work in local testing mode. You must upload to a server (or move to a local server directory) for this to function properly.</p>
<pre class="brush: jscript; title: Code Example; notranslate">

function winOpen(url:String, winName:String, wide:Number, high:Number, chrome:Boolean, centered:Boolean)
{
//Chrome on window un-centered
if (chrome == true &amp;&amp; centered == false)­
{
getURL(&quot;javascript:&quot;+winName+&quot;=window.open('&quot;+url+&quot;', '&quot;+winName+&quot;', 'width=&quot;+wide+&quot;,height=&quot;+high+&quot;,left=0,top=0,toolbar=1,location=1,scrollbars=1,status=1,resizable=1,fullscreen=no'); &quot;+winName+&quot;.focus(); void(0);&quot;);
}
//Chromeless un-centered
else if (chrome == false &amp;&amp; centered == false)­
{
getURL(&quot;javascript:&quot;+winName+&quot;=window.open('&quot;+url+&quot;', '&quot;+winName+&quot;', 'width=&quot;+wide+&quot;,height=&quot;+high+&quot;'); &quot;+winName+&quot;.focus(); void(0);&quot;);
}
//Chrome on, centered
else if (chrome == true &amp;&amp; centered == true)
{
getURL(&quot;javascript:&quot;+winName+&quot;=window.open('&quot;+url+&quot;', '&quot;+winName+&quot;', 'width=&quot;+wide+&quot;,height=&quot;+high+&quot;,left=0,top=0,toolbar=1,location=1,scrollbars=1,status=1,resizable=1,fullscreen=no'); &quot;+winName+&quot;.focus(); screen_height = window.screen.availHeight;screen_width = window.screen.availWidth; left_point = parseInt(screen_width/2)-(&quot;+wide+&quot;/2); top_point = parseInt(screen_height/2)-(&quot;+high+&quot;/2); setTimeout('&quot;+winName+&quot;.moveTo(left_point,top_point)',10); void(0);&quot;);
}
//Chromeless, centered (most popular!)
else if (chrome == false &amp;&amp; centered == true)
{
getURL(&quot;javascript:&quot;+winName+&quot;=window.open('&quot;+url+&quot;', '&quot;+winName+&quot;', 'width=&quot;+wide+&quot;,height=&quot;+high+&quot;,left=0,top=0,toolbar=no,location=no,scrollbars=no,status=no,resizable=no,fullscreen=no'); &quot;+winName+&quot;.focus(); screen_height = window.screen.availHeight;screen_width = window.screen.availWidth; left_point = parseInt(screen_width/2)-(&quot;+wide+&quot;/2); top_point = parseInt(screen_height/2)-(&quot;+high+&quot;/2); setTimeout('&quot;+winName+&quot;.moveTo(left_point,top_point)',10); void(0);&quot;);
}
}

//Sample of application, requires a button with instance name of button_mc on stage
button_mc.onRelease = function()
{
winOpen(&quot;http://www.bitconsultants.net/&quot;, &quot;MyWindow&quot;, 350, 350, true, true);
­}
</pre>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">
<pre class="geshifilter-actionscript"><span style="color: #000000; font-weight: bold;">function</span> winOpen<span style="color: #66cc66;">(</span><span style="color: #0066cc;">url</span>:<span style="color: #0066cc;">String</span>, winName:<span style="color: #0066cc;">String</span>, wide:<span style="color: #0066cc;">Number</span>, high:<span style="color: #0066cc;">Number</span>, chrome:<span style="color: #0066cc;">Boolean</span>, centered:<span style="color: #0066cc;">Boolean</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">{</span>
    <span style="color: #808080; font-style: italic;">//Chrome on window un-centered</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>chrome == <span style="color: #000000; font-weight: bold;">true</span> &amp;&amp; centered == <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">)</span>­
    <span style="color: #66cc66;">{</span>
        <span style="color: #0066cc;">getURL</span><span style="color: #66cc66;">(</span><span style="color: #ff0000;">"javascript:"</span>+winName+<span style="color: #ff0000;">"=window.open('"</span>+<span style="color: #0066cc;">url</span>+<span style="color: #ff0000;">"', '"</span>+winName+<span style="color: #ff0000;">"', 'width="</span>+wide+<span style="color: #ff0000;">",height="</span>+high+<span style="color: #ff0000;">",left=0,top=0,toolbar=1,location=1,scrollbars=1,status=1,resizable=1,fullscreen=no'); "</span>+winName+<span style="color: #ff0000;">".focus(); void(0);"</span><span style="color: #66cc66;">)</span>;
    <span style="color: #66cc66;">}</span>
    <span style="color: #808080; font-style: italic;">//Chromeless un-centered</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>chrome == <span style="color: #000000; font-weight: bold;">false</span> &amp;&amp; centered == <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">)</span>­
    <span style="color: #66cc66;">{</span>
        <span style="color: #0066cc;">getURL</span><span style="color: #66cc66;">(</span><span style="color: #ff0000;">"javascript:"</span>+winName+<span style="color: #ff0000;">"=window.open('"</span>+<span style="color: #0066cc;">url</span>+<span style="color: #ff0000;">"', '"</span>+winName+<span style="color: #ff0000;">"', 'width="</span>+wide+<span style="color: #ff0000;">",height="</span>+high+<span style="color: #ff0000;">"'); "</span>+winName+<span style="color: #ff0000;">".focus(); void(0);"</span><span style="color: #66cc66;">)</span>;
    <span style="color: #66cc66;">}</span>
    <span style="color: #808080; font-style: italic;">//Chrome on, centered</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>chrome == <span style="color: #000000; font-weight: bold;">true</span> &amp;&amp; centered == <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">)</span>
    <span style="color: #66cc66;">{</span>
        <span style="color: #0066cc;">getURL</span><span style="color: #66cc66;">(</span><span style="color: #ff0000;">"javascript:"</span>+winName+<span style="color: #ff0000;">"=window.open('"</span>+<span style="color: #0066cc;">url</span>+<span style="color: #ff0000;">"', '"</span>+winName+<span style="color: #ff0000;">"', 'width="</span>+wide+<span style="color: #ff0000;">",height="</span>+high+<span style="color: #ff0000;">",left=0,top=0,toolbar=1,location=1,scrollbars=1,status=1,resizable=1,fullscreen=no'); "</span>+winName+<span style="color: #ff0000;">".focus(); screen_height = window.screen.availHeight;screen_width = window.screen.availWidth; left_point = parseInt(screen_width/2)-("</span>+wide+<span style="color: #ff0000;">"/2); top_point = parseInt(screen_height/2)-("</span>+high+<span style="color: #ff0000;">"/2); setTimeout('"</span>+winName+<span style="color: #ff0000;">".moveTo(left_point,top_point)',10); void(0);"</span><span style="color: #66cc66;">)</span>;
    <span style="color: #66cc66;">}</span>
    <span style="color: #808080; font-style: italic;">//Chromeless, centered (most popular!)</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>chrome == <span style="color: #000000; font-weight: bold;">false</span> &amp;&amp; centered == <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">)</span>
    <span style="color: #66cc66;">{</span>
        <span style="color: #0066cc;">getURL</span><span style="color: #66cc66;">(</span><span style="color: #ff0000;">"javascript:"</span>+winName+<span style="color: #ff0000;">"=window.open('"</span>+<span style="color: #0066cc;">url</span>+<span style="color: #ff0000;">"', '"</span>+winName+<span style="color: #ff0000;">"', 'width="</span>+wide+<span style="color: #ff0000;">",height="</span>+high+<span style="color: #ff0000;">",left=0,top=0,toolbar=no,location=no,scrollbars=no,status=no,resizable=no,fullscreen=no'); "</span>+winName+<span style="color: #ff0000;">".focus(); screen_height = window.screen.availHeight;screen_width = window.screen.availWidth; left_point = parseInt(screen_width/2)-("</span>+wide+<span style="color: #ff0000;">"/2); top_point = parseInt(screen_height/2)-("</span>+high+<span style="color: #ff0000;">"/2); setTimeout('"</span>+winName+<span style="color: #ff0000;">".moveTo(left_point,top_point)',10); void(0);"</span><span style="color: #66cc66;">)</span>;
    <span style="color: #66cc66;">}</span>
<span style="color: #66cc66;">}</span>

<span style="color: #808080; font-style: italic;">//Sample of application, requires a button with instance name of button_mc on stage</span>
button_mc.<span style="color: #0066cc;">onRelease</span> = <span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">{</span>
    winOpen<span style="color: #66cc66;">(</span><span style="color: #ff0000;">"http://www.bitconsultants.net/"</span>, <span style="color: #ff0000;">"MyWindow"</span>, <span style="color: #cc66cc;">350</span>, <span style="color: #cc66cc;">350</span>, <span style="color: #000000; font-weight: bold;">true</span>, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">)</span>;
­<span style="color: #66cc66;">}</span></pre>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2009/actionscript-2-0-centered-popup-window/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Alternating Table Rows with PHP</title>
		<link>http://www.bitconsultants.net/2008/alternating-table-rows-with-php/</link>
		<comments>http://www.bitconsultants.net/2008/alternating-table-rows-with-php/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 05:44:22 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=140</guid>
		<description><![CDATA[Using PHP and CSS, it&#8217;s very easy to create a report-style table with alternating colors on each row. This setup assumes a connection to a MySQL database<a href="http://www.bitconsultants.net/2008/alternating-table-rows-with-php/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p>Using <strong>PHP </strong>and <strong>CSS</strong>, it&#8217;s very easy to create a report-style table with alternating colors on each row. This setup assumes a connection to a MySQL database (though any supported DBMS will work), and that you have already queried your database and are ready to work with the results in your php code.</p>
<p>CSS</p>
<pre class="brush: css; title: Code Example; notranslate">
.norm{
color:#fff;
background-color:#000;
}

.alt{
color:#000;
background-color:#fff;
}
</pre>
<p>PHP Code:</p>
<pre class="brush: php; title: Code Example; notranslate">

&lt;?php

$style = 0;//switch to know which row we are on
echo '&lt;table&gt;';
while($row = mysql_fetch_array($query))
{
$name = $row['name'];//for each corresponding column name you wish to show
$add   =  $row['address'];
$email = $row['email'];

if($style == 0)
{
echo '&lt;tr class=&quot;norm&quot;&gt;';
echo '&lt;td&gt;'.$name.'&lt;/td&gt;';
echo '&lt;td&gt;'.$add.'&lt;/td&gt;';
echo '&lt;td&gt;'.$email.'&lt;/td&gt;';
echo '&lt;/tr&gt;';
$style++;
}else{
echo '&lt;tr class=&quot;alt&quot;&gt;';
echo '&lt;td&gt;'.$name.'&lt;/td&gt;';
echo '&lt;td&gt;'.$add.'&lt;/td&gt;';
echo '&lt;td&gt;'.$email.'&lt;/td&gt;';
echo '&lt;/tr&gt;';
$style--;
}
}
echo '&lt;/table&gt;';

?&gt;
</pre>
<p>That&#8217;s all, not much to it really.</p>
<p>Edit: It should be stated that this could be accomplished in a much more simple manner using the ternary operator to conditionally set the class, here is what that would look like:</p>
<pre class="brush: php; title: Code Example; notranslate">

&lt;?php

$style = 'norm';//switch to know which row we are on
echo '&lt;table&gt;';
while($row = mysql_fetch_array($query))
{
$name = $row['name'];//for each corresponding column name you wish to show
$add   =  $row['address'];
$email = $row['email'];
echo '&lt;tr class=&quot;'.$style.'&quot;&gt; ';
echo '&lt;td&gt;'.$name.'&lt;/td&gt;';
echo '&lt;td&gt;'.$add.'&lt;/td&gt;';
echo '&lt;td&gt;'.$email.'&lt;/td&gt;';
echo '&lt;/tr&gt;';
$style = ($style == 'norm') ? 'alt' : 'norm';
}
echo '&lt;/table&gt;';

?&gt;
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2008/alternating-table-rows-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery U.S. States Autocomplete</title>
		<link>http://www.bitconsultants.net/2008/jquery-u-s-states-autocomplete/</link>
		<comments>http://www.bitconsultants.net/2008/jquery-u-s-states-autocomplete/#comments</comments>
		<pubDate>Sat, 26 Apr 2008 03:27:09 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=244</guid>
		<description><![CDATA[Yes, I looked too; but it&#8217;s not out there. Here is a quick plugin I wrote utilizing the popular jQuery Autocomplete function found here Add it to<a href="http://www.bitconsultants.net/2008/jquery-u-s-states-autocomplete/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p>Yes, I looked too; but it&#8217;s not out there. Here is a quick plugin I wrote utilizing the popular jQuery Autocomplete function found <a href="http://www.google.com/url?sa=t&amp;source=web&amp;ct=res&amp;cd=1&amp;ved=0CAYQFjAA&amp;url=http%3A%2F%2Fdocs.jquery.com%2FPlugins%2FAutocomplete&amp;ei=ggjVS7jDK4KB8gb10tUH&amp;usg=AFQjCNEwMF1oJ-qXvWtcwWbuVvL0RuLA7g&amp;sig2=qgwF3ATMeV-1NouqQ7PUHw" target="_blank">here</a></p>
<p>Add it to your form element by using:</p>
<pre class="brush: xml; title: Code Example; notranslate">
&lt;input type=&quot;text&quot; id=&quot;state_search&quot;  /&gt;
&lt;input type=&quot;hidden&quot; name=&quot;state&quot; /&gt;
...
&lt;script type=&quot;text/javascript&quot;&gt;
$('#state_search').states();
&lt;/script&gt;
</pre>
<p>Here is the list and the jQuery function:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
var state_autocomplete = [
{full:&quot;Alabama&quot;,abbr:&quot;AL&quot;},
{full:&quot;Alaska&quot;,abbr:&quot;AK&quot;},
{full:&quot;Arizona&quot;,abbr:&quot;AZ&quot;},
{full:&quot;Arkansas&quot;,abbr:&quot;AR&quot;},
{full:&quot;California&quot;,abbr:&quot;CA&quot;},
{full:&quot;Colorado&quot;,abbr:&quot;CO&quot;},
{full:&quot;Connecticut&quot;,abbr:&quot;CT&quot;},
{full:&quot;Delaware&quot;,abbr:&quot;DE&quot;},
{full:&quot;District of Columbia&quot;,abbr:&quot;DC&quot;},
{full:&quot;Florida&quot;,abbr:&quot;FL&quot;},
{full:&quot;Georgia&quot;,abbr:&quot;GA&quot;},
{full:&quot;Hawaii&quot;,abbr:&quot;HI&quot;},
{full:&quot;Idaho&quot;,abbr:&quot;ID&quot;},
{full:&quot;Illinois&quot;,abbr:&quot;IL&quot;},
{full:&quot;Indiana&quot;,abbr:&quot;IN&quot;},
{full:&quot;Iowa&quot;,abbr:&quot;IA&quot;},
{full:&quot;Kansas&quot;,abbr:&quot;KS&quot;},
{full:&quot;Kentucky&quot;,abbr:&quot;KY&quot;},
{full:&quot;Louisiana&quot;,abbr:&quot;LA&quot;},
{full:&quot;Maine&quot;,abbr:&quot;ME&quot;},
{full:&quot;Maryland&quot;,abbr:&quot;MD&quot;},
{full:&quot;Massachusetts&quot;,abbr:&quot;MA&quot;},
{full:&quot;Michigan&quot;,abbr:&quot;MI&quot;},
{full:&quot;Minnesota&quot;,abbr:&quot;MN&quot;},
{full:&quot;Mississippi&quot;,abbr:&quot;MS&quot;},
{full:&quot;Missouri&quot;,abbr:&quot;MO&quot;},
{full:&quot;Montana&quot;,abbr:&quot;MT&quot;},
{full:&quot;Nebraska&quot;,abbr:&quot;NE&quot;},
{full:&quot;Nevada&quot;,abbr:&quot;NV&quot;},
{full:&quot;New Hampshire&quot;,abbr:&quot;NH&quot;},
{full:&quot;New Jersey&quot;,abbr:&quot;NJ&quot;},
{full:&quot;New Mexico&quot;,abbr:&quot;NM&quot;},
{full:&quot;New York&quot;,abbr:&quot;NY&quot;},
{full:&quot;North Carolina&quot;,abbr:&quot;NC&quot;},
{full:&quot;North Dakota&quot;,abbr:&quot;ND&quot;},
{full:&quot;Ohio&quot;,abbr:&quot;OH&quot;},
{full:&quot;Oklahoma&quot;,abbr:&quot;OK&quot;},
{full:&quot;Oregon&quot;,abbr:&quot;OR&quot;},
{full:&quot;Pennsylvania&quot;,abbr:&quot;PA&quot;},
{full:&quot;Rhode island&quot;,abbr:&quot;RI&quot;},
{full:&quot;South Carolina&quot;,abbr:&quot;SC&quot;},
{full:&quot;South Dakota&quot;,abbr:&quot;SD&quot;},
{full:&quot;Tennessee&quot;,abbr:&quot;TN&quot;},
{full:&quot;Texas&quot;,abbr:&quot;TX&quot;},
{full:&quot;Utah&quot;,abbr:&quot;UT&quot;},
{full:&quot;Vermont&quot;,abbr:&quot;VT&quot;},
{full:&quot;Virginia&quot;,abbr:&quot;VA&quot;},
{full:&quot;Washington&quot;,abbr:&quot;WA&quot;},
{full:&quot;West Virginia&quot;,abbr:&quot;WV&quot;},
{full:&quot;Wisconsin&quot;,abbr:&quot;WI&quot;},
{full:&quot;Wyoming&quot;,abbr:&quot;WY&quot;}
];

$.fn.states = function(){
    this.autocomplete(state_autocomplete,{
        mustMatch:true,
        formatItem: function(row) {
            return row.full;
        },
        formatResult: function(row) {
            return row.abbr;
        }
    }).result(function(event, data){
        this.value = data.full;
        $(this).next(&quot;:input[type=hidden]&quot;).attr('value', data.abbr);
    });
}
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2008/jquery-u-s-states-autocomplete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Form Validation: theory and practice</title>
		<link>http://www.bitconsultants.net/2008/jquery-form-validation-theory-and-practice/</link>
		<comments>http://www.bitconsultants.net/2008/jquery-form-validation-theory-and-practice/#comments</comments>
		<pubDate>Sun, 27 Jan 2008 21:37:30 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.bitconsultants.net/?p=173</guid>
		<description><![CDATA[jQuery makes it very easy to validate forms. There are a number of useful plugins, the most prominent being validate. If you are wanting something very lightweight<a href="http://www.bitconsultants.net/2008/jquery-form-validation-theory-and-practice/"> Read More...</a>]]></description>
			<content:encoded><![CDATA[<p>jQuery makes it very easy to validate forms. There are a number of useful plugins, the most prominent being <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" target="_blank">validate</a>. If you are wanting something very lightweight or are just interested in how something like this works, read on. The $.each function allows you to iterate over collections in jQuery, it is really one of the most useful utility methods available. We can iterate over all input elements on a page using $.each like this<br />
<script type="text/javascript"><!--
google_ad_client = "pub-4761320180230999";
/* 336x280, created 4/15/10 */
google_ad_slot = "4518447987";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<pre class="brush: jscript; title: Code Example; notranslate">
var input_count = 0;

$(document).ready(function(){
	$.each($('input'), function(index, value){
		input_count++;
	});
	console.log(&quot;Number of inputs:  %i&quot;,  input_count);//use Firebug, not alert() !
});
</pre>
<h3>Iterating Over Text Inputs</h3>
<p>There is a problem with the above code, any input elements (including buttons) are going to be iterated over, so let&#8217;s use a more specific selector to only retrieve input elements of type &#8220;text&#8221;</p>
<pre class="brush: jscript; title: Code Example; notranslate">

...

$.each($('input[type=&quot;text&quot;]'), function(index, value){

...
</pre>
<h3>Required Elements</h3>
<p>Okay, now we can iterate over our text inputs. So, where to go from here? Do we check that each item has a value? What if some items aren&#8217;t required? The easiest way I&#8217;ve found to do this is to use a class on required items (I usually call it &#8220;required&#8221; (creative, huh?)).</p>
<pre class="brush: xml; title: Code Example; notranslate">
...
&lt;form action=&quot;&quot; method=&quot;POST&quot; id=&quot;login_form&quot;&gt;
	&lt;dl&gt;
	  &lt;dt&gt;
		&lt;dd&gt;Username &lt;span class=&quot;req&quot;&gt;*&lt;/span&gt;&lt;/dd&gt;
		&lt;dd&gt;&lt;input type=&quot;text&quot; name=&quot;username&quot; class=&quot;required&quot; maxlength=&quot;7&quot; /&gt;&lt;/dd&gt;
		&lt;dd&gt;Password &lt;span class=&quot;req&quot;&gt;*&lt;/span&gt;&lt;/dd&gt;
		&lt;dd&gt;&lt;input type=&quot;text&quot; name=&quot;password&quot; class=&quot;required&quot; maxlength=&quot;7&quot; /&gt;&lt;/dd&gt;
		&lt;dd&gt;Favorite Color&lt;dd&gt;
		&lt;dd&gt;&lt;input type=&quot;text&quot; name=&quot;username&quot; /&gt;&lt;/dd&gt;
		&lt;dd&gt;Finish&lt;/dd&gt;
		&lt;dd&gt;&lt;input type=&quot;submit&quot; name=&quot;submit&quot; /&gt;&lt;/dd&gt;
	  &lt;/dt&gt;
	&lt;/dl&gt;
&lt;/form&gt;
...
</pre>
<p>Now we can check which fields are required and cancel form submission if they are empty. Getting rid of our input counter variable, here is the new code</p>
<pre class="brush: jscript; title: Code Example; notranslate">
$(document).ready(function(){
	$('#login_form').submit(function(){//add an onsubmit event handler to our form
		var blank_fields = false;//initialize a generic error detector
		$.each($('input[type=&quot;text&quot;]'), function(index, value){
			var t = $(this);//limit the number of new jQuery objects created
			if(t.hasClass('required')){//we know it is required
				if(t.val() == &quot;&quot; || t.val() === undefined){
					console.error('%s can not be blank', t.attr('name'));
					blank_fields = true;
				}
			}
		});
		return !blank_fields;//if there are no blank fields, submit
	});
});
</pre>
<p>That is a mouthful, but it is actually quite simple. When our form is submitted, we iterate over each input item to see if it is required. If it&#8217;s required, check to see if it is empty, if it is empty, return false (cancelling form submission).</p>
<p>Now, there are a couple errors with the code above. For one, it is checking all form inputs (not just the one in our form), so if we had multiple forms on the page, both with required elements, this would fail. Also, being able to check more specific criteria would be nice. We will limit our iteration to input items that are of type text and are descendants of the target form. Let&#8217;s also add a maxlength attribute to a form field to ensure that it is within the set character length:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
$(document).ready(function(){
	$('#login_form').submit(function(){
		var blank_fields = false;
		var length_error = false;//check for length errors
		$.each($('#login_form input[type=&quot;text&quot;]'), function(index, value){//limit input elements to those within the form
			var t = $(this);
			if(t.hasClass('required')){
				if(t.val() == &quot;&quot; || t.val() === undefined){//check if it's empty
					console.error('%s can not be blank', t.attr('name'));
					blank_fields = true;
				}
				if(t.attr('maxlength') !== undefined){//if maxlength attribute is present in the current element
					if(t.val().length &gt; t.attr('maxlength')){//check string length against given maxlength
						console.error('%s is too long: %i chars', t.attr('name'), t.val().length);
						length_error = true;
					}
				}
			}
		});
		return !(blank_fields || length_error);//if there are no blank fields and no length errors, submit
	});
});
</pre>
<p>Okay, now we are getting somewhere. This could be used as is, but it doesn&#8217;t provide very friendly error messages (they have to have Firebug installed to know what the errors are). Let&#8217;s wrap up our code so far into a jQuery function and provide some more useful errors. I&#8217;ve commented changes to the code, but it is mostly the same.</p>
<pre class="brush: jscript; title: Code Example; notranslate">
$.fn.validate = function(options){
	/*
	* Define the default error message tag and styling, allow this to be overridden
	*/
	var defaults = {
		 formTag: 'div',
		 color: '#8A1F11',
		 border: '2px solid #FBC2C4',
		 errorBG: '#FBE3E4 0 0',
		 marginBottom:'1em',
		 padding:'0.8em',
		 width: $(this).width()
	 };
	var o = $.extend(defaults, options);

	/*
	* Private method creates error element
	*/
	function genError(msg){
		var err = $(document.createElement(o.formTag));//create an error element
		err.css('border', 		 o.border)
		   .css('background', 	 o.errorBG)
		   .css('margin-bottom', o.marginBottom)
		   .css('padding', 		 o.padding)
		   .css('color', 		 o.color)
		   .css('width', 		 o.width);//Apply css style rules to the error
		err.html(msg);//insert the error message into the element
		return err;
	}

	/*
	* Our slightly modified form validation
	*/
	$(this).submit(function(){//now uses $(this) reference as the method is applied to the form selector
		var blank_fields = false;//initialize a generic error detector
		var length_error = false;
		//now we use $(this).find('input[type=&quot;text&quot;]') to locate our forms child elements
		$.each($(this).find('input[type=&quot;text&quot;]'), function(index, value){
			var t = $(this);
			if(t.hasClass('required')){
				if(t.val() == &quot;&quot; || t.val() === undefined){
					//instead of logging error, create a new element and append it to the input elements parent
					errormsg = genError(t.attr('name') + ' can not be blank')
					t.parent().append(errormsg);
					blank_fields = true;
				}
				if(t.attr('maxlength') !== undefined){
					if(t.val().length &gt; t.attr('maxlength')){
						//same as above but more concise
						t.parent().append(genError(t.attr('name') + ' is too long'));
						length_error = true;
					}
				}
			}
		});
		return !(blank_fields || length_error);
	});
}
</pre>
<p>Usage:</p>
<pre class="brush: jscript; title: Code Example; notranslate">
$(document).ready(function(){
	$('#login_form').validate({color:'#000'});
});
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.bitconsultants.net/2008/jquery-form-validation-theory-and-practice/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using xcache
Page Caching using xcache
Object Caching 828/951 objects using memcached

Served from: www.bitconsultants.net @ 2012-02-05 16:16:32 -->
