<?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>Query7 &#187; Programming</title>
	<atom:link href="http://query7.com/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://query7.com</link>
	<description>PHP, Javascript, Python and Web Development</description>
	<lastBuildDate>Sat, 25 Jun 2011 21:29:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Resources for Learning Vim</title>
		<link>http://query7.com/resources-for-learning-vim</link>
		<comments>http://query7.com/resources-for-learning-vim#comments</comments>
		<pubDate>Mon, 23 May 2011 09:48:38 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1710</guid>
		<description><![CDATA[<p>Over the last few months I&#8217;ve found myself using the <a href="http://vim.org">Vim</a> text editor an increasing amount. Below are some resources that I found particularly useful.</p>
<h3>Venturing Into Vim</h3>
<p>Jeffery Way, editor and author of Nettuts, has released a 4 part video tutorial series called <a href="http://marketplace.tutsplus.com/item/venturing-into-vim-4part-video-series/131400">Learning Vim From The Ground Up</a>. The 4 videos total over 2 hours playtime and cost just $5. They are recorded on Mac OS X at a screen resolution of 1280×720. Way&#8217;s experience in screencasting really shows in these videos. He clearly communicates all of his points, step by step, at a good speed. These videos start with the assumption you know absolutely nothing about Vim so they are a great resource for a Vim user of any level.</p>
<h3>Vim Cheatsheet</h3>
<p>The folks at ViEmu.com (who produce Vim keybindings for MS Office and Visual Studio) have produced a printable <a href="http://www.viemu.com/vi-vim-cheat-sheet.gif">Vim cheatsheet</a>. The cheatsheet clearly lays out the lower and upper case functionality for each key as well as some general Vim commands. The text size and colour contrast makes it easy to read from a distance, I recommend you print it out.</p>
<p><a href="http://www.viemu.com/vi-vim-cheat-sheet.gif"><img height="382" width="540" src="http://www.viemu.com/vi-vim-cheat-sheet.gif" alt="vim cheatsheet" /></a></p>
<h3>VimCasts.org</h3>
<p>Drew Neil produces short, focused Vim screencasts and posts&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>Over the last few months I&#8217;ve found myself using the <a href="http://vim.org">Vim</a> text editor an increasing amount. Below are some resources that I found particularly useful.</p>
<h3>Venturing Into Vim</h3>
<p>Jeffery Way, editor and author of Nettuts, has released a 4 part video tutorial series called <a href="http://marketplace.tutsplus.com/item/venturing-into-vim-4part-video-series/131400">Learning Vim From The Ground Up</a>. The 4 videos total over 2 hours playtime and cost just $5. They are recorded on Mac OS X at a screen resolution of 1280×720. Way&#8217;s experience in screencasting really shows in these videos. He clearly communicates all of his points, step by step, at a good speed. These videos start with the assumption you know absolutely nothing about Vim so they are a great resource for a Vim user of any level.</p>
<h3>Vim Cheatsheet</h3>
<p>The folks at ViEmu.com (who produce Vim keybindings for MS Office and Visual Studio) have produced a printable <a href="http://www.viemu.com/vi-vim-cheat-sheet.gif">Vim cheatsheet</a>. The cheatsheet clearly lays out the lower and upper case functionality for each key as well as some general Vim commands. The text size and colour contrast makes it easy to read from a distance, I recommend you print it out.</p>
<p><a href="http://www.viemu.com/vi-vim-cheat-sheet.gif"><img height="382" width="540" src="http://www.viemu.com/vi-vim-cheat-sheet.gif" alt="vim cheatsheet" /></a></p>
<h3>VimCasts.org</h3>
<p>Drew Neil produces short, focused Vim screencasts and posts them at <a href="http://vimcasts.org">VimCasts.org</a>. They are typically 5-10 minutes in length and each focus on how to achieve or learn a particular feature of Vim. My favourite VimCast is about <a href="http://vimcasts.org/episodes/synchronizing-plugins-with-git-submodules-and-pathogen/">Synchronizing plugins with git submodules and pathogen</a>. In it Neil walks you through setting up a directory which holds the <em>.vimrc</em> file and all vim plugins. He then shows how you can install Vim plugins as git submodules using the pathogen plugin for Vim.</p>
<h3>vimtutor</h3>
<p>vimtutor is an interactive learning application that comes bundled with Vim. It can be started by entering the command <em>vimtutor</em> into the shell. It should take a beginner around 30 minutes to complete. I recommend doing <em>vimtutor</em> daily until you can comfortably complete it without needing to actively think about the keys you are pressing.</p>
<p><a href="http://query7.com/wp-content/uploads/vimtutor.png"><img src="http://query7.com/wp-content/uploads/vimtutor.png" alt="" title="vimtutor" width="540" height="400" class="aligncenter size-full wp-image-1718" /></a></p>
<h3>Additional Reading</h3>
<ul>
<li><a href="http://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118">Understanding Vim</a></li>
<li><a href="http://vim.wikia.com/wiki/Tutorial">Using the basic commands</a></li>
<li><a href="http://jmcpherson.org/editing.html">Efficient Editing with Vim</a></li>
<li><a href="http://rayninfo.co.uk/vimtips.html">Hundreds of Vim 1 liners</a> (amazing read)</li>
<li><a href="http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about">What are the dark corners your Mom never told you about?</a></li>
<li><a href="http://stackoverflow.com/questions/164847/what-is-in-your-vimrc">What is in your <em>.vimrc</em>?</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/resources-for-learning-vim/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kohana 3.1 Wiki Tutorial Routes</title>
		<link>http://query7.com/kohana-3-1-wiki-tutorial-routes</link>
		<comments>http://query7.com/kohana-3-1-wiki-tutorial-routes#comments</comments>
		<pubDate>Mon, 16 May 2011 07:39:43 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1655</guid>
		<description><![CDATA[<p>In the original <a href="http://query7.com/kohana-3-1-wiki-tutorial">Kohana wiki application</a> the URLs in the views were hardcoded. If we wanted to change the domain name or restructure a route we would need to go through the application and change every single URL.</p>
<p>Thankfully the Kohana <em>Route</em> class comes with a method <em>url()</em> which allows us to generate URLs to routes we have specified in the application. In the first <a href="http://query7.com/kohana-3-1-wiki-tutorial">tutorial</a> we defined the following routes in <strong>application/bootstrap.php</strong>:</p>
<pre>Route::set('wiki-edit', 'wiki/&#60;page&#62;/edit')
	-&#62;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'edit_page',
	));

Route::set('wiki-save', 'wiki/&#60;page&#62;/save')
	-&#62;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'save_page',
	));

Route::set('wiki-page', 'wiki/&#60;page&#62;')
	-&#62;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'view_page',
	));

Route::set('default', 'wiki')
	-&#62;defaults(array(
		'controller' => 'wiki',
		'action'     => 'view_page',
		'id'		 => 'index',
	));
</pre>
<p>Before we can generate routes we need to set some configuration options in <strong>application/bootstrap.php</strong> (line ~82). We need to specify the <em>base_url</em> and <em>index_file</em> attributes in the array passed to <em>Kohana::init()</em>. The application on my local install is located at 127.0.0.1/query7kwiki/index.php, so my <em>Kohana::init()</em> statement would read:</p>
<pre>Kohana::init(array(
	'base_url'   =&#62; '/query7kwiki/',
	'index_file' =&#62; 'index.php'
));</pre>
<p>In <strong>application/views/edit.php</strong> the form <em>action</em> attribute was hardcoded to the value <em>/query7kwiki/index.php/wiki/</em>. That can be replaced by:</p>
<pre>&#60;?php echo Route::url('wiki-save', array('page' =&#62; $page)); ?&#62;</pre>
<p>In <strong>application/views/single.php</strong> there is a&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>In the original <a href="http://query7.com/kohana-3-1-wiki-tutorial">Kohana wiki application</a> the URLs in the views were hardcoded. If we wanted to change the domain name or restructure a route we would need to go through the application and change every single URL.</p>
<p>Thankfully the Kohana <em>Route</em> class comes with a method <em>url()</em> which allows us to generate URLs to routes we have specified in the application. In the first <a href="http://query7.com/kohana-3-1-wiki-tutorial">tutorial</a> we defined the following routes in <strong>application/bootstrap.php</strong>:</p>
<pre>Route::set('wiki-edit', 'wiki/&lt;page&gt;/edit')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'edit_page',
	));

Route::set('wiki-save', 'wiki/&lt;page&gt;/save')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'save_page',
	));

Route::set('wiki-page', 'wiki/&lt;page&gt;')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'view_page',
	));

Route::set('default', 'wiki')
	-&gt;defaults(array(
		'controller' => 'wiki',
		'action'     => 'view_page',
		'id'		 => 'index',
	));
</pre>
<p>Before we can generate routes we need to set some configuration options in <strong>application/bootstrap.php</strong> (line ~82). We need to specify the <em>base_url</em> and <em>index_file</em> attributes in the array passed to <em>Kohana::init()</em>. The application on my local install is located at 127.0.0.1/query7kwiki/index.php, so my <em>Kohana::init()</em> statement would read:</p>
<pre>Kohana::init(array(
	'base_url'   =&gt; '/query7kwiki/',
	'index_file' =&gt; 'index.php'
));</pre>
<p>In <strong>application/views/edit.php</strong> the form <em>action</em> attribute was hardcoded to the value <em>/query7kwiki/index.php/wiki/</em>. That can be replaced by:</p>
<pre>&lt;?php echo Route::url('wiki-save', array('page' =&gt; $page)); ?&gt;</pre>
<p>In <strong>application/views/single.php</strong> there is a link to the edit that specific page. We can replace the <em>href</em> of the anchor tag with:</p>
<pre>&lt;?php echo Route::url('wiki-edit', array('page' =&gt; $page)); ?&gt;</pre>
<p>In the view <strong>application/views/create.php</strong> change the <em>href</em> of the create page link to:</p>
<pre>&lt;?php echo Route::url('wiki-edit', array('page' =&gt; $page)); ?&gt;</pre>
<p>The wiki application is now portable and can safely be moved to a different server without functionality breaking.</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/kohana-3-1-wiki-tutorial-routes/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kohana 3.1 Wiki Tutorial</title>
		<link>http://query7.com/kohana-3-1-wiki-tutorial</link>
		<comments>http://query7.com/kohana-3-1-wiki-tutorial#comments</comments>
		<pubDate>Mon, 09 May 2011 06:09:52 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1632</guid>
		<description><![CDATA[<p>In this tutorial you will learn how to create a simple wiki using the PHP framework Kohana version 3.1. Several years ago Siddharta Govindaraj created a <a href="http://showmedo.com/videotutorials/video?name=1100000&#038;fromSeriesID=110">screencast</a> demonstrating how to create a wiki using Django, this is essentially the Kohana version of that. It covers using Kohana&#8217;s Routing, ORM and MVC systems. Full source code of the application is available on <a href="https://github.com/lastkarrde/query7kwiki">github</a>.</p>
<p>The wiki application has 3 different pages: </p>
<ul>
<li>/wiki/somepage/save &#8211; handles the saving of the page</li>
<li>/wiki/somepage/edit &#8211; displays a form that allows the user to edit the page</li>
<li>/wiki/somepage &#8211; displays the page</li>
</ul>
<h3>Configuration</h3>
<p>We will be using the ORM module to query the database for our wiki pages so we must load it in the <strong>application/bootstrap.php</strong> file (Line ~99).</p>
<pre>Kohana::modules(array(

	'database'   => MODPATH.'database',   // Database access
	'orm'        => MODPATH.'orm',        // Object Relationship Mapping

	));</pre>
<p>We also need to specify our database configuration settings. This is done in <strong>application/config/database.php</strong>.</p>
<pre>&#60;?php

return array
  (
  	'default' => array
  	(
  		'type'       => 'mysql',
  		'connection' => array(
  			'hostname'   => '127.0.0.1',
  			'username'   => 'root',
  			'password'   => 'root',
  			'persistent' => FALSE,
  			'database'   => 'query7kwiki',
  		),
  		'table_prefix' => '',
  		'charset'      => 'utf8',
  		'caching'      => FALSE,
  		'profiling'    => TRUE,
  	),
  );</pre><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>In this tutorial you will learn how to create a simple wiki using the PHP framework Kohana version 3.1. Several years ago Siddharta Govindaraj created a <a href="http://showmedo.com/videotutorials/video?name=1100000&#038;fromSeriesID=110">screencast</a> demonstrating how to create a wiki using Django, this is essentially the Kohana version of that. It covers using Kohana&#8217;s Routing, ORM and MVC systems. Full source code of the application is available on <a href="https://github.com/lastkarrde/query7kwiki">github</a>.</p>
<p>The wiki application has 3 different pages: </p>
<ul>
<li>/wiki/somepage/save &#8211; handles the saving of the page</li>
<li>/wiki/somepage/edit &#8211; displays a form that allows the user to edit the page</li>
<li>/wiki/somepage &#8211; displays the page</li>
</ul>
<h3>Configuration</h3>
<p>We will be using the ORM module to query the database for our wiki pages so we must load it in the <strong>application/bootstrap.php</strong> file (Line ~99).</p>
<pre>Kohana::modules(array(

	'database'   => MODPATH.'database',   // Database access
	'orm'        => MODPATH.'orm',        // Object Relationship Mapping

	));</pre>
<p>We also need to specify our database configuration settings. This is done in <strong>application/config/database.php</strong>.</p>
<pre>&lt;?php

return array
  (
  	'default' => array
  	(
  		'type'       => 'mysql',
  		'connection' => array(
  			'hostname'   => '127.0.0.1',
  			'username'   => 'root',
  			'password'   => 'root',
  			'persistent' => FALSE,
  			'database'   => 'query7kwiki',
  		),
  		'table_prefix' => '',
  		'charset'      => 'utf8',
  		'caching'      => FALSE,
  		'profiling'    => TRUE,
  	),
  );

  ?&gt;</pre>
<h3>Model</h3>
<p>Compared to most ORMs (Django, Doctrine, Propel), Kohana&#8217;s ORM is relatively light. You don&#8217;t need to specify the fields of your table as the Kohana ORM doesn&#8217;t attempt to generate the tables for you. It simply maps attribute names of the model object to field names in the database table. Be sure to check the <a href="http://kohanaframework.org/3.1/guide/">Kohana Documentation</a> for a detailed explanation of the ORM.</p>
<p><strong>application/classes/model/page.php</strong></p>
<pre>class Model_Page extends ORM
{

	protected $_table_name = 'page';

	public function rules()
	{
		return array(

			'title' => array(
						array('not_empty')
							)

		);
	}

}</pre>
<p>Execute the following SQL:</p>
<pre>CREATE TABLE `page` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 255 ) NOT NULL ,
`content` TEXT NOT NULL
) ENGINE = MYISAM ;</pre>
<h3>Routing</h3>
<p>I define all routes at the bottom of <strong>application/bootstrap.php</strong>, however if you are working on a large application it may beneficial in the long run to define them in a separate file and then include them into the bootstrap file.</p>
<p><em>Route::set()</em> accepts 2 parameters. The first is the name of the route and the second is the URI pattern it should match. Because <em>Route::set()</em> returns an instance of <em>Kohana_Route</em>, we can chain the <em>defaults</em> method onto it. There we specify the controller and action that should be executed if the route is matched. </p>
<p>The <em>&lt;page&gt;</em> section of the URI pattern is captured from the URI and automatically passed to the controller method as an argument.</p>
<pre>Route::set('wiki-edit', 'wiki/&lt;page&gt;/edit')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'edit_page',
	));

Route::set('wiki-save', 'wiki/&lt;page&gt;/save')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'save_page',
	));

Route::set('wiki-page', 'wiki/&lt;page&gt;')
	-&gt;defaults(array(
		'controller'=> 'wiki',
		'action'	=> 'view_page',
	));

Route::set('default', 'wiki')
	-&gt;defaults(array(
		'controller' => 'wiki',
		'action'     => 'view_page',
		'id'		 => 'index',
	));
</pre>
<h3>Views</h3>
<p><strong><a href="http://query7.com/kohana-3-1-wiki-tutorial-routes">Read this tutorial on generating domain-independent, non hardcoded URLs</a></strong></p>
<p><strong>application/views/single.php</strong></p>
<pre>&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;&lt;?php echo $page; ?&gt;&lt;/title&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;h1&gt;&lt;?php echo $page; ?&gt;&lt;/h1&gt;
		&lt;p&gt;
			&lt;?php echo $content; ?&gt;
		&lt;/p&gt;
		&lt;hr&gt;
		&lt;p&gt;
			&lt;a href=&quot;/query7kwiki/index.php/wiki/&lt;?php echo $page; ?&gt;/edit&quot;&gt;Edit&lt;/a&gt;
		&lt;/p&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre>
<p><strong>application/views/create.php</strong></p>
<pre>&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;&lt;?php echo $page; ?&gt; - Create&lt;/title&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;h1&gt;&lt;?php echo $page; ?&gt;&lt;/h1&gt;
		&lt;p&gt;This page does not exist. &lt;a href=&quot;/query7kwiki/index.php/wiki/&lt;?php echo $page; ?&gt;/edit/&quot;&gt;Create?&lt;/a&gt;&lt;/p&gt;

	&lt;/body&gt;
&lt;/html&gt;</pre>
<p><strong>application/views/edit.php</strong></p>
<pre>&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;&lt;?php echo $page; ?&gt; - Edit&lt;/title&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;h1&gt;&lt;?php echo $page; ?&gt; - Edit&lt;/h1&gt;
		&lt;p&gt;
			&lt;form method=&quot;POST&quot; action=&quot;/query7kwiki/index.php/wiki/&lt;?php echo $page; ?&gt;/save/&quot;&quot;&gt;

				&lt;textarea rows=&quot;10&quot; cols=&quot;60&quot; name=&quot;content&quot;&gt;&lt;?php echo $content; ?&gt;&lt;/textarea&gt;
				&lt;br /&gt;
				&lt;input type=&quot;submit&quot; value=&quot;Edit Page&quot; name=&quot;submit&quot;&gt;
			&lt;/form&gt;
		&lt;/p&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre>
<h3>Controller</h3>
<p>The wiki only has one controller, <em>Controller_Wiki</em>, located in <strong>application/classes/controller/wiki.php</strong>. All of the methods accept one parameter, the name of the page which is automatically passed by the URL Router.</p>
<p>The <em>action_view_page()</em> method will display the wiki page if it exists or a &#8216;create&#8217; page if it does not exist. <em>$single-&gt;loaded()</em> will return true if the ORM returned a result, so if the page exists we load the &#8216;single&#8217; view and attach the appropriate variables to the view, if it does not exist then we load the &#8216;create&#8217; view.</p>
<pre>public function action_view_page($page)
{

	$single = ORM::factory('page')
			-&gt;where('title', '=', $page)
			-&gt;find();

	if($single->loaded())
	{
		$v = View::factory('single');
		$v-&gt;page = $page;
		$v-&gt;content = $single-&gt;content;
				}
	else
	{
		$v = View::factory('create');
		$v-&gt;page = $page;
	}

	$this-&gt;response-&gt;body($v);

}</pre>
<p><em>action_edit_page()</em> returns the &#8216;edit&#8217; page with the correct <em>content</em> field.</p>
<pre>public function action_edit_page($page)
{
	$single = ORM::factory('page')
			-&gt;where('title', '=', $page)
			-&gt;find();

	if($single-&gt;loaded())
	{
		$content = $single-&gt;content;
	}
	else
	{
		$content = '';
	}

	$v = View::factory('edit');
	$v-&gt;page = $page;
	$v-&gt;content = $content;

	$this-&gt;response-&gt;body($v);
}</pre>
<p><em>action_save_page()</em> handles saving the page after the user submits the edit form. It first checks to see if the page exists. If it does exist then we update the <em>content</em> attribute of the model with whatever was posted in the form. If it doesn&#8217;t exist then we make a new page by instantiating a new model, assigning the <em>title</em> and <em>content</em> attributes and saving it.</p>
<pre>public function action_save_page($page)
{
	$single = ORM::factory('page')
			-&gt;where('title', '=', $page)
			-&gt;find();

	$content = $this-&gt;request-&gt;post('content');

	if($single-&gt;loaded())
	{
		$single-&gt;content = $content;
		$single-&gt;save();
	}
	else
	{
		$new_single = new Model_Page();
		$new_single-&gt;title = $page;
		$new_single-&gt;content = $content;
		$new_single-&gt;save();
	}

	$this-&gt;request-&gt;redirect('http://127.0.0.1/query7kwiki/index.php/wiki/' . $page);

}</pre>
<p>Full source code of the application is available on <a href="https://github.com/lastkarrde/query7kwiki">Github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/kohana-3-1-wiki-tutorial/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tutorial Django Dojo DataGrid</title>
		<link>http://query7.com/tutorial-django-dojo-datagrid</link>
		<comments>http://query7.com/tutorial-django-dojo-datagrid#comments</comments>
		<pubDate>Mon, 18 Apr 2011 10:03:57 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1476</guid>
		<description><![CDATA[<p>Dojo is an open source Javascript toolkit. It provides an easy way to access and modify the DOM as well as a rich user interface widget library. One of the most powerful widgets in the Dojo toolkit is <a href="http://dojotoolkit.org/reference-guide/dojox/grid/DataGrid.html">DataGrid</a>. It provides an easy way to represent what is essentially a cross between a spreadsheet and a table. In a recent Django project I needed to output the contents of a model into the DataGrid. Thanks to <a href="http://code.google.com/p/django-dojoserializer/">django-dojoserializer</a> this is very easy.</p>
<h3>Setup</h3>
<p>We need the Python package <a href="http://code.google.com/p/django-dojoserializer/">django-dojoserializer</a>. This can be installed by downloading the source and running
<pre>python setup.py install</pre>
</p><p> or with setuptools using
<pre>easy_install django-dojoserializer</pre>
</p><p> or with pip using
<pre>pip install django-dojoserializer</pre>
</p><p> Then add <em>django-dojoserializer</em> to the <em>INSTALLED_APPS</em> tuple in <strong>settings.py</strong>.</p>
<p>Dojo will need to be linked correctly in the Django template. We need to require the <em>dojox.grid.DataGrid</em> and <em>dojo.data.ItemFileReadStore</em> classes.</p>
<pre>&#60;script src="/static/libs/dojo/dojo.js" djConfig="parseOnLoad: true"&#62;%lt;/script&#62;
&#60;script type="text/javascript"&#62;
dojo.require('dojox.grid.DataGrid');
dojo.require('dojo.data.ItemFileReadStore');
&#60;/script&#62;
</pre>
<h3>Django Model</h3>
<pre>PROXY_TYPE_CHOICES = (

	('SOCKS4', 'SOCKS4'),
	('SOCKS5', 'SOCKS5'),
	('HTTP', 'HTTP'),

)

class Proxy(models.Model):
	ip = models.CharField(max_length=50)
	type = models.CharField(max_length=6, choices=PROXY_TYPE_CHOICES)
	alive = models.BooleanField(default=False)
	added = models.DateTimeField(auto_now=False, auto_now_add=True)
	last_checked = models.DateTimeField(auto_now=True, auto_now_add=False)

	def __unicode__(self):
		return self.ip</pre>
<h3>Django View</h3>
<p>The view needs&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>Dojo is an open source Javascript toolkit. It provides an easy way to access and modify the DOM as well as a rich user interface widget library. One of the most powerful widgets in the Dojo toolkit is <a href="http://dojotoolkit.org/reference-guide/dojox/grid/DataGrid.html">DataGrid</a>. It provides an easy way to represent what is essentially a cross between a spreadsheet and a table. In a recent Django project I needed to output the contents of a model into the DataGrid. Thanks to <a href="http://code.google.com/p/django-dojoserializer/">django-dojoserializer</a> this is very easy.</p>
<h3>Setup</h3>
<p>We need the Python package <a href="http://code.google.com/p/django-dojoserializer/">django-dojoserializer</a>. This can be installed by downloading the source and running
<pre>python setup.py install</pre>
<p> or with setuptools using
<pre>easy_install django-dojoserializer</pre>
<p> or with pip using
<pre>pip install django-dojoserializer</pre>
<p> Then add <em>django-dojoserializer</em> to the <em>INSTALLED_APPS</em> tuple in <strong>settings.py</strong>.</p>
<p>Dojo will need to be linked correctly in the Django template. We need to require the <em>dojox.grid.DataGrid</em> and <em>dojo.data.ItemFileReadStore</em> classes.</p>
<pre>&lt;script src="/static/libs/dojo/dojo.js" djConfig="parseOnLoad: true"&gt;%lt;/script&gt;
&lt;script type="text/javascript"&gt;
dojo.require('dojox.grid.DataGrid');
dojo.require('dojo.data.ItemFileReadStore');
&lt;/script&gt;
</pre>
<h3>Django Model</h3>
<pre>PROXY_TYPE_CHOICES = (

	('SOCKS4', 'SOCKS4'),
	('SOCKS5', 'SOCKS5'),
	('HTTP', 'HTTP'),

)

class Proxy(models.Model):
	ip = models.CharField(max_length=50)
	type = models.CharField(max_length=6, choices=PROXY_TYPE_CHOICES)
	alive = models.BooleanField(default=False)
	added = models.DateTimeField(auto_now=False, auto_now_add=True)
	last_checked = models.DateTimeField(auto_now=True, auto_now_add=False)

	def __unicode__(self):
		return self.ip</pre>
<h3>Django View</h3>
<p>The view needs to display data from our model as JSON which is correctly formatted for the Dojo DataTable. Simply encoding the Django queryset as a JSON object would not work. Thankfully <me>django-dojoserializer</em> provides the <em>dojoserializer.serialize()</em> method which correctly formats our the queryset in a format the DataTable can read. The route <em>/render/proxies</em> maps to the following view:</p>
<pre>
from django.http import HttpResponse
from proxies.models import Proxy
from dojoserializer import serialize

def render_json(request):

	proxies = Proxy.objects.filter(alive=True)

	json_data = serialize(proxies)

	return HttpResponse(json_data, mimetype="application/json")
</pre>
<p>This gives the following output:</p>
<p><a href="http://query7.com/wp-content/uploads/json.png"><img src="http://query7.com/wp-content/uploads/json.png" alt="" title="json" width="540" height="274" class="aligncenter size-full wp-image-1482" /></a></p>
<h3>Defining the DataTable</h3>
<p>We define the Dojo DataTable in two parts. The first is a Javascript representation of the structure of the DataTable, the second part is a <em>&lt;div&gt;</em> for where the DataTable will sit in markup. Note that each <em>field</em> attribute is the exact name of the corresponding field from the Django model. If the names do match the data will not display in the table.</p>
<pre>var layoutProxies = [
            [{
                field: "ip",
                name: "IP",
                width: 'auto'
            },
            {
                field: "type",
                name: "Type",
                width: 'auto'
            },
            {
                field: "last_checked",
                name: "Last Checked",
                width: 10
            },
            {
                field: "alive",
                name: "Alive",
                width: 'auto'
            }

            ]];</pre>
<p>Note the structure attribute of the <em>div</em> is set to the value of our structure. We will define <em>proxyStore</em>, the value of the <em>store</em> attribute below.</p>
<pre>
&lt;div id="proxyGrid" dojoType="dojox.grid.DataGrid" store="proxyStore" structure="layoutProxies" query="{}" rowsPerPage="40"&gt;&lt;/div&gt;</pre>
<h3>Connecting the DataTable to The Proxy Data</h3>
<p>Finally we need to specify the <em>proxyStore</em> variable for the table to pull its data from. <em>proxyStore</em> is an instance of <em>dojo.data.ItemFileReadStore()</em>. We pass the URL of our JSON file and set <em>urlPreventCache</em> to true.</p>
<pre>proxyStore = new dojo.data.ItemFileReadStore({url: '/render/proxies', urlPreventCache: true});</pre>
<p>Which gives the final product:</p>
<p><img src="http://query7.com/wp-content/uploads/ss.png" alt="" title="ss" width="540" height="300" class="aligncenter size-full wp-image-1480" /></p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/tutorial-django-dojo-datagrid/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NodeJS cURL Tutorial</title>
		<link>http://query7.com/nodejs-curl-tutorial</link>
		<comments>http://query7.com/nodejs-curl-tutorial#comments</comments>
		<pubDate>Mon, 28 Mar 2011 01:34:25 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[nodejs]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1369</guid>
		<description><![CDATA[<p>NodeJS is a powerful evented Javascript platform running on top of Google&#8217;s V8 javascript engine. Over the last year the popularity of NodeJS has increased greatly, as shown by the number of discussions on programming forums such as Hacker News, Reddit and Stackoverflow. Despite this NodeJS is still young and it falls short to Python and Ruby when it comes to the number and range of libraries and modules available.</p>
<h3>The Problem</h3>
<p>I wanted to convert one of my web scraping applications I made in PHP to NodeJS. The application interacts with SOCKS4 and SOCKS5 proxies using PHP&#8217;s cURL bindings. Unfortunately there are no cURL bindings (or SOCKS protocol wrappers) written for NodeJS. NodeJS does come with an HTTP client module that can issue web requests, however it doesn&#8217;t support SOCKS proxies.</p>
<h3>The Solution</h3>
<p>Although there are no specific NodeJS bindings for cURL, we can still issue cURL requests via the command line interface. NodeJS comes with the <em>child_process</em> module which easily allows us to start processes and read their output. Doing so is fairly straight forward. We just need to import the <a href="http://nodejs.org/docs/v0.4.3/api/child_processes.html#child_process.exec">exec</a> method from the <a href="http://nodejs.org/docs/v0.4.3/api/child_processes.html">child_process</a> module and call it. The first parameter is the command&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>NodeJS is a powerful evented Javascript platform running on top of Google&#8217;s V8 javascript engine. Over the last year the popularity of NodeJS has increased greatly, as shown by the number of discussions on programming forums such as Hacker News, Reddit and Stackoverflow. Despite this NodeJS is still young and it falls short to Python and Ruby when it comes to the number and range of libraries and modules available.</p>
<h3>The Problem</h3>
<p>I wanted to convert one of my web scraping applications I made in PHP to NodeJS. The application interacts with SOCKS4 and SOCKS5 proxies using PHP&#8217;s cURL bindings. Unfortunately there are no cURL bindings (or SOCKS protocol wrappers) written for NodeJS. NodeJS does come with an HTTP client module that can issue web requests, however it doesn&#8217;t support SOCKS proxies.</p>
<h3>The Solution</h3>
<p>Although there are no specific NodeJS bindings for cURL, we can still issue cURL requests via the command line interface. NodeJS comes with the <em>child_process</em> module which easily allows us to start processes and read their output. Doing so is fairly straight forward. We just need to import the <a href="http://nodejs.org/docs/v0.4.3/api/child_processes.html#child_process.exec">exec</a> method from the <a href="http://nodejs.org/docs/v0.4.3/api/child_processes.html">child_process</a> module and call it. The first parameter is the command we want to execute and the second is a callback function that accepts <em>error</em>, <em>stdout</em>, <em>stderr</em>.</p>
<h3>The Code</h3>
<pre>var util = require('util');
var exec = require('child_process').exec;

var command = 'curl -sL -w "%{http_code} %{time_total}\\n" "http://query7.com" -o /dev/null'

child = exec(command, function(error, stdout, stderr){

	console.log('stdout: ' + stdout);
	console.log('stderr: ' + stderr);

	if(error !== null)
	{
		console.log('exec error: ' + error);
	}

});</pre>
<p>This returns the HTTP code and time it took for the request to be issued:</p>
<pre>stdout: 200 0.710</pre>
<h3>Conclusion</h3>
<p>Although NodeJS is still young and bindings haven&#8217;t been made for alot of C libraries, the code above shows how you can still interact with the functionality they provide. That being said, the number of NodeJS modules is growing weekly. Be sure to keep an eye on the <a href="https://github.com/joyent/node/wiki/modules">module wiki</a> and <a href="http://search.npmjs.org/">npm registry</a> for a list of modules.</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/nodejs-curl-tutorial/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Titanium Mobile Android Development: First Application</title>
		<link>http://query7.com/titanium-mobile-android-development-first-application</link>
		<comments>http://query7.com/titanium-mobile-android-development-first-application#comments</comments>
		<pubDate>Mon, 28 Feb 2011 08:35:39 +0000</pubDate>
		<dc:creator>logan</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Titanium Mobile]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://query7.com/?p=1159</guid>
		<description><![CDATA[<p>In this series of tutorials we use Appcelerator’s Titanium Mobile platform to create Android applications. This tutorial walks you through developing and packaging your first Titanium application. Full source and packaged application is available on <a href="https://github.com/lastkarrde/query7rss">github</a>.</p>
<ul>
<li><a href="http://query7.com/titanium-mobile-android-development-installation">Installation &#038; setup of Titanium Mobile</a></li>
<li><a href="http://query7.com/titanium-mobile-android-development-first-application">How to make your first Android application with Titanium Mobile</a></li>
<li>]]></description>
			<content:encoded><![CDATA[<p>In this series of tutorials we use Appcelerator’s Titanium Mobile platform to create Android applications. This tutorial walks you through developing and packaging your first Titanium application. Full source and packaged application is available on <a href="https://github.com/lastkarrde/query7rss">github</a>.</p>
<ul>
<li><a href="http://query7.com/titanium-mobile-android-development-installation">Installation &#038; setup of Titanium Mobile</a></li>
<li><a href="http://query7.com/titanium-mobile-android-development-first-application">How to make your first Android application with Titanium Mobile</a></li>
<li><a href=http://query7.com/titanium-mobile-android-development-soundboard-app">How to make a Soundboard application with Titanium Mobile</a></li>
<li><a href="http://query7.com/titanium-mobile-android-development-device-information">How to make a Device Information application with Titanium Mobile</a></li>
</ul>
<h3>The Application</h3>
<p>The application itself is fairly basic but incorporates many techniques that you may need to use in your own apps. It fetches the latest 10 items off the Query7.com RSS feed and displays them in a <em>TableView</em>. If you click on one of the items Android will open the link in a web browser (<em>Internet</em>, Opera Mini, Firefox etc, whatever your default Android browser is). </p>
<p><center><img src="http://query7.com/wp-content/uploads/query7rss.jpg" alt="" title="query7rss" width="338" height="496" class="aligncenter size-full wp-image-1160" /></center></p>
<h3>The User Interface</h3>
<p>The user interface has two Titanium view elements &#8211; a <em>Window</em> and a <em>TableView</em>. After creating both views we need to call the <em>add</em> method on the instance of <em>Window</em> to ensure the <em>TableView</em> shows on the page. Doing so is fairly straight forward:</p>
<pre>Titanium.UI.setBackgroundColor('#000');

var win = Titanium.UI.createWindow({
    title:'Query7 RSS Feed',
    backgroundColor:'#000'
});

var data = [];

var tableview = Titanium.UI.createTableView({
	data:data,
	headerTitle: 'Query7 RSS',
	backgroundColor:'#000'
});

win.add(tableview);
win.open();</pre>
<h3>HTTP Requests</h3>
<p>The next step is to retrieve the RSS feed from the Query7 blog. Titanium has a very nice <a href="http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.Network.HTTPClient-object.html">HTTPClient</a> object that allows us to perform requests similar to the way we would using Ajax/JS in the web browser. We specify an <em>onload</em> method that handles the response of the request and an <em>open</em> method in which we specify the type of request (GET/POST/PUT/DELETE) and the URL we are requesting. Finally we initiate the request by calling the <em>send</em> method. </p>
<pre>var xhr = Titanium.Network.createHTTPClient();

xhr.onload = function()
{

	try
	{
		// manipulate response data here

	}
	catch(E)
	{
		alert(E);
	}

};

xhr.open('GET', 'http://feeds.feedburner.com/query7blog.rss');
xhr.send();</pre>
<h3>Parsing XML using Titanium</h3>
<p>Even though we are coding in Javascript, we are not in a web browser environment, so the usual <em>document</em> and <em>window</em> objects do not exist. This means frameworks which make XML manipulation easy, such as jQuery and Mootools, will not work. Luckily Titanium offers us the <a href="http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.XML.DOMDocument-object.html">DOMDocument</a> object, which acts and has a similar API to the web browser <em>document</em> object.</p>
<p>In the code below we can get the output of the HTTP request and automatically turn it into a <em>DOMDocument</em> object by accessing it as <em>this.responseXML.documentElement</em>. If you just wanted to get the output as plain text, you would access it by <em>this.responseText</em>. Now that the <em>DOMDocument</em> instance is set up, we do a simple XPath query to get the title and iterate over the items to get the data about the individual posts.</p>
<pre>
// manipulate response data here

var doc = this.responseXML.documentElement;
var items = doc.getElementsByTagName('item');
var doctitle = doc.evaluate("//channel/title/text()").item(0).nodeValue;

var urls = new Array();

for(var c=0; c&gt;items.length;c++)
{

	urls[c] = items.item(c).getElementsByTagName('link').item(0).text;

	postName = items.item(c).getElementsByTagName('title').item(0).text;
	postUrl = items.item(c).getElementsByTagName('link').item(0).text;

}</pre>
<h3>Populating the <em>TableView</em></h3>
<p>Now that we have the data from the RSS feed we can populate the <em>TableView</em>. To do this we create several <a href="http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.UI.TableViewRow-object.html">Titanium.UI.TableViewRow</a> objects and then append them to our <em>TableView</em>.</p>
<pre>
row = Titanium.UI.createTableViewRow({
			title: postName,
			backgroundColor:'#000',
			color: '#FF0'
		});

tableview.appendRow(row);
</pre>
<h3>Click events, Intents</h3>
<p>Now that we have data in the <em>TableView</em> we want to add functionality so that when an item in the <em>TableView</em> is clicked, the Android web browser will open to that specific post. Our code needs to listen for a click event on a <em>TableViewRow</em> and then launch a <a href="http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.Android.Intent-object.html">Titanium.Android.Intent</a>.</p>
<pre>row.addEventListener('click', function (e){

	var intent = Titanium.Android.createIntent({

			action: Titanium.Android.ACTION_VIEW,
			data: urls[e.index],

		});

	intent.addCategory(Titanium.Android.CATEGORY_BROWSABLE);
	Ti.Android.currentActivity.startActivity(intent);

});</pre>
<h3>Packaging</h3>
<p>Now all we need to do is package our application into a <em>.apk</em> file so that it can be distributed among Android devices. We need to generate a key to sign our Android app. Run the command below in the MSDOS prompt. You will be asked some additional information such as your name or country. None of it is really important unless you intend to put this app on the Android Market. Remember the <em>KEYALIASNAME</em> and password you set as Titanium requires you enter them.</p>
<pre>keytool -genkey -v -keystore <em>KEYSTORENAME</em> -alias <em>KEYALIASNAME</em> -keyalg RSA -validity 11000</pre>
<p><img src="http://query7.com/wp-content/uploads/dist.jpg" alt="" title="dist" width="540" height="495" class="aligncenter size-full wp-image-1170" /></p>
<p>After clicking package Titanium will compile your app into <em>.apk</em> format. From there you can put it on your phone&#8217;s SD card and install it. If you intend to publish an app you create onto the Android Market then be sure to give <a href="http://developer.appcelerator.com/doc/mobile/android_market">this</a> and <a href="http://developer.appcelerator.com/doc/mobile/android_market">this</a> a good read.</p>
<p>And thats it, your first Android application is now complete. Next week we will look at creating a Soundboard application using Titanium Mobile. As always if you have any comments, questions or requests for tutorials, please ask below.</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/titanium-mobile-android-development-first-application/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Getting started with Python</title>
		<link>http://query7.com/getting-started-with-python</link>
		<comments>http://query7.com/getting-started-with-python#comments</comments>
		<pubDate>Mon, 13 Dec 2010 11:24:12 +0000</pubDate>
		<dc:creator>Adit Gupta</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.webdevelopmentbits.com/?p=713</guid>
		<description><![CDATA[<div>I&#8217;ve been writing programs in Python for the past 3 years and I must accept that I am a big fan of its no-nonsense approach towards programming and it&#8217;s clean and easy to understand syntax. It was recently chosen as the <a href="http://www.activestate.com/blog/2010/11/linux-developers-choose-python-best-programming-language-and-scripting-language">best programming and scripting language by Linux Developers</a> and is also considered as the <a href="http://cdsweb.cern.ch/record/974627">Holy Grail of programming</a> by CERN. It is perhaps the <a href="http://www.reddit.com/r/programming/comments/7ax0j/is_python_the_best_first_language_to_learn_see/">best language for beginners</a> as it lets you focus on programming without worrying much about syntax.
<p>Today, Python is being extensively used at Google, Yahoo, CERN, NASA and ITA. It has been successfully embedded in a number of software products as a scripting language including Maya,MotionBuilder, SoftImage, Cinema4D, Blender, GIMP and Paint Shop Pro. Python has also been actively used for writing web applications. Some of the most sophisticated Python web frameworks include Django, Pylons, TurboGears and Web2Py.</p>
<p>In this article, I&#8217;ll provide you some resources, which will help you get started with Python:</p>
<p><a href="http://code.google.com/appengine/docs/python/gettingstarted/">Google Code: Getting Started &#8211; Python</a><br />
<a href="http://freevideolectures.com/Course/2512/Python-Programming">Python Programming Tutorials</a><br />
<a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-189-a-gentle-introduction-to-programming-using-python-january-iap-2008/">A Gentle Introduction to Programming Using Python</a><br />
<a href="http://diveintopython.org/">Dive Into Python</a><br />
<a href="http://www.openbookproject.net/thinkcs/python/english2e/">How to think like a computer scientist &#8211; Learning with Python</a></p>
<p>I hope these resources</p></div><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<div>I&#8217;ve been writing programs in Python for the past 3 years and I must accept that I am a big fan of its no-nonsense approach towards programming and it&#8217;s clean and easy to understand syntax. It was recently chosen as the <a href="http://www.activestate.com/blog/2010/11/linux-developers-choose-python-best-programming-language-and-scripting-language">best programming and scripting language by Linux Developers</a> and is also considered as the <a href="http://cdsweb.cern.ch/record/974627">Holy Grail of programming</a> by CERN. It is perhaps the <a href="http://www.reddit.com/r/programming/comments/7ax0j/is_python_the_best_first_language_to_learn_see/">best language for beginners</a> as it lets you focus on programming without worrying much about syntax.</p>
<p>Today, Python is being extensively used at Google, Yahoo, CERN, NASA and ITA. It has been successfully embedded in a number of software products as a scripting language including Maya,MotionBuilder, SoftImage, Cinema4D, Blender, GIMP and Paint Shop Pro. Python has also been actively used for writing web applications. Some of the most sophisticated Python web frameworks include Django, Pylons, TurboGears and Web2Py.</p>
<p>In this article, I&#8217;ll provide you some resources, which will help you get started with Python:</p>
<p><a href="http://code.google.com/appengine/docs/python/gettingstarted/">Google Code: Getting Started &#8211; Python</a><br />
<a href="http://freevideolectures.com/Course/2512/Python-Programming">Python Programming Tutorials</a><br />
<a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-189-a-gentle-introduction-to-programming-using-python-january-iap-2008/">A Gentle Introduction to Programming Using Python</a><br />
<a href="http://diveintopython.org/">Dive Into Python</a><br />
<a href="http://www.openbookproject.net/thinkcs/python/english2e/">How to think like a computer scientist &#8211; Learning with Python</a></p>
<p>I hope these resources will give you a hang of Python.We would be soon starting a series on web application and blog development using the Django framework. I hope you would be pretty much familiar with Python by that time! See you soon with more Python awesomeness!
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/getting-started-with-python/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scrape the First Paragraph &amp; Image from a Wikipedia Entry</title>
		<link>http://query7.com/scrape-the-first-paragraph-image-from-a-wikipedia-entry</link>
		<comments>http://query7.com/scrape-the-first-paragraph-image-from-a-wikipedia-entry#comments</comments>
		<pubDate>Mon, 26 Jul 2010 14:10:40 +0000</pubDate>
		<dc:creator>Cary F</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wikipedia]]></category>

		<guid isPermaLink="false">http://www.webdevelopmentbits.com/?p=652</guid>
		<description><![CDATA[Automate fetching Wikipedia descriptions and images for webpage content. Render content dynamically based on specific keywords.]]></description>
			<content:encoded><![CDATA[<p>by Kannan Ramakrishnan</p>
<p>One day, while you&#8217;re organizing the content for your latest and greatest website, you may find yourself wishing for an automated way to fetch a description for some of that content.  Perhaps an image, too, to pull into a header or elsewhere on your page.  And since you’ve got 100 other things on your plate, you’d like this content to be implemented automatically, dynamically appearing on certain pages based on a few keywords.  For novice Web developers, this sounds impossible, I know.  But… it’s totally doable.</p>
<p>So off you go in search of good, usable, public content.  Before long you’ll probably realize it yourself, but I’ll save you an hour of digging with this quick pro tip: Wikipedia is your friend. The bottomless content at Wikipedia is a perfect match for what we want to do.  The caveat, though, is it’s so vast we might scrape the wrong content.  And especially if you’re automating a task like this, constantly looking over your shoulder to confirm the content would defeat the entire purpose.  So relying <em>soley </em>on the Wiki gremlins is not the best way to go.</p>
<p><a href="http://query7.com/wp-content/uploads/250px-Red_Apple3.jpg"><img class="aligncenter size-full wp-image-663" title="250px-Red_Apple" src="http://query7.com/wp-content/uploads/250px-Red_Apple3.jpg" alt="" width="252" height="229" /></a></p>
<p>Let’s take for example a Wiki search for a popular technology company, say, <a href="http://www.apple.com">Apple</a>.  For a Web-savvy person like yourself, a Wiki search for ‘Apple’ turns up what you probably expect: the entry for <a href="http://en.wikipedia.org/wiki/Apple">a scrumptious kind of fruit</a>.  And as Web developers, we <em>should </em>be more astute in our search terms, but sometimes yes, well, there are those gremlins.</p>
<p>So&#8230; to cut the risk of unwanted fruit creeping onto your page, we’re going to combine a Wiki search with a Google search.</p>
<p>Following is the code for scraping the first paragraph and image of the entry from a page in Wikipedia.  As long as your keywords aren’t really crazy, this should get the job done!</p>
<p>Finally, make sure you don&#8217;t forget to credit Wikipedia on your page&#8230; and if you have any questions, <a href="mailto:webdevelopmentbits@sourcebits.com">drop us a line here</a> any time!!</p>
<p>Here&#8217;s the code:</p>
<pre>require  'hpricot'
require 'open-uri'

def fetch_description(query_item)
    page_title, uri_title = get_wiki_name(query_item)
    return get_wiki_description(page_title, uri_title)
end

def upload_photo(wiki_photo)
    begin
      base_uri = URI.parse(wiki_photo)
      uploaded_data = open(base_uri)
      def uploaded_data.original_filename; base_uri.path.split('/').last; end
      return uploaded_data.original_filename.blank? ? nil : uploaded_data
    rescue
      return nil
    end
end

#Method to fetch wiki page and strip first two

 Tags
def get_wiki_description(page_title, uri_title)
    url =  uri_title
    final_content = ""
    if url.size &gt; 10
      buffer = Hpricot(open(url, "UserAgent" =&gt; "reader"+rand(10000).to_s).read)
      #Capture first two paragraphs of text
      content = buffer.search("//div[@id='content']").search("//div[@id='bodyContent']").search("//p")[0..2]

      #Remove the extra spaces and strip html tags from the fetched content
      content.each do |c|
        final_content+=c.inner_html.gsub(/&lt; \/?[^&gt;]*&gt;/, '').gsub(/&amp;#\d+;/,'').gsub(/\([^\)]+\)/,'').gsub(/\[[^\]]+\]/,'').gsub(/ +/,' ')+"\n"
      end
    end
    return final_content
end

#Method to get the link for wikipedia from google search results
def get_wiki_name(query_item)
    search_keywords = query_item.strip.gsub(/\s+/,'+')
    url = "http://www.google.com/search?q=#{search_keywords}+site%3Aen.wikipedia.org"
    begin
      doc = Hpricot(open(url, "UserAgent" =&gt; "reader"+rand(10000).to_s).read)
      result = doc.search("//div[@id='ires']").search("//li[@class='g']").first.search("//a").first unless doc
    rescue
      return '',''
    end
    if result
      return result.inner_html.gsub(/&lt; \/?[^&gt;]*&gt;/,"").gsub(/./,""),result.attributes["href"]
    else
      return '',''
    end
end

wiki_description, wiki_photo = fetch_description("Apple")
upload_photo(wiki_photo)</pre>
<p>And this is how it looks implemented live, in context:</p>
<p><a href="http://query7.com/wp-content/uploads/smallerScreen-shot-2010-07-26-at-4.50.03-PM.png"><img class="aligncenter size-full wp-image-666" title="smallerScreen shot 2010-07-26 at 4.50.03 PM" src="http://query7.com/wp-content/uploads/smallerScreen-shot-2010-07-26-at-4.50.03-PM.png" alt="" width="500" height="245" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/scrape-the-first-paragraph-image-from-a-wikipedia-entry/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blogger Template Wizardry</title>
		<link>http://query7.com/blogger-template-wizardry</link>
		<comments>http://query7.com/blogger-template-wizardry#comments</comments>
		<pubDate>Fri, 04 Jun 2010 03:46:49 +0000</pubDate>
		<dc:creator>Chinmay Chiranjeeb</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[blogger]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[customizing]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.webdevelopmentbits.com/?p=599</guid>
		<description><![CDATA[Google’s Blogger is the eighth most popular site on the entire Web today, and by far the most popular free blogging site.  According to Google, Blogger now hosts over 300 million blogs and publishes 388 million words per day – simply staggering figures.  Let’s look at some of the more compelling reasons for Blogger’s popularity.]]></description>
			<content:encoded><![CDATA[<p>Google’s Blogger is the eighth most popular site on the entire Web today, and by far the most popular free blogging site.  According to Google, Blogger now hosts over 300 million blogs and publishes 388 million words per day – simply staggering figures.  Let’s look at some of the more compelling reasons for Blogger’s popularity.</p>
<ul>
<li>Google’s services are ubiquitous, and you’ve probably already got an account for say, Gmail, Docs, YouTube or Calendar.  So when you land on the Blogger homepage, all you need to do is enter your login info and off you go!  No registration required.</li>
<li>It’s powered by Google, so there’s a better chance of placing high on search engine rankings.  From an SEO/SEM (search engine optimization / search engine marketing) point of view, that’s quite the big deal.</li>
<li>Users can create multiple blogs.  For Web developers or designers with diverse portfolios it’s easier than ever to start your own blogging network.</li>
<li>Blogger has a limited but respectable directory of templates with plenty of options for customization.  Inveterate tweakers should clear the afternoon.</li>
<li>Users can create and configure their own templates for upload, or download an existing template, customize it, then re-upload and use it.</li>
<li>Rather than keeping the off-the-shelf yourname.blogspot.com domain, users can register their own custom domain and point their Blogger page to that.</li>
</ul>
<p>Sure enough, there are plenty of good reasons Blogger’s gained traction the past few years, but it’s become a hell of a crowded field and for anyone looking to grow their audience it’s increasingly hard to stand out.</p>
<p>The fact is, even if you’re posting killer, must-read content you’ve lost the lion’s share of readers before their first click with a page designed from a yawn-inducing Blogger template.</p>
<p>So besides great content, you’re going to want a template with distinctive design. Read on to follow this basic tutorial and create your own fresh Blogger template.</p>
<h2>Create an HTML Template for Your Blog</h2>
<p>Go to the <a href="http://www.blogger.com/">Blogger homepage</a> and log in with your Google info to create a new blog.  With or without a Google account the signup is pretty painless.</p>
<p><a href="http://query7.com/wp-content/uploads/1.png"><img class="aligncenter size-full wp-image-602" title="1" src="http://query7.com/wp-content/uploads/1.png" alt="" width="531" height="178" /></a></p>
<p>If you&#8217;re an existing user, you&#8217;ll also get the status of your current blogs.</p>
<p><a href="http://query7.com/wp-content/uploads/22.png"><img class="aligncenter size-full wp-image-618" title="2" src="http://query7.com/wp-content/uploads/22.png" alt="" width="531" height="115" /></a></p>
<h2>Head to Layout and then Edit HTML</h2>
<p><a href="http://query7.com/wp-content/uploads/3.png"><img class="aligncenter size-full wp-image-604" title="3" src="http://query7.com/wp-content/uploads/3.png" alt="" width="531" height="115" /></a></p>
<p>Developers love code, but sometimes even laymen want a peek under the hood.  If you&#8217;re up for it, just scroll down and click View Classic Template.</p>
<p>Keep in mind that Blogger can only use XML-formatted templates, so you’ll need to create a blank XML file on your hard drive as &lt;Your Template name&gt;.xml.</p>
<p>Now add the following code to your XML document:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//ES" "<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd</a>"&gt;
&lt;html xmlns='<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>' xmlns:b='<a href="http://www.google.com/2005/gml/b">http://www.google.com/2005/gml/b</a>' xmlns:data='<a href="http://www.google.com/2005/gml/data">http://www.google.com/2005/gml/data</a>' xmlns:expr='<a href="http://www.google.com/2005/gml/expr">http://www.google.com/2005/gml/expr</a>'&gt;
&lt;head&gt;</pre>
<h2>Let’s start with the Blogger code to add a header element.</h2>
<p>Generally, Blogger code starts with &lt;b:</p>
<pre>&lt;b:include data='blog' name='all-head-content'/&gt;</pre>
<h2>Now we’ll add the title of the blog and post:</h2>
<pre>&lt;title&gt;&lt;data:blog.pageTitle/&gt;&lt;/title&gt;</pre>
<h2>Referencing the blog skin:</h2>
<pre>&lt;b:skin&gt;</pre>
<h2>And template details:</h2>
<pre>&lt;![CDATA[/*
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Name: MacDevelopmentBits
Blogger template by Sourcebits Technologies
Author: Sourcebits Technologies
Author URL: <a href="http://www.sourcebits.com/">http://www.sourcebits.com</a>
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */</pre>
<h2>Now let’s hide the default navigation bar.</h2>
<p><a href="http://query7.com/wp-content/uploads/5.png"><img class="aligncenter size-full wp-image-606" title="5" src="http://query7.com/wp-content/uploads/5.png" alt="" width="531" height="31" /></a></p>
<pre>/*-- (Hiding the navbar) --*/
#navbar-iframe {
height:0px;
visibility:hidden;
display:none;
}</pre>
<h2>And add some custom CSS to stylize the blog.</h2>
<pre>/*-- (CSS for Blog ) --*/
body{
font-family:Georgia, "Times New Roman", Times, serif;
font-size:12px;
color:#000000;
margin:0px;
padding:0px;
background:#dedede;
}

:focus {
outline: 0;
}

.clr{
clear:both;
}

.wrap{
margin:0 auto;
padding:0px;
min-width:1200px;
}

.head{
background:#cde3e4 url(your path to header image) repeat-x;
margin-top:-1px;
}

]]&gt;&lt;/b:skin&gt;</pre>
<p>If you don&#8217;t have a domain to host images then you can use Picasa, Flickr or any other image hosting services.  Just make sure that image viewing permissions are set to public.</p>
<h2>To generate feeds and archives for your blog:</h2>
<pre>&lt;script type='text/javascript'&gt;

function rp(json){ document.write(&amp;#39;&amp;lt;ul&amp;gt;&amp;#39;);for(var i=0;i&amp;lt;numposts;i++){document.write(&amp;#39;&amp;lt;li&amp;gt;&amp;#39;);var entry=json.feed.entry[i];var posttitle=entry.title.$t;var posturl;if(i==json.feed.entry.length)break;for(var k=0;k&amp;lt;entry.link.length;k++){if(entry.link[k].rel==&amp;#39;alternate&amp;#39;){posturl=entry.link[k].href;break}}posttitle=posttitle.link(posturl);var readmorelink=&amp;quot;(more)&amp;quot;;readmorelink=readmorelink.link(posturl);var postdate=entry.published.$t;var cdyear=postdate.substring(0,4);var cdmonth=postdate.substring(5,7);var cdday=postdate.substring(8,10);var monthnames=new Array();monthnames[1]=&amp;quot;Jan&amp;quot;;monthnames[2]=&amp;quot;Feb&amp;quot;;monthnames[3]=&amp;quot;Mar&amp;quot;;monthnames[4]=&amp;quot;Apr&amp;quot;;monthnames[5]=&amp;quot;May&amp;quot;;monthnames[6]=&amp;quot;Jun&amp;quot;;monthnames[7]=&amp;quot;Jul&amp;quot;;monthnames[8]=&amp;quot;Aug&amp;quot;;monthnames[9]=&amp;quot;Sep&amp;quot;;monthnames[10]=&amp;quot;Oct&amp;quot;;monthnames[11]=&amp;quot;Nov&amp;quot;;monthnames[12]=&amp;quot;Dec&amp;quot;;if(&amp;quot;content&amp;quot;in entry){var postcontent=entry.content.$t}else if(&amp;quot;summary&amp;quot;in entry){var postcontent=entry.summary.$t}else var postcontent=&amp;quot;&amp;quot;;var re=/&amp;lt;\S[^&amp;gt;]*&amp;gt;/g;postcontent=postcontent.replace(re,&amp;quot;&amp;quot;);document.write(posttitle);if(showpostdate==true)document.write(&amp;#39; - &amp;#39;+monthnames[parseInt(cdmonth,10)]+&amp;#39; &amp;#39;+cdday);if(showpostsummary==true){if(postcontent.length&amp;lt;numchars){document.write(postcontent)}else{postcontent=postcontent.substring(0,numchars);var quoteEnd=postcontent.lastIndexOf(&amp;quot; &amp;quot;);postcontent=postcontent.substring(0,quoteEnd);document.write(postcontent+&amp;#39;...&amp;#39;+readmorelink)}}document.write(&amp;#39;&amp;lt;/li&amp;gt;&amp;#39;)}document.write(&amp;#39;&amp;lt;/ul&amp;gt;&amp;#39;)}

var numposts = 5;
var showpostdate = false;
var showpostsummary = false;
var numchars = 40;

&lt;/script&gt;</pre>
<h2>You can also insert external JavaScript files:</h2>
<pre>&lt;script language='javascript' src='<a href="http://code.jquery.com/jquery-1.4.2.min.js">http://code.jquery.com/jquery-1.4.2.min.js</a>' type='text/javascript'/&gt;
&lt;script type='text/javascript'&gt;
//your code here
&lt;/script&gt;</pre>
<h2>Now let’s replace the default Blogger favicon with a custom jobbie that suits our taste.</h2>
<pre>&lt;link href='path to favicon' rel='shortcut icon' type='favicon'/&gt;
&lt;/head&gt;
&lt;body&gt;</pre>
<h2>Include your HTML code from the blog template created earlier and let’s add a widget to your header.</h2>
<pre>&lt;b:section id='top35' maxwidgets='1' showaddelement='no'&gt;
&lt;b:widget id='Header1' locked='true' title='MacDevelopmentBits (Header)' type='Header'&gt;

&lt;b:includable id='title'&gt;
&lt;A expr:href='data:blog.homepageUrl'&gt;&lt;div class='logo'&gt;&lt;data:title/&gt;&lt;/div&gt;&lt;/A&gt;
&lt;/b:includable&gt;

&lt;b:includable id='description'&gt;
&lt;h1 class='slogan'&gt;&lt;data:description/&gt;&lt;/h1&gt; &lt;!-- It fetches the description from basic settings page. --&gt;
&lt;/b:includable&gt;

&lt;b:includable id='main'&gt;
&lt;div class='slogan1'&gt;
&lt;b:include name='title'/&gt;
&lt;/div&gt;
&lt;b:include name='description'/&gt;
&lt;/b:includable&gt;

&lt;/b:widget&gt;
&lt;/b:section&gt;</pre>
<p>Note that you can use multiple widgets in the template but they should have unique id= &#8216;Your Unique ID&#8217; and maxwidgets=&#8217;No of widgets&#8217;</p>
<h2>Now add navigation:</h2>
<pre>&lt;b:include name='nextprev'/&gt;</pre>
<p>And the conditional statement to show/hide navigation is:</p>
<pre>&lt;b:if cond='data:newerPageUrl'&gt;

&lt;span id='blog-pager-newer-link'&gt;
&lt;a class='blog-pager-newer-link' expr:href='data:newerPageUrl' expr:id='data:widget.instanceId + &amp;quot;_blog-pager-newer-link&amp;quot;' expr:title='data:newerPageTitle'&gt;&lt;data:newerPageTitle/&gt;&lt;/a&gt;
&lt;/span&gt;

&lt;/b:if&gt;
&lt;b:if cond='data:olderPageUrl'&gt;
&lt;span id='blog-pager-older-link'&gt;
&lt;a class='blog-pager-older-link' expr:href='data:olderPageUrl' expr:id='data:widget.instanceId + &amp;quot;_blog-pager-older-link&amp;quot;' expr:title='data:olderPageTitle'&gt;&lt;data:olderPageTitle/&gt;&lt;/a&gt;
&lt;/span&gt;

&lt;/b:if&gt;</pre>
<h2>And include feed links:</h2>
<pre>&lt;b:include name='feedLinks'/&gt;</pre>
<h2>To display content only on the main and archive pages, include this tag with your content:</h2>
<pre>&lt;MainOrArchivePage&gt;
&lt;1-- Your Content for Home and Archive Page--&gt;
&lt;/MainOrArchivePage&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h2>Phew!  Almost there.  Now after saving the XML file, it’s time to upload to Blogger.</h2>
<p>Back on the Layout tab, under Edit HTML, you’ll find:</p>
<p><a href="http://query7.com/wp-content/uploads/6.png"><img class="aligncenter size-full wp-image-607" title="6" src="http://query7.com/wp-content/uploads/6.png" alt="" width="533" height="33" /></a></p>
<p>After uploading, save the template so now you can edit the file online and preview changes as you go.</p>
<p><a href="http://query7.com/wp-content/uploads/7.png"><img class="aligncenter size-full wp-image-608" title="7" src="http://query7.com/wp-content/uploads/7.png" alt="" width="533" height="45" /></a></p>
<p>And feel free to experiment!  You can always hit the <strong>Clear Edits</strong> button to revert to the last saved version.</p>
<p>Let&#8217;s take a look at an outline of the page elements used in the template:</p>
<p><a href="http://query7.com/wp-content/uploads/8.png"><img class="aligncenter size-full wp-image-609" title="8" src="http://query7.com/wp-content/uploads/8.png" alt="" width="531" height="115" /></a></p>
<p>We can also place widgets with just a few clicks.</p>
<p><a href="http://query7.com/wp-content/uploads/4.png"><img class="aligncenter size-full wp-image-605" title="4" src="http://query7.com/wp-content/uploads/4.png" alt="" width="531" height="178" /></a></p>
<p>Clicking one of the Add a Gadget links drops you into a vast pool of Blogger and third party gadgets. Pick a gadget and add it by clicking the +, however many suit your needs.</p>
<p><a href="http://query7.com/wp-content/uploads/9.png"><img class="aligncenter size-full wp-image-610" title="9" src="http://query7.com/wp-content/uploads/9.png" alt="" width="533" height="180" /></a></p>
<p>And&#8230; VOILA!</p>
<p>Here’s a sample template we did up awhile ago with a basic but unique design, just FYI.</p>
<p style="text-align: center;"><a href="http://macdevelopmentbits.blogspot.com/"><img class="aligncenter size-full wp-image-611" title="10" src="http://query7.com/wp-content/uploads/10.png" alt="" width="531" height="178" /></a></p>
<p><a href="http://macdevelopmentbits.blogspot.com/">http://macdevelopmentbits.blogspot.com/</a></p>
<p>Feel free to drop us a line with any of your Blogger templating issues.  We&#8217;re happy to lend a hand. For that matter, we&#8217;re keen to discuss any Web development projects you&#8217;re interested in.  <a href="http://www.webdevelopmentbits.com/contact">Get in touch</a> any time!</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/blogger-template-wizardry/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML Email Compatibility Across Mail Clients</title>
		<link>http://query7.com/html-email-compatibility-across-mail-clients</link>
		<comments>http://query7.com/html-email-compatibility-across-mail-clients#comments</comments>
		<pubDate>Mon, 17 May 2010 00:29:25 +0000</pubDate>
		<dc:creator>Prakash Mohanty</dc:creator>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Mail]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS Table]]></category>
		<category><![CDATA[HTML mail]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://www.webdevelopmentbits.com/?p=573</guid>
		<description><![CDATA[<p style="text-align: center;"><a href="http://query7.com/wp-content/uploads/Screen-shot-2010-05-17-at-9.20.44-PM.png"><img class="size-full wp-image-578  aligncenter" title="Screen shot 2010-05-17 at 9.20.44 PM" src="http://query7.com/wp-content/uploads/Screen-shot-2010-05-17-at-9.20.44-PM.png" alt="" width="530" height="181" /></a></p>
<p>Lots of compatibility issues occur when HTML developers deal with HTML-formatted emails generated using server side languages like PHP, PERL, JAVA, etc. in their projects.</p>
<p>From time to time you’ll find the odd gobbledygooked message in your Web-based email app, but generally speaking HTML-formatted messages render flawlessly on the Web.  On the other hand, desktop mail clients such as Outlook on Windows, Mail.app on OS X, and the rainbow flavors of desktop Linux (Ubuntu, Centos, and so on) routinely have rendering issues with HTML-based email.</p>
<p>Despite the incredible advances in modern software, why does this continue to happen?</p>
<p>The answer is quite simple: certain mail clients ignore certain HTML tags.  Now there’s no universal rule as to which ignores what, but the more you code the more you’ll learn, so for now let’s take a look at one case with Outlook.</p>
<p>For many users, email ‘stationery’ conjures up late 90s memories of <a href="http://www.incredimail.com/english/splash.aspx">Incredimail</a> and a general, unsavory n00bishness.  But for marketing purposes a well-designed mail template, consisting of a stylish background image, thoughtful font selection, layout and copy equates to sales.  Perhaps thousands of people – from prospective clients to the media – will view mail&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://query7.com/wp-content/uploads/Screen-shot-2010-05-17-at-9.20.44-PM.png"><img class="size-full wp-image-578  aligncenter" title="Screen shot 2010-05-17 at 9.20.44 PM" src="http://query7.com/wp-content/uploads/Screen-shot-2010-05-17-at-9.20.44-PM.png" alt="" width="530" height="181" /></a></p>
<p>Lots of compatibility issues occur when HTML developers deal with HTML-formatted emails generated using server side languages like PHP, PERL, JAVA, etc. in their projects.</p>
<p>From time to time you’ll find the odd gobbledygooked message in your Web-based email app, but generally speaking HTML-formatted messages render flawlessly on the Web.  On the other hand, desktop mail clients such as Outlook on Windows, Mail.app on OS X, and the rainbow flavors of desktop Linux (Ubuntu, Centos, and so on) routinely have rendering issues with HTML-based email.</p>
<p>Despite the incredible advances in modern software, why does this continue to happen?</p>
<p>The answer is quite simple: certain mail clients ignore certain HTML tags.  Now there’s no universal rule as to which ignores what, but the more you code the more you’ll learn, so for now let’s take a look at one case with Outlook.</p>
<p>For many users, email ‘stationery’ conjures up late 90s memories of <a href="http://www.incredimail.com/english/splash.aspx">Incredimail</a> and a general, unsavory n00bishness.  But for marketing purposes a well-designed mail template, consisting of a stylish background image, thoughtful font selection, layout and copy equates to sales.  Perhaps thousands of people – from prospective clients to the media – will view mail on this template and associate it with your corporate brand, so perfection is key.</p>
<p style="text-align: center;"><img class="size-medium wp-image-579   aligncenter" title="Ye Gods!!  Incredimail!!! " src="http://www.webdevelopmentbits.com/wp-content/uploads/2010/05/back1-300x240.gif" alt="" width="248" height="199" /></p>
<p style="text-align: left;">Now let’s focus on the background image.  Many HTML developers will begin by putting CSS styles in the header of the HTML email directly, or when that fails try working around the problem using div tags and inline CSS.  But either way the results are borked.  Why?  Because Outlook ignores the CSS property “background-image”.</p>
<p style="text-align: left;">After so much trial and error, the solution we finally decided on was a pure table-based layout with inline CSS – with the CSS being restricted to each individual table cell since Outlook does not ignore those.  We’ve found this not only renders properly in Outlook, but all the other major desktop and Web clients, too.</p>
<p>And here&#8217;s how good it can look.</p>
<p style="text-align: center;"><a href="http://query7.com/wp-content/uploads/Image-xbox.png"><img class="size-full wp-image-580  aligncenter" title="Image-xbox" src="http://query7.com/wp-content/uploads/Image-xbox.png" alt="" width="539" height="746" /></a></p>
<p>For your reference, here are few examples of HTML tags that are compatible with almost all desktop and Web-based mail clients.</p>
<pre>&lt;table cellspacing="0" cellpadding="0" bgcolor="#6b6f7a"&gt;
    &lt;tr&gt;
        &lt;td width="55" height="53" valign="top"&gt;
            &lt;img src="http://domainname/media/mail/header_01.jpg" alt="" width="78" height="53" /&gt;
        &lt;/td&gt;
        &lt;td style="font-family: Arial,sans-serif;" width="546" bgcolor="#ffffff"&gt;&lt;/td&gt;
        &lt;td style="border-bottom: 1px solid #ffffff; padding: 0pt 15px; background-color: #b6d354; color: #ffffff; text-transform: uppercase; height: 43px; vertical-align: middle; font-size: 12px;"&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;</pre>
<p>CSS style property -</p>
<pre>word-wrap: break-all;</pre>
<p>With the absence of a background tag, images can be used inside the</p>
<pre>&lt;table&gt;</pre>
<p>and</p>
<pre>&lt;td&gt;</pre>
<p>tags.</p>
<p>Happy HTML email  coding!!</p>
]]></content:encoded>
			<wfw:commentRss>http://query7.com/html-email-compatibility-across-mail-clients/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

