<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title> blog</title>
		<link>http://www.mitchviner.com/blog/</link>
		<atom:link href="http://www.mitchviner.com/blog/" rel="self" type="application/rss+xml" />
		<description></description>

		
		<item>
			<title>A couple days with backbone</title>
			<link>http://www.mitchviner.com/blog/a-couple-days-with-backbone/</link>
			<description>&lt;p&gt;At the beginning of the week I started looking into the various Javascript frameworks that are designed to help provide more structure to your javascript applications. Namely Javascript MVC, Backbone, and SproutCore. After reading through the docs, looking at the examples, and just alot of general reading on each framework, I ultimately decided to go forward using Backbone.js - Why is a topic for another post...&lt;/p&gt;
&lt;p&gt;I've been using it for a couple days now and really just wanted to post the articles that I've found to be the most helpful.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://weblog.bocoup.com/organizing-your-backbone-js-application-with-modules/&quot; target=&quot;_blank&quot;&gt;Beaucoup's: Organizing Your Backbonejs Application with Modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://liquidmedia.ca/blog/2011/01/backbone-js-part-1/&quot; target=&quot;_blank&quot;&gt;Liquid Media's Intro to Backbone Series&lt;/a&gt; 
&lt;ul&gt;&lt;li&gt;Note that as of the current version of Backbone, Controllers have been replaced with Routers, so the concept of Controllers in this series applies to Routers&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://backbonetutorials.com/&quot; target=&quot;_blank&quot;&gt;Backbone Tutorials @ Backbonetutorials.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; target=&quot;_blank&quot;&gt;The Backbone documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The articles above are great for getting you to start thinking about your application in the &quot;backbone way&quot;. In my experience, just grasping how the different components work together and the proper ways to hook them together was the most challenging aspect of using Backbone. Once I figured that out though, I was able to start building out some of the parts of my application very quickly.&lt;/p&gt;</description>
			<pubDate>Fri, 03 Feb 2012 09:20:03 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/a-couple-days-with-backbone/</guid>
		</item>
		
		<item>
			<title>Removing Entities in Doctrine2</title>
			<link>http://www.mitchviner.com/blog/removing-entities-in-doctrine2/</link>
			<description>&lt;p&gt;Removing entities in doctrine2 is concpetually and easy process. I'm referring to removing the actual model class and the physical php file. I just had to remove a few of them from my application. I thought, easy, I'll delete the file, drop the table, remove any references in my other entities and clear the cache and I should be good to go So needless to say, I was surprised to get an error saying that the ClassMetadataFacrtory.php file could not find one of my entities on line 223.&lt;/p&gt;
&lt;p&gt;Well, I beat my head against the wall on this for hours, I walked through the code using the stack trace and in my debugging I found a couple references to my existing classes in other entities. Long story short, I forgot I had extended the User entity to own one of the entities I was removing. This was causing everything! I updated the User entity to remove the reference to the now deleted Entity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Moral of the story:&lt;/strong&gt; Make sure you have double checked all entities to ensure the one(s) you are removing are not referenced anywhere within the model layer.&lt;/p&gt;</description>
			<pubDate>Thu, 12 Jan 2012 18:30:09 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/removing-entities-in-doctrine2/</guid>
		</item>
		
		<item>
			<title>Code Sample: HTML / CSS</title>
			<link>http://www.mitchviner.com/blog/code-sample-html-css/</link>
			<description>&lt;p&gt;For an HTML / CSS code sample, just view the source of this website. It uses the HTML5 doctype, modernizr.js for older browser support, and is powered by SilverStripe. I authored all the css, using Paul Irish's HTML5 Boilerplate as a starting point to get the compatibility with older browsers. The mobile version of the site is done just by using CSS Media Queries and including a seperate stylesheet for mobile.&lt;/p&gt;
&lt;p&gt;Code: Right Click -&amp;gt; View Source&lt;/p&gt;</description>
			<pubDate>Thu, 05 Jan 2012 11:24:12 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/code-sample-html-css/</guid>
		</item>
		
		<item>
			<title>Updates - Jan 3 2012</title>
			<link>http://www.mitchviner.com/blog/updates-jan-3-2012/</link>
			<description>&lt;p&gt;Just wanted to talk real quickly about some updates I made to my site today. Nothing too major, just putting some of the finishing touches on the site construction itself before turning my focus towards building the actual content.&lt;/p&gt;
&lt;p&gt;I've added a mobile version, just using media queries and without a 'Switch to Full Site' capability... yet. If you're not familiar with media queries, it's basically just querying the browser to find information about the host machine. Typically, for a mobile version, the query looks similar to:&lt;/p&gt;
&lt;pre class=&quot;brush: plain;light: true; fontsize: 100; first-line: 1; &quot;&gt;&amp;lt;link rel=&quot;stylesheet&quot; media=&quot;screen and (max-device-width: 480px)&quot; href=&quot;mobile.css&quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;That's about as basic as you can get in doing a mobile version.&lt;/p&gt;
&lt;p&gt;I've also added a site search to every page. This is using the built in search module that ships with SilverStripe 2.4.1. It's not too useful yet, as the information on the site is pretty easy to find ( since there is not much info ).&lt;/p&gt;
&lt;p&gt;That is all, not much to report but it's something.&lt;/p&gt;</description>
			<pubDate>Tue, 03 Jan 2012 15:25:22 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/updates-jan-3-2012/</guid>
		</item>
		
		<item>
			<title>Just launched...</title>
			<link>http://www.mitchviner.com/blog/just-launched/</link>
			<description>&lt;p&gt;I've just put this website live! I'm pretty excited about it!&lt;/p&gt;
&lt;p&gt;I have spent the past couple months, off and on, here and there, working on this. Mainly just getting everything setup, writing some initial blog posts (which is why this isn't the &lt;a href=&quot;http://www.mitchviner.com/blog/first-post/&quot;&gt;First Post&lt;/a&gt;). But alas, here you will find some random &quot;ramblings&quot; of mine, as well as some work I've done.&lt;/p&gt;
&lt;p&gt;As of right now, the &lt;a href=&quot;http://www.mitchviner.com/portfolio/&quot;&gt;Portfolio &lt;/a&gt;section is pretty small, only 3 projects. Basically these are probably the 3 biggest projects I've worked on, one is what I'm still doing for 40 hours a week. I'll be adding some of the hundreds of other smaller sites / projects I've done in the portfolio as time goes.&lt;/p&gt;
&lt;p&gt;I plan to blog as often as I can, but at the same time, I don't want to waste my time. If I don't have anything good to blog about, I probably won't blog. My goal is to build a &quot;diary&quot; of my experiences and hopefully it can serve as a reference to someone else who is having the same experience.&lt;/p&gt;
&lt;p&gt;Next thing I'm working on, is a mobile version... hopefully I'll have that done within the next few days.&lt;/p&gt;</description>
			<pubDate>Thu, 29 Dec 2011 15:44:34 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/just-launched/</guid>
		</item>
		
		<item>
			<title>Code Sample: Magento</title>
			<link>http://www.mitchviner.com/blog/code-sample-magento/</link>
			<description>&lt;p&gt;This is a partial Magento controller that was used to override the default Product Controller in order to split the usual product page into a 3 step product configuration wizard. The full file is not posted here just because of it's size, some of the methods removed were just methods that overrode, and slightly modified existing methods. This controller was created for Magento 1.3.4 about a year ago.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&quot;brush: php;fontsize: 100; first-line: 1; &quot;&gt;&amp;lt;?php 
require_once 'Mage/Catalog/controllers/ProductController.php';
class Establish_Catalog_ProductController extends Mage_Catalog_ProductController
{
	private $_price = 0;
	private $_cfg;
	private $_prod;
	
	public function steptwoAction() {
		if (!$this-&amp;gt;_initProduct()) {
            if (isset($_GET['store']) &amp;amp;&amp;amp; !$this-&amp;gt;getResponse()-&amp;gt;isRedirect()) {
                $this-&amp;gt;_redirect('');
            } elseif (!$this-&amp;gt;getResponse()-&amp;gt;isRedirect()) {
                $this-&amp;gt;_forward('noRoute');
            }
            return;
        }
        $this-&amp;gt;loadLayout();
        $this-&amp;gt;renderLayout();
	}
	
	public function reviewAction() {
		if (!$this-&amp;gt;_initProduct() ) {
			if (isset($_GET['store']) &amp;amp;&amp;amp; !$this-&amp;gt;getResponse()-&amp;gt;isRedirect()) {
				$this-&amp;gt;_redirect('');
			} elseif (!$this-&amp;gt;getResponse()-&amp;gt;isRedirect()) {
				$this-&amp;gt;_forward('noRoute');
			}
			return;
		}
		
		$this-&amp;gt;loadLayout();
        $this-&amp;gt;renderLayout();
	}
	
	private function _addToPrice($amt) {
		$this-&amp;gt;_price = $this-&amp;gt;_price + $amt;
	}
	
	private function _addFullColor() {
		if($fcTiers = $this-&amp;gt;getFullColorPriceTiers()) {
			return $this-&amp;gt;_getCustomTierPrice($fcTiers);
		} else {
			return array(0, &quot;c&quot;);
		}
	}
	
	private function _addBackside($color = false, $readOnly = false) {
		if($color) {
			$btiers = $this-&amp;gt;getBacksideColorPriceTiers();
		} else {
			$btiers = $this-&amp;gt;getBacksidePriceTiers();
		}
		if($btiers) {
			$tierPrice = $this-&amp;gt;_getCustomTierPrice($btiers, $readOnly);
			$backSetup = array($this-&amp;gt;_prod-&amp;gt;getBacksideSetupCharge(), $this-&amp;gt;_prod-&amp;gt;getAttributeText('backside_setup_charge_dc')); 
			return array_merge($tierPrice, $backSetup);
		} else {
			return array(0, &quot;c&quot;, 0, &quot;c&quot;);
		}
	}
	
	private function _getCustomTierPrice($tiers, $readOnly = false) {
		$qty = $this-&amp;gt;_cfg['qty'];
		$price = 0;
		$dCode = &quot;c&quot;;
		foreach($tiers as $t) {
			if($qty &amp;gt;= $t['qty']) {
				$price = $t['price'];
				$dCode = $t['discountCode'];
			}
		}
		if(!$readOnly) {
			$this-&amp;gt;_addToPrice($price);
		}
		return array($price,$dCode);
	}
	
	private function _addFullColorOnColor() {
		if($fcTiers = $this-&amp;gt;getFullColorOnColorPriceTiers()) {
			return $this-&amp;gt;_getCustomTierPrice($fcTiers);
		} else {
			return array(0, &quot;c&quot;);
		}
	}
	
	private function _validateProductConfiguration() {
		$cfg = array(
			&quot;status&quot; =&amp;gt; 200,
			&quot;msg&quot; =&amp;gt; array(),
			&quot;id&quot; =&amp;gt; intval($this-&amp;gt;getRequest()-&amp;gt;getParam('id')),
			&quot;background&quot; =&amp;gt; $this-&amp;gt;getRequest()-&amp;gt;getParam('background') || FALSE,
			&quot;fullColorCapable&quot; =&amp;gt; (bool)$this-&amp;gt;getRequest()-&amp;gt;getParam('fullColorCapable'),
			&quot;imprintType&quot; =&amp;gt; $this-&amp;gt;getRequest()-&amp;gt;getParam('imprintType'),
			&quot;inkColor&quot; =&amp;gt; $this-&amp;gt;getRequest()-&amp;gt;getParam('inkColor'),
			&quot;productColor&quot; =&amp;gt; $this-&amp;gt;getRequest()-&amp;gt;getParam('productColor'),
			&quot;qty&quot; =&amp;gt; intval($this-&amp;gt;getRequest()-&amp;gt;getParam('qty')),
			&quot;backside&quot; =&amp;gt; (bool)$this-&amp;gt;getRequest()-&amp;gt;getParam('backside')
		);
		/* Validate Ink Color */
		if(!is_array($cfg['inkColor'])) {
			$cfg['status'] = 500;
			$cfg['msg'][] = 'Invalid ink color supplied.';
		} else {
			if($cfg['inkColor'][0]==&quot;&quot; || $cfg['inkColor'][1]==&quot;&quot;) {
				$cfg['status'] = 500;
				$cfg['msg'][] = 'Ink color was not supplied.';
			}
		}
		
		/* Validate Product Color */
		if(!is_array($cfg['productColor'])) {
			$cfg['status'] = 500;
			$cfg['msg'][] = 'Invalid product color supplied.';
		} else {
			if($cfg['productColor'][0]==&quot;&quot; || $cfg['productColor'][1]==&quot;&quot;) {
				$cfg['status'] = 500;
				$cfg['msg'][] = 'Product color was not supplied.';
			}
		}
		return $cfg;
	}
	
	private function getFullColorPriceTiers()
	{
		$prod = $this-&amp;gt;_prod;
		$tiers = $prod-&amp;gt;getFullColorPrice();
		if($tiers) {
			$obj = Zend_Json::decode($tiers);
			return $obj['data'];
		} else {
			return false;
		}
	}
	
	private function getFullColorOnColorPriceTiers()
	{
		$prod = $this-&amp;gt;_prod;
		$tiers = $prod-&amp;gt;getFullColorOnColorPrice();
		if($tiers) {
			$obj = Zend_Json::decode($tiers);
			return $obj['data'];
		} else {
			return false;
		}
	}
	
	private function getBacksidePriceTiers()
	{
		$prod = $this-&amp;gt;_prod;
		$tiers = $prod-&amp;gt;getBackSidePrice();
		if($tiers) {
			$obj = Zend_Json::decode($tiers);
			return $obj['data'];
		} else {
			return false;
		}
	}
	
	private function getBacksideColorPriceTiers()
	{
		$prod = $this-&amp;gt;_prod;
		$tiers = $prod-&amp;gt;getBacksideFcPrice();
		if($tiers) {
			$obj = Zend_Json::decode($tiers);
			return $obj['data'];
		} else {
			return false;
		}
	}
	
	
}
/* -- End of file -- */&lt;/pre&gt;</description>
			<pubDate>Thu, 22 Dec 2011 11:14:09 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/code-sample-magento/</guid>
		</item>
		
		<item>
			<title>Code Sample: Symfony2</title>
			<link>http://www.mitchviner.com/blog/code-sample-symfony2/</link>
			<description>&lt;p&gt;Below is a work-in-progress base controller for a Symfony application that is still in it's infancy. It's nothing too fancy, but demonstrates knowledge of PHP5.3 OOP development.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&quot;brush: php;fontsize: 100; first-line: 1; &quot;&gt;&amp;lt;?php

/**
 * MageRoller BaseController
 * @updated 12/15/2011
 * @created Mitch Viner
 */

namespace MageRoller\EditorBundle\Controller;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller as Controller;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Validator\Constraints as Assert;

class BaseController extends Controller
{

	protected $_viewData; // local storage for the view data
	protected static $themeId; // store theme id once pulled from session once
	
	public function __construct() {
		$this-&amp;gt;_viewData = array();
	}
	
	/**
	 * Store data to be sent to the view on render
	 *
	 * @param string $key
	 * @param mixed $mixed
	 * @return null
	 */
	protected function sendToView($key, $mixed)
	{
		$this-&amp;gt;_viewData[$key] = $mixed;
	}
	
	/**
	 * Retrieve data currently ready to be sent as response
	 *
	 * @return array
	 */
	protected function getViewData()
	{
		return $this-&amp;gt;_viewData;
	}

	/**
	 * Create JSON response from data designated to be sent to view
	 *
	 * @return Response
	 */
	protected function renderJson()
	{
    	return new Response(json_encode($this-&amp;gt;getViewData()), 200, array('Content-Type' =&amp;gt; 'application/json'));
	}

	/**
	 * Get the currently logged in user
	 *
	 * @return UserInterface
	 */
	protected function getUser()
	{
		$user = $this-&amp;gt;container-&amp;gt;get('security.context')-&amp;gt;getToken()-&amp;gt;getUser();
		
        if (!is_object($user) || !$user instanceof UserInterface) {
            throw new AccessDeniedException('This user does not have access to this section.');
        }
        return $user;
	}

	/**
	 * Set theme id being edited
	 *
	 * @param int $id
	 * @return null
	 */
	protected function setEditing($id)
	{
		$sess = $this-&amp;gt;container-&amp;gt;get('session');
		$sess-&amp;gt;set('editing', $id);

		self::$themeId = $id;
		
	}

	/**
	 * Retrieve the theme id being edited from the session
	 *
	 * @return int
	 */
	protected function getEditing()
	{
		if(!self::$themeId) {
			$editing = $this-&amp;gt;container-&amp;gt;get('session')-&amp;gt;get('editing');
			self::$themeId = $editing;
			return $editing;
		} 
		return self::$themeId;
	}

	/**
	 * Method to validate some data against a given constraint
	 *
	 * @param string $constraint
	 * @param mixed $value
	 * @return bool | string
	 */
	public function dataIsValid($constraint, $value)
	{
		if(is_string($constraint)) {
			$constraint = $this-&amp;gt;getConstraint($constraint);
		}
		$errors = $this-&amp;gt;container-&amp;gt;get('validator')-&amp;gt;validateValue($value, $constraint);

		if(count($errors) == 0) {
			return true;
		} else {
			return $errors[0]-&amp;gt;getMessage();
		}
	}

	/**
	 * Utility method to get constraint to use to validate input recieved via JSON
	 *
	 * @TODO: Add the rest of the constraints
	 * @return Assert
	 * @param string $const
	 */
	protected function getConstraint($const)
	{
		switch($const)
		{
			case &quot;notBlank&quot;:
				return new Assert\NotBlank();				
				break;
			default:
				throw new FormException('Constraint supplied was invalid.');
				break;

		}
	}

}
&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
			<pubDate>Mon, 19 Dec 2011 13:00:00 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/code-sample-symfony2/</guid>
		</item>
		
		<item>
			<title>Code Sample: jQuery</title>
			<link>http://www.mitchviner.com/blog/code-sample-jquery/</link>
			<description>&lt;p&gt;Below is a jQuery &quot;storage&quot; mechanism I developed to extend an application with the ability to store data on an IFrame. The purpose of using the IFrame, is that other parts of the application can load templates for use by the jQuery jsRender plugin to render views inside of the application. This simple extension allows for easy access to reading and writing those templates within the IFrame as well as seamlessly manages storing data objects on the IFrame as well. This provides a unified way to access the jsRender templates, as well as JSON data.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&quot;brush: jscript;fontsize: 100; first-line: 1; &quot;&gt;/*
 * Unified storage api for templates and json
 */
(function($, MRL) {

 	var storage = null;
 	
 	$.extend(MRL, { Storage : {
		
		get: function(name) {
			return (storage.data(name)) ? storage.data(name) : storage.find('#'+name).html();
		},
        // convenience method for compatibility with existing methods
		set: function(name, data) {
			return this.put(name,data);	
		},
		put: function(name, data) {
			if( $.isPlainObject(data) ) { // Store as data on the iframe
				if(name=='toc') { $.publish('fatalError', ['Cannot set data object to key of \'toc\' as it is a protected key']); return false; }
				storage.data(name, data);
                                // Keep a index of all data keys stored for easy 'getAll'
				var toc = storage.data('toc');
				if( $.inArray(name, toc) === -1 ) {
					toc.push(name);
					storage.data('toc', toc);
				}
				
			} else { // Storing a template string
			        //Create Script element:
				var sc = document.createElement('script');
				sc.type = 'text/x-jquery-tmpl';
				sc.id = name;
				sc.name = name;
				storage.append(sc);
				setTimeout(function() {
					sc.innerHTML = data;
				}, 1);
			}			
		},
		hasData: function() {
			return (storage.data('toc').length) ? true : false;
		},
		allData: function() {
			var d = [];
			var toc = storage.data('toc');
			$.each(toc, function(k, v) {
				d.push({ name: v, value: storage.data(v) });
			});
			return d;
		},
		remove: function(name) 
		{
			if(name=='toc') { return false; }
			if( storage.data(name) ) {
				storage.removeData(name);
				var toc = storage.data('toc');
				toc = $.grep(toc, function(v, i) {
					return v != name;
				});
				storage.data('toc', toc);
			} else {
				var ele = storage.find('#'+name);
				if(ele.length) { ele.remove(); }
			}
		}

	}});

        /* Add the iFrame to the dom, then set the local storage variable to the body tag */
	$('document').ready(function() {
		$('body').append($('&amp;lt;iframe /&amp;gt;').attr('id', 'mrl-storage').attr('name', 'mrl-storage').css({&quot;width&quot; : &quot;1&quot;, &quot;height&quot;: &quot;1&quot;, &quot;border&quot; : &quot;none&quot; }));
		setTimeout( function() {
			storage = $('#mrl-storage').contents().find('body');
			storage.data('toc', []);
		}, 1); 
	});

 })(jQuery, MageRoller);&lt;/pre&gt;</description>
			<pubDate>Fri, 16 Dec 2011 10:32:07 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/code-sample-jquery/</guid>
		</item>
		
		<item>
			<title>jQuery interface for testing Zend_Json_Server</title>
			<link>http://www.mitchviner.com/blog/jquery-interface-for-testing-zend-json-server/</link>
			<description>&lt;p&gt;I'm currently working on building an API with Zend Framework and JSON-RPC. As I was creating this API I wanted an interface that I could use to test the implementation, but without having to do a lot of work or install any software. After some quick Google searches I stumbled upon the &lt;a class=&quot;aga aga_0&quot; href=&quot;http://plugins.jquery.com/project/zendjsonrpc&quot;&gt;jQuery.Zend.jsonrpc&lt;/a&gt; plugin and quickly got it working. This plugin is great, setup for it was a breeze and I was able to make API requests in no time. But what I didn’t like, was that I had to modify some javascript code everytime I needed to test a new API method.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I needed to spend time working on the API, not writing javascript to test it.&lt;/em&gt;&lt;br/&gt;&lt;br/&gt; So I threw together the HTML / Javascript below, which is made specifically to work with Zend_Json_Server and the jQuery.Zend.jsonrpc plugin. This script will parse the SMD returned from Zend_Json_Server and will create a list of methods. You can then select a method and the script will generate a form with fields that correspond to the parameters the SMD has indicated the method requires. After filling out and submitting the form, it will output the JSON response in the result area. The script will support namespaced API's as well.&lt;/p&gt;
&lt;p&gt;In order to get this to work, it will require you to make one small modification to the jQuery.Zend.jsonrpc plugin to put the raw SMD into the global scope so that the script below can access it.&lt;/p&gt;
&lt;p&gt;To make the raw SMD data accessible, modify the jQuery.ajax success function inside of jQuery.Zend.jsonrpc, around line 83:&lt;/p&gt;
&lt;pre class=&quot;brush: php; title: ;&quot;&gt;success: function(data){
            	//Store a copy of the original response to global scope
            	window.apiMethods = data.methods; // this is the new line
                /* Set version if we don't have it yet. */
                if(!self.options.version){
                    if(data.envelope == &quot;JSON-RPC-1.0&quot;){&lt;/pre&gt;
&lt;p&gt;You’ll need the following script (jsonFormatter.js) that I found online to have your JSON output in a readable format:&lt;/p&gt;
&lt;pre class=&quot;brush: jscript; title: ;&quot;&gt;/**
 * Utility function to transform json object into a formatted string.
 *
 *
 * @TODO: Find where I found this and give credit to the creator
 */

function FormatJSON(oData, sIndent) {
    if (arguments.length &amp;lt; 2) {
        var sIndent = &quot;&quot;;
    }
    var sIndentStyle = &quot;    &quot;;
    var sDataType = RealTypeOf(oData);

    // open object
    if (sDataType == &quot;array&quot;) {
        if (oData.length == 0) {
            return &quot;[]&quot;;
        }
        var sHTML = &quot;[&quot;;
    } else {
        var iCount = 0;
        $.each(oData, function() {
            iCount++;
            return;
        });
        if (iCount == 0) { // object is empty
            return &quot;{}&quot;;
        }
        var sHTML = &quot;{&quot;;
    }

    // loop through items
    var iCount = 0;
    $.each(oData, function(sKey, vValue) {
        if (iCount &amp;gt; 0) {
            sHTML += &quot;,&quot;;
        }
        if (sDataType == &quot;array&quot;) {
            sHTML += (&quot;\n&quot; + sIndent + sIndentStyle);
        } else {
            sHTML += (&quot;\n&quot; + sIndent + sIndentStyle + &quot;\&quot;&quot; + sKey + &quot;\&quot;&quot; + &quot;: &quot;);
        }

        // display relevant data type
        switch (RealTypeOf(vValue)) {
            case &quot;array&quot;:
            case &quot;object&quot;:
                sHTML += FormatJSON(vValue, (sIndent + sIndentStyle));
                break;
            case &quot;boolean&quot;:
            case &quot;number&quot;:
                sHTML += vValue.toString();
                break;
            case &quot;null&quot;:
                sHTML += &quot;null&quot;;
                break;
            case &quot;string&quot;:
                sHTML += (&quot;\&quot;&quot; + vValue + &quot;\&quot;&quot;);
                break;
            default:
                sHTML += (&quot;TYPEOF: &quot; + typeof(vValue));
        }

        // loop
        iCount++;
    });

    // close object
    if (sDataType == &quot;array&quot;) {
        sHTML += (&quot;\n&quot; + sIndent + &quot;]&quot;);
    } else {
        sHTML += (&quot;\n&quot; + sIndent + &quot;}&quot;);
    }

    // return
    return sHTML;
}

function RealTypeOf(v) {
	if (typeof(v) == &quot;object&quot;) {
		if (v === null) return &quot;null&quot;;
		if (v.constructor == (new Array).constructor) return &quot;array&quot;;
		if (v.constructor == (new Date).constructor) return &quot;date&quot;;
		if (v.constructor == (new RegExp).constructor) return &quot;regex&quot;;
		return &quot;object&quot;;
	}
	return typeof(v);
}&lt;/pre&gt;
&lt;p&gt;After that, create a page with the code below in the same directory with your API endpoint.&lt;/p&gt;
&lt;pre class=&quot;brush: php; title: ;&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&amp;gt;
    &amp;lt;title&amp;gt;JSON RPC Test Page&amp;lt;/title&amp;gt;
    &amp;lt;script type=&quot;text/javascript&quot; src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/json2.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/jquery.zend.jsonrpc.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/jsonFormatter.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type=&quot;text/javascript&quot;&amp;gt;

    function ucFirst(str) {
    	str += '';
        var f = str.charAt(0).toUpperCase();
        return f + str.substr(1);
    }

    (function($) {
	    $(function(){						

	    	var myApi = jQuery.Zend.jsonrpc({ url: '/api/v1/jsonrpc' });

	    	var apiList = $('&amp;lt;ul /&amp;gt;').attr('id', 'apiList').appendTo($('.leftColumn'));

	    	// Add the available methods to the list.
			var method = null;

			var methodNames = [];
			$.each(apiMethods, function(k, v) {
				if( k != 'undefined' ) {
					methodNames.push(k);
				}
			});

			var form = $('#requestParams');

	    	$(methodNames).each(function(i, v) {

	        	method = apiMethods[this];

	        	methodName = this;

	        	if(methodName.indexOf('.')&amp;gt;0) { // If has namespaced api, get rid of the namespace
	        		methodName = (methodName.split('.'))[1];
	        	}

				var readable = ucFirst(methodName.replace(/([A-Z])/g, &quot; $1&quot;));

	    		apiList.append($('&amp;lt;li /&amp;gt;').html($('&amp;lt;a /&amp;gt;').attr('rel', this).attr('href', '#').addClass('apiMethod').html(readable).bind('click', handleMethodSelect)));

	    	});

	    	filterList();

	    	function handleMethodSelect() {
				disableForm();
				var clicked = $(this).attr('rel');
				$('.formTitle').html($(this).html());
				var m = apiMethods[clicked];
				var input;
				var label;
				var p;
				$.each(m.parameters, function() {
					p = this;
					var lbl = '';
					if(p.optional!=true) {
						lbl = &quot;&amp;lt;span class='required'&amp;gt;*&amp;lt;/span&amp;gt;&quot;;
					}
					lbl += p.name;
					label = $('&amp;lt;label /&amp;gt;').html(lbl).appendTo(form);
					input = $('&amp;lt;input /&amp;gt;').attr('type', 'text').attr('name', 'param[]').addClass('param').appendTo(form);
					if(p.optional!=true) {
						input.addClass('required');
					}
				});
				$('&amp;lt;input /&amp;gt;').attr('type', 'hidden').attr('name', 'method').attr('value', clicked).appendTo(form);
				var submit = $('&amp;lt;input /&amp;gt;').attr('type', 'submit').attr('value', 'Submit Request').addClass('submitBtn').appendTo(form);
				enableForm();
	    	}

			function enableForm() {

				form.bind('submit', function(e) {
					e.preventDefault();
					e.stopPropagation();
					var method = $('input[name=method]').val();
					var paramString = $('input.param').map(function() {
						if($(this).val() !== &quot;&quot;) {
							return $(this).val();
						}
					});

					var apiResults = '';
					if(method.indexOf('.')&amp;gt;0) { // If has namespaced api
						method = method.split('.');
						var ns = method[0];
						var func = method[1];

						apiResults = myApi[ns][func].apply(null, paramString);
					} else {
						apiResults = myApi[method].apply( null, paramString);
					}
					$('#jsonResults').html( '&amp;lt;pre&amp;gt;'+FormatJSON( apiResults )+'&amp;lt;/pre&amp;gt;' );
					matchHeights();
				});
				form.fadeIn(500, matchHeights);

			}
			function disableForm() {
				form.hide();
				form.unbind('submit');
				form.empty();
			}

			function matchHeights() {
	    		($('.leftColumn').height() &amp;gt; $('.stage').height()) ? $('.stage').height($('.leftColumn').height()) : $('.leftColumn').height($('.stage').height());
			}
			matchHeights();

			// custom css expression for a case-insensitive contains()
	    	jQuery.expr[':'].Contains = function(a,i,m){
	    		return (a.textContent || a.innerText || &quot;&quot;).toUpperCase().indexOf(m[3].toUpperCase())&amp;gt;=0;
	    	};

	    	function filterList() {
		    	$('#filterMethods').keyup( function () {
			    	var val = $(this).val();

			    	$('#apiList a:not(:Contains(&quot;' + val + '&quot;))').parent().slideUp();
			    	$('#apiList a:Contains(&quot;' + val + '&quot;)').parent().slideDown();
		    	});
	    	} 

	    });

    })(jQuery);

    &amp;lt;/script&amp;gt;
    &amp;lt;style type=&quot;text/css&quot;&amp;gt;
		body, p, ul { margin: 0; padding: 0; font-family: &quot;Trebuchet MS&quot;, Arial, Helvetica; font-size: 12px; }
    	.leftColumn { width: 20%; border-right: #CCC solid 3px; float: left; background: #EEE; min-height: 200px; border-bottom: 3px solid #CCC; }
		.leftColumn form { padding: 4px; border-bottom: 2px solid #CCC; }
		.leftColumn ul { list-style: none; }
		.leftColumn ul li { border-bottom: 1px solid #CCC; display: block; }
		.leftColumn ul li a { padding: 4px; color: #FFBF00; text-decoration: none; display: block; }
		.leftColumn ul li a:hover { background: #666; }
		.stage { float: left; display: block; width: 79%; border-bottom: 3px solid #CCC; background: #FFDC73; }
		.formTitle { background: #EEE; border-bottom: 2px solid #CCC; font-size: 16px; color: #666; padding: 5px 8px; }
		.formStage { padding: 15px; border-bottom: 3px solid #CCC; min-height: 167px; background: #FFF; }
		.formStage label { padding: 3px 0; display: block; }
		.formStage input { display: block; }
		.formStage .submitBtn { clear: both; margin: 8px; }
		.resultsWrapper { padding: 15px; color: #666; background: #FFDC73; min-height: 90px; }
		.resultsWrapper p { font-size: 18px; color: #999; }
		#jsonResults { padding: 30px; font-size: 12px; }
		span.required { color: #990000; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;div class=&quot;leftColumn&quot;&amp;gt;
		&amp;lt;form&amp;gt;&amp;lt;label&amp;gt;Filter List: &amp;lt;/label&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;filterMethods&quot; id=&quot;filterMethods&quot; size=&quot;28&quot; /&amp;gt;&amp;lt;/form&amp;gt;

	&amp;lt;/div&amp;gt;
	&amp;lt;div class=&quot;stage&quot;&amp;gt;
		&amp;lt;div class=&quot;formTitle&quot;&amp;gt;
		Select an api method from the left.
		&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;formStage&quot;&amp;gt;
			&amp;lt;form name=&quot;requestParams&quot; id=&quot;requestParams&quot;&amp;gt;

			&amp;lt;/form&amp;gt;
		&amp;lt;/div&amp;gt;
		&amp;lt;div class=&quot;resultsWrapper&quot;&amp;gt;
			&amp;lt;p&amp;gt;Result:&amp;lt;/p&amp;gt;
			&amp;lt;div id=&quot;jsonResults&quot;&amp;gt;

			&amp;lt;/div&amp;gt;
		&amp;lt;/div&amp;gt;
	&amp;lt;/div&amp;gt;

&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/pre&gt;
&lt;p&gt;Hopefully you’ll have a working interface with which to test your API! If not, let me know in the comments and I’ll help you out.&lt;/p&gt;</description>
			<pubDate>Thu, 15 Dec 2011 12:31:00 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/jquery-interface-for-testing-zend-json-server/</guid>
		</item>
		
		<item>
			<title>Add SyntaxHighlighter to SilverStripe</title>
			<link>http://www.mitchviner.com/blog/add-syntaxhighlighter-to-silverstripe/</link>
			<description>&lt;p&gt;Today I took some time to go back through previous posts and do a little clean-up. I also needed to add SyntaxHighlighter to make my code snippets that I have, and the many more to come easier to read. I've used SyntaxHighlighter via a plugin in WordPress before and really liked the way it works. However, with WordPress you just install the plug-in and it works. Which is great, if you're using WordPress. However, I'm using SilverStripe and as you likely know, if you're reading this, installing plug-ins for SilverStripe is completely different than WordPress as you typically need to have some knowledge of what it is you're doing. So here's what I did to get SyntaxHighlighter installed and working for this SilverStripe installation:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Download SyntaxHighlighter TinyMCE Plug-in - &lt;a href=&quot;http://github.com/RichGuk/syntaxhl&quot; target=&quot;_blank&quot;&gt;Syntaxhl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Copy the files into your SilverStripe installation at 'sapphire/thirdparty/tinymce/syntaxhl'.&lt;/li&gt;
&lt;li&gt;Then in your _config.php file add:&lt;br/&gt;&lt;pre class=&quot;brush: php;fontsize: 100; first-line: 1; &quot;&gt;HtmlEditorConfig::get('cms')-&amp;gt;enablePlugins('syntaxhl');
HtmlEditorConfig::get('cms')-&amp;gt;insertButtonsAfter('formatselect', 'syntaxhl');&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Also, in cms/_config.php add the following to 'extended_valid_elements' array:&lt;br/&gt;&lt;pre class=&quot;brush: plain;fontsize: 100; first-line: 1; &quot;&gt;textarea[cols|rows|disabled|name|readonly|class]
&lt;br/&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Now you should be able to use the Syntaxhl TinyMCE plugin from within the CMS to add code to your page, however it will not render as you would expect just yet. You now need to download the actual SyntaxHighlighter javascript library and add it to any pages you wish to use SyntaxHighlighter on. You will do this by downloading SyntaxHighlighter script files from &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/download/&quot; target=&quot;_blank&quot;&gt;the SyntaxHighlighter website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once you've downloaded all the files, and uploaded them to your server. You will need to add the CSS and JS files to your SilverStripe theme templates. If you want to use them on all pages of your SilverStripe website, then add the files to your Page.ss file, otherwise you can choose to add the scripts and styles to only specific page types. As an example, if you have the blog module and only want to use SyntaxHighlighter within the blog, you would add the scripts only to the BlogEntry.ss and BlogHolder.ss template files.&lt;/p&gt;
&lt;p&gt;Last thing to remember is to run SyntaxHighlighter by adding:&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;&lt;pre class=&quot;brush: jscript;fontsize: 100; first-line: 1; &quot;&gt;SyntaxHighlighter.all();&lt;/pre&gt;

&lt;p&gt;At the bottom of the template.&lt;/p&gt;</description>
			<pubDate>Wed, 14 Dec 2011 12:08:08 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/add-syntaxhighlighter-to-silverstripe/</guid>
		</item>
		
		<item>
			<title>My New Favorite Text Editor</title>
			<link>http://www.mitchviner.com/blog/my-new-favorite-text-editor/</link>
			<description>&lt;p&gt;I have been using Eclipse based editors for years for all of my development. Whether it's javascript, Java, or PHP I've always used some flavor of Eclipse and never had a problem. They always work, have great autocomplete and intellisense. However, for some larger files and projects they always run slow or even crash frequently, in my experience.&lt;/p&gt;
&lt;p&gt;So I tried experimenting with some other editors, MacVim, Sublime Text 2, among others. In my experimenting, I decided that my favorite, and now my Eclipse replacement is Sublime Text 2. Why?&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It's FAST!&lt;/li&gt;
&lt;li&gt;Extensible - with nice selection of existing plug-ins&lt;/li&gt;
&lt;li&gt;Easy to configure - able to change setting per project and that projects code guidellines&lt;/li&gt;
&lt;li&gt;Great command system&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Doing things in Sublime is easy, cmd + shift + p start typing the command, press enter. I do this all day. I don't spend time going through menu's anymore, I can do just about everything that I need to in my daily development tasks (within Sublime) without taking my hands off the keyboard. Even opening files, Sublime has a great method to find and open the files you need. Just press cmd + p, then start typiing the name of the file, once you see the file, arrow to it, press enter and it's open and ready to edit.&lt;/p&gt;
&lt;p&gt;The command system is great, it's super fast, there are quality plugins (SFTP is my most used). However, it does require some sacrifices in terms of autocompletion. I'm not easily able to find a method signature for a third party library without actually opening up the file itself or looking it up in some documentation. BUT, I will gladly sacrifice that any day for the gains in speed that I see in other areas. It's no secret that when the editor ( or IDE ) has to keep a catalog of the method signatures / help docs for your entire application, it's going to start slowing it down. For me, this isn't a big deal, but it may be for you. I'm sure everyone's mileage varies, but Sublime Text 2 is my new go to editor.&lt;/p&gt;
&lt;p&gt;Download it &lt;a href=&quot;http://www.sublimetext.com/2&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; and try it for yourself.&lt;/p&gt;</description>
			<pubDate>Wed, 07 Dec 2011 15:12:38 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/my-new-favorite-text-editor/</guid>
		</item>
		
		<item>
			<title>New Skullcandy</title>
			<link>http://www.mitchviner.com/blog/new-skullcandy/</link>
			<description>&lt;p&gt;At my job, we have a rewards program that I've been accruing points in for the past year or so. Well I had saved up quite a bit when we were told we had to spend what we have since the program is being discontinued ( bummer since I was planning on saving for a long time and getting a new TV :( ). Well I decided to use my points on a nice set of headphones, since the ones I had in middle school got stolen years ago.&lt;/p&gt;
&lt;p&gt;I ended up getting &lt;a href=&quot;http://www.skullcandy.com/shop/2011-hesh-black-gray&quot; target=&quot;_blank&quot;&gt;Skullcandy Hesh&lt;/a&gt; headphones. They took FOREVER to come in from the rewards company ( not drop-shipped and not meant to be a reflection of Skullcandy shipping service when buying direct.... blah! ) but they were free so I shouldn't really complain. Anyway, these things are great. I sit at my computer for at least 8 hours a day, sometimes much longer. And, for the past few days I've been blasting some of my favorite music and just loving the clear sound and nice bass that these headphones have been producing. Just last night, my wife came into my office with a disgusted look on her face and said, &quot;I've been calling you for 10 minutes!&quot;. These are by far the best headphones I've ever owned, however it's worth noting I haven't had a set that didn't come with the iPod or Phone I've purchased since, as stated before, middle school!&lt;/p&gt;
&lt;p&gt;So take my opinion for what it is, but I just wanted to share my thoughts and love for these headphones. If you're contemplating getting a pair, go ahead, you won't be dissappointed.&lt;/p&gt;</description>
			<pubDate>Thu, 10 Nov 2011 20:00:00 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/new-skullcandy/</guid>
		</item>
		
		<item>
			<title>Brief Hiatus</title>
			<link>http://www.mitchviner.com/blog/brief-hiatus/</link>
			<description>&lt;p&gt;My aplogies, I've taken a brief hiatus from my blog during it's infancy. I just finished doing a large addition to my house, and will now be able to pick back up where I left off. I'll be adding more content in the blog in the coming days as I get back into doing the work I love ( web development ) and not doing the work I hate ( house addition ).&lt;/p&gt;
&lt;p&gt;Anyway.... stay tuned!&lt;/p&gt;</description>
			<pubDate>Tue, 08 Nov 2011 10:30:00 -0600</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/brief-hiatus/</guid>
		</item>
		
		<item>
			<title>Custom Symfony Services</title>
			<link>http://www.mitchviner.com/blog/custom-symfony-services/</link>
			<description>&lt;p&gt;Today I've spent some time refactoring some code on a project I'm building on the Symfony2 Framework. Admittably, this is my first &quot;real&quot; project using the framework, so I expected some growing ( or learning ) pains. I initially read through the Symfony2 Documentation and did a few small projects to get my feet wet. However, it wasn't until building this larger appiication that I saw the real value in setting up custom services.&lt;/p&gt;
&lt;p&gt;Essentially, I decided I wanted a better way of getting my doctrine repositories, since I found myself frequently typing:&lt;/p&gt;
&lt;pre class=&quot;brush: php;light: true;fontsize: 100; first-line: 1; &quot;&gt;$this-&amp;gt;getDoctrine()-&amp;gt;getRepository('SomeBundlePackage:Entity')&lt;/pre&gt;
&lt;p&gt;Well this doesn't seem all that bad, but the fact that this is just an example of one of many services within my application. Symfony provides many built in services that are accessible via a much friendlier method inside your controllers:&lt;/p&gt;
&lt;pre class=&quot;brush: php;light: true; fontsize: 100; first-line: 1; &quot;&gt;$service = $this-&amp;gt;get('serviceName');&lt;/pre&gt;
&lt;p&gt;Well, you can setup your own services to be accessible via this same 'get' method from inside of your controllers. The following will create a service from a doctrine repository.&lt;/p&gt;
&lt;p&gt;In src/Project/MyBundle/Resources/config/services.yml:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&quot;brush: plain;fontsize: 100; first-line: 1; &quot;&gt;parameters:
  entity.entityName: Project\MyBundle\Entity\EntityName

services:

  #Doctrine factory service
  My.repoFactory:
    alias: doctrine.orm.default_entity_manager

  My.repository:
    class: %entity.entityName%
    factory_service: My.repoFactory
    factory_method: getRepository
    arguments:
      - %entity.entityName%&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;In the first two lines above, we store the name of our service class as a parameter.&lt;/p&gt;
&lt;p&gt;Then in the 'My.repoFactory' section, we create a local reference to the factory class that will create an instance of a doctrine repository. In this case, we are getting the Doctrine Entity Manager. This type of reference may not be necessary for a custom service that does not have any dependancies.&lt;/p&gt;
&lt;p&gt;Next, we define our actual service. You can see, that we call the getRepository function of the 'entity manager' passing in the class name of the entity that we want the repository for.&lt;/p&gt;
&lt;p&gt;Now we can use this service in any of our controllers within this bundle by calling:&lt;/p&gt;
&lt;pre class=&quot;brush: php;light: true; fontsize: 100; first-line: 1; &quot;&gt;$myRepo = $this-&amp;gt;get('My.repository');&lt;/pre&gt;
&lt;p&gt;The example above uses the existing Doctrine framework as the basis for our custom service, but this same method can be used for your own custom created services as well.&lt;/p&gt;
&lt;p&gt;This really only scratches the surface of Symfony2's service container, so go check out &lt;a href=&quot;http://www.mitchviner.com/#http://symfony.com/doc/current/book/service_container.html&quot; target=&quot;_blank&quot;&gt;Symfony's own documentation&lt;/a&gt; if you need more help.&lt;/p&gt;
&lt;p&gt;I'll cover this topic more in-depth at a later date.&lt;/p&gt;</description>
			<pubDate>Thu, 25 Aug 2011 13:00:00 -0500</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/custom-symfony-services/</guid>
		</item>
		
		<item>
			<title>jQuery Deferreds</title>
			<link>http://www.mitchviner.com/blog/jquery-deferreds/</link>
			<description>&lt;p&gt;I don't really think this qualifies as a &quot;quality&quot; first post, but I just wanted to throw a quick shout to my blog, to take a minute and call myself an idiot. I'm a fan of jQuery, I use it anytime I get the choice of which JS Framework to use on a project. I usually pride myself with being up on the &quot;latest&quot; with what's going on with jQuery and will take the time to read about new things they are adding, or proposing to add to jQuery core. Well, long story short, i ignored Deferreds... and now I regret it.&lt;/p&gt;
&lt;p&gt;The Deferred object that was introduced in jQuery 1.5 is amazing. I've just finished using it for the first time and I love how easy it is. Typically, when I am running some complex action, during which I may have to fire an ajax request, recalculate element sizes, or parse some compex JSON object, then fire some callback method. I would do it one of two ways, either Pub/Sub, where I just fire a custom event when the processing is done, then in my subscriber I would check to see if it was successful, etc. The other way would be to pass a callback method into the function itself and then call the callback on completion. Both methods worked, they worked pretty well actually. This is likely why I ignored Deferred's in the first place, I didn't really see a place for them at the time. However, now that I have taken the time to understand the Deferred object and it's API, I can honestly say I feel like an idiot for not paying it more attention months ago.&lt;/p&gt;
&lt;p&gt;In short, the Deferred object in the jQuery core can drastically clean up your code. Making it exponentially easier to read and follow exactly what processing is happening and when. This post isn't about how to use Deferred's, sorry if that's what you were hoping for ( but you can find it here, &lt;a href=&quot;http://api.jquery.com/category/deferred-object/&quot; target=&quot;_blank&quot;&gt;jQuery Deferred Object&lt;/a&gt; ), this is just to say &quot;You SHOULD be using them&quot;.&lt;/p&gt;</description>
			<pubDate>Mon, 08 Aug 2011 18:30:00 -0500</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/jquery-deferreds/</guid>
		</item>
		
		<item>
			<title>First Post...</title>
			<link>http://www.mitchviner.com/blog/first-post/</link>
			<description>&lt;p&gt;So, welcome to my blog, or should I say my attempt at a blog. I'm pretty notorious for starting these types of things and then never actually writing on them. But alas, maybe this time will be different.&lt;/p&gt;
&lt;p&gt;I guess I'll start off with some background about me. This is my personal website (obviously) and portfolio. I'm a web developer with over 6 years of experience, most of which has been spent doing front-end development, but recently I've started to focus in on backend / application development. Alot of this change has to do with the fact that with recent advances in JavaScript, the HTML5 spec, and browser technology, the line that defines a front-end and a back-end developer is really starting to blur. This is a good thing, in my opinion. I believe that with the emergence of Mobile browsing over the last few years and the &quot;Apps&quot; craze continuing into the forseeable future, that the front-end / back-end developer line will only continue to blur.&lt;/p&gt;
&lt;p&gt;Currently, my primary interests are Event Driven Front-End Development, Symfony2 and Doctrine2, and Magento Ecommerce. As a result, I'm working on an application using all three of these methodologies and technologies, respectively. I'm hoping my experiences with this project will help build this blog from nothing to something, even if that something is small.&lt;/p&gt;
&lt;p&gt;Thanks for checking this out, and stay tuned...&lt;/p&gt;</description>
			<pubDate>Wed, 03 Aug 2011 12:46:17 -0500</pubDate>
			
			
			<guid>http://www.mitchviner.com/blog/first-post/</guid>
		</item>
		

	</channel>
</rss>
