<?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:admin="http://webns.net/mvcb/"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"	
	>

    	<channel>
    
    	<title>Evan Black&#039;s Blog</title>
    	<link>http://www.evanblack.com/blog/</link>
    	<description>The Blog of Evan Black, a web designer and developer from Indianapolis, IN.</description>
    	<dc:language>en</dc:language>
    	<dc:creator>evanmblack@gmail.com</dc:creator>
    	<dc:rights>Copyright 2011</dc:rights>
    	<dc:date>2011-06-14T17:44:05+00:00</dc:date>
    	<admin:generatorAgent rdf:resource="http://expressionengine.com/" />
    	<atom:link href="http://www.evanblack.com/blog/feed" rel="self" type="application/rss+xml" />


    	<item>
      		<title>Introducing Poncho: a simple weather app for Android and iPhone</title>
      		<link>http://www.evanblack.com/blog/introducing-poncho-a-simple-weather-app-for-android-and-iphone/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/introducing-poncho-a-simple-weather-app-for-android-and-iphone/#comments</comments>
      		<pubDate>Tue, 14 Jun 2011 17:44:05 -0700</pubDate>
      		<guid>http://www.evanblack.com/blog/introducing-poncho-a-simple-weather-app-for-android-and-iphone/#When:17:44:05</guid>
      		<description>Poncho is a dead simple mobile web app for viewing current and next&#45;day weather conditions. It works on Android and iOS, although it&#8217;s tailored for non&#45;tablet smartphone devices like Android phones, iPhone and iPod Touch. It&#8217;s a mobile web app instead of a native app, so it may work on even more platforms, but I haven&#8217;t tested it on anything else. If you go to app.getponcho.com on your device&#8217;s browser, you can bookmark and/or add the app to your homescreen and run it virtually just like a native app.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/introducing-poncho-a-simple-weather-app-for-android-and-iphone/"><img src="/images/sized/uploads/images/preview-280x190.jpg" width="280" height="190"  alt="Introducing Poncho: a simple weather app for Android and iPhone" /></a><p><a href="http://app.getponcho.com/" title="Poncho Weather App">Poncho</a> is a dead simple mobile web app for viewing current and next-day weather conditions. It works on Android and iOS, although it's tailored for non-tablet smartphone devices like Android phones, iPhone and iPod Touch. It's a mobile web app instead of a native app, so it may work on even more platforms, but I haven't tested it on anything else. If you go to <a href="http://app.getponcho.com/" title="Poncho Weather App">app.getponcho.com</a> on your device's browser, you can bookmark and/or add the app to your homescreen and run it virtually just like a native app.</p>
<p><a href="http://app.getponcho.com/" title="Poncho Weather App"><img alt="Add to Homescreen on iOS and Android" height="450" src="/uploads/images/add-app-to-homescreen.jpg" width="600" /></a></p>
<p>Poncho basically consists of 2 simple views: a weather tab and a locations tab. The app will automatically detect your location (if you allow it to) and you can add other locations just by entering a zip code, city or place name into the input on the locations tab. View the weather for any of your locations just by tapping on the location. On the weather tab there's also a radar button that will take you to a weather radar integrated with Google Maps.</p>
<h4>Background and Tech</h4>
<p>For obvious reasons I've been hugely interested in mobile development for the last year or so. Between that and all kinds of new UI frameworks and tools springing up on an almost weekly - if not daily - basis, I wanted to jump head first into developing something for mobile platforms.</p>
<p>Poncho runs mainly on <a href="http://maccman.github.com/spine/" title="Spine MVC">Spine</a>, a lightweight MVC javascript framework for building web applications. Instead of the bloated jQuery, it uses the more lightweight and mobile-geared <a href="http://zeptojs.com/" title="Zepto Framework">Zepto framework</a>. Since I'm using <a href="http://developer.yahoo.com/yql/" title="Yahoo Query Language">YQL</a> (Yahoo Query Language) as my weather API and HTML5 LocalStorage to store the user's locations, I needed to choose a javascript templating language as an efficient way to display the data. I chose <a href="http://mustache.github.com/" title="Mustache Javascript Templates">Mustache</a> for my Javascript templates for it's small size and efficient rendering.</p>
<p>I'm hosting Poncho on Google App Engine and have used <a href="http://remysharp.com/" title="Remy Sharp">Remy Sharp's</a> awesome <a href="https://github.com/remy/inliner" title="Inliner">Inliner tool</a> to inline all the HTML, CSS, Javascript and Images into 1 file. Since the main goal of the project was a learning experience and building an app that I myself would enjoy using, I've open sourced the project on <a href="https://github.com/evanblack/spine.weather" title="Poncho on GitHub">GitHub</a>. If you're trying the app out and having any problems or notice any bugs, please <a href="https://github.com/evanblack/spine.weather/issues" title="File a bug for Poncho">create an issue</a></p>
<h4>Plans</h4>
<p>I'm starting to put together some features and additions I want to make to Poncho, including adding a landscape orientation view. I'm also considering packaging and bundling the project using PhoneGap so that it could possibly be distributed through the Android market.</p>
<p>Note: Poncho's weather icons are the awesome Mobydock <a href="http://voogee.deviantart.com/art/Grzanka-s-Icons-nr-2-44204272" title="Weather Icons">icons by Wojciech Grzanka</a></p>]]></content:encoded>
      		<dc:subject>Design, Development</dc:subject>
      		<dc:date>2011-06-14T17:44:05+00:00</dc:date>
    	</item>

    	<item>
      		<title>Touch &#8220;slide to unlock&#8221; in Mobile Safari</title>
      		<link>http://www.evanblack.com/blog/touch-slide-to-unlock/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/touch-slide-to-unlock/#comments</comments>
      		<pubDate>Tue, 17 Aug 2010 01:08:50 -0700</pubDate>
      		<guid>http://www.evanblack.com/blog/touch-slide-to-unlock/#When:01:08:50</guid>
      		<description>I've been reading a bit about implementing touch interfaces recently at work. I didn't realize that, for the most part, it's as easy as attaching Javascript touch events to DOM elements - just like you would with any other events in Javascript. The other thing that is a major help with Mobile Safari development is using the new CSS3 properties for animations and such. Thankfully, since you're primarily tagerting Mobile Safari/Webkit, you don't need to worry too much about&#8230;</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/touch-slide-to-unlock/"><img src="/images/sized/uploads/images/blog_slide-unlock-280x190.jpg" width="280" height="190"  alt="Touch &#8220;slide to unlock&#8221; in Mobile Safari" /></a><p>I've been reading a bit about implementing touch interfaces recently at work. I didn't realize that, for the most part, it's as easy as attaching Javascript touch events to DOM elements - just like you would with any other events in Javascript. The other thing that is a major help with Mobile Safari development is using the new CSS3 properties for animations and such. Thankfully, since you're primarily tagerting Mobile Safari/Webkit, you don't need to worry too much about cross-browser issues.</p>
<p>Last week, <a href="http://chriscoyier.net/" title="Chris Coyier">Chris Coyier</a> wrote an article over on <a href="http://css-tricks.com/" title="CSS Tricks">CSS Tricks</a> about recreating the <a href="http://css-tricks.com/slide-to-unlock/" title="iphone slide to unlock text in Webkit/CSS3">iphone "slide to unlock" text in Webkit/CSS3</a>. I thought this would be a perfect opportunity to play around and take it one step further to add touch support for iphone and ipad (again, just as an experiment).</p>
<h4>The Result</h4>
<p>Check out the finished <a href="/touch-test/">demo on ipad, iphone or ipod touch</a>.</p>
<h4>The Markup</h4>
<p>The markup is pretty much the same as Chris'. I DID add an <strong>id</strong> to the arrow slider so that my Javascript would have a DOM hookup.</p>
<pre class="brush: html;"><div id="page-wrap">
	<div id="well">
		<h2><img alt="slider" id="slider" src="/my-admin/arrow.png" /> <span>slide to unlock</span></h2>
	</div>
</div>
</pre>
<h4>The CSS</h4>
<p>I copied pretty much all of Chris' CSS as well. I did however remove some of the work he did to get the cool animated text highlight since it was messing with some of the Webkit animations I added (and it wasn't really the goal of my experiment). Here is the CSS I've added:</p>
<pre class="brush: css;">#well {
	-webkit-transition: opacity 0.4s ease-out;
}
</pre>
<p>This takes care of the fade out animation once you've slid it far enough to unlock. Technically, we'll handle the slide back animation for when you haven't slid the slider far enough in CSS as well, but we'll get to that in the Javascript part.</p>
<p>Here's my final combined CSS:</p>
<pre class="brush: css;">/*
	 CSS-Tricks Example
	 by Chris Coyier
	 http://css-tricks.com
*/

* { margin: 0; padding: 0; }
html { background: black; }
body { 
	font: 14px Georgia, serif; 
	background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #3b3b3b),color-stop(1, #000000));
	background-repeat: no-repeat;
	min-height: 350px;
	color:#fff;
}
#page-wrap { width: 720px; margin: 0 auto; padding-top: 100px; }

#well {
	padding: 14px 20px 20px 20px;
	-webkit-border-radius: 30px;
	-moz-border-radius: 30px;
	border-radius: 30px;
	
	background: -moz-linear-gradient(top, #010101, #181818);
	background: -webkit-gradient(linear,left top,left bottom,color-stop(0, #010101),color-stop(1, #181818));
	
	border: 2px solid #454545; 
	overflow: hidden;
	
	-webkit-transition: opacity 0.4s ease-out;
}

h2 {
  background: -moz-linear-gradient(left, #4d4d4d, 0.4, #4d4d4d, 0.5, white, 0.6, #4d4d4d, #4d4d4d); 
  background: -webkit-gradient(linear,left top,right top,color-stop(0, #4d4d4d),color-stop(0.4, #4d4d4d),color-stop(0.5, white),color-stop(0.6, #4d4d4d),color-stop(1, #4d4d4d)); 
  
  -moz-background-clip: text;
  -webkit-background-clip: text;
/*  
  -moz-text-fill-color: transparent;
  -webkit-text-fill-color: transparent;
*/  
  -webkit-animation: slidetounlock 5s infinite;
  
  font-size: 80px;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  font-weight: 300;
  
  padding: 0;
  width: 200%;
}

h2 img {
	vertical-align: middle; 
}
</pre>
<h4>Javascript Fun</h4>
<p>Now for the Javascript fun:</p>
<pre class="brush: js;">function $(id){ return document.getElementById(id); }

$('slider').addEventListener('touchmove', function(event) {
    event.preventDefault();
    var el = event.target;
    var touch = event.touches[0];
    curX = touch.pageX - this.offsetLeft - 73;
    if(curX &lt;= 0) return;
    if(curX &gt; 550){
    	$('well').style.opacity = 0;
    }
   	el.style.webkitTransform = 'translateX(' + curX + 'px)'; 
}, false);

$('slider').addEventListener('touchend', function(event) {	
    this.style.webkitTransition = '-webkit-transform 0.3s ease-in';
    this.addEventListener( 'webkitTransitionEnd', function( event ) { this.style.webkitTransition = 'none'; }, false );
    this.style.webkitTransform = 'translateX(0px)';
}, false);
</pre>
<p>To capture touch events in Webkit, you'll mostly be working with the <strong>touchstart</strong>, <strong>touchmove</strong> and <strong>touchend</strong> events. After attaching the Javascript touch events, we just have to position the slider button based on the page coordinates of your finger, and trigger our CSS3 animations. I've offset the x-axis position an additional 73px (half of our slider image) to position the touch point for the slider in the middle of the image.</p>
<p>We only neeed to worry about the movement along the x-axis, so we use the <strong>translateX</strong> function with the <strong>-webkit-transform</strong> property. The nice thing about Safari is that it will <a href="http://developer.apple.com/safari/library/documentation/internetweb/conceptual/safarivisualeffectsprogguide/Transitions/Transitions.html#//apple_ref/doc/uid/TP40008032-CH4-SW1">trigger animations automatically</a> when your declared properties are changed - in this case "opacity". These implicit animations also <a href="http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariCSSRef/Introduction.html#//apple_ref/doc/uid/TP40002050">only apply to certain properties</a>.</p>
<p>To get the button to slide back to the starting position when the user releases their finger, we use the touchend event to add the <strong>-webkit-transition</strong> property to our button. Unfortunately, to avoid funkiness from conflicting events, we need to programmatically apply and remove the transition in the touchend event. We do this by attaching a <strong>webkitTransitionEnd</strong> event to the object and then setting the CSS property to "none".</p>
<h4>Conclusion</h4>
<p>This was a fun little experiment to get started using Mobile Safari's touch capabilities. Currently, I've only gotten this working on iphone, ipod touch and ipad. I may play around with trying to get it to work on Android, so if anyone has any suggestions please let me know.</p>]]></content:encoded>
      		<dc:subject>Development</dc:subject>
      		<dc:date>2010-08-17T01:08:50+00:00</dc:date>
    	</item>

    	<item>
      		<title>An Experiment in HTML5 and CSS3</title>
      		<link>http://www.evanblack.com/blog/an-experiment-in-html5-and-css3/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/an-experiment-in-html5-and-css3/#comments</comments>
      		<pubDate>Fri, 07 May 2010 02:29:59 -0700</pubDate>
      		<guid>http://www.evanblack.com/blog/an-experiment-in-html5-and-css3/#When:02:29:59</guid>
      		<description>A couple months ago I decided it was about time that I jumped on the HTML5 bandwagon. I really hadn't had any real world experience building anything in HTML5, and had only used a few CSS3 properties as progressive enhancements. I really wanted to take some time to design and build something awesome - without having to worry about the elephant in the room, *cough* Internet Explorer *cough*. Unfortunately, I didn't have a whole lot of unique content laying around that could be&#8230;</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/an-experiment-in-html5-and-css3/"><img src="/images/sized/uploads/images/blog_sweetcron-280x190.jpg" width="280" height="190"  alt="An Experiment in HTML5 and CSS3" /></a><p>A couple months ago I decided it was about time that I jumped on the HTML5 bandwagon. I really hadn't had any real world experience building anything in HTML5, and had only used a few CSS3 properties as progressive enhancements. I really wanted to take some time to design and build something awesome - without having to worry about the elephant in the room, *cough* Internet Explorer *cough*.</p>
<p>Unfortunately, I didn't have a whole lot of unique content laying around that could be the foundation for my site, so I decided to go the <a href="http://en.wikipedia.org/wiki/Lifestreaming" title="Lifestream">Lifestream</a> route. I also decided to build the site with Yong Fook's <a href="http://code.google.com/p/sweetcron/" title="Sweetcron">SweetCron</a>&nbsp;platform, which is built on my favorite php framework, CodeIgniter. It aggregates feeds from this blog, my Twitter, Delicious, Last.fm, Flickr and YouTube accounts. But enough about the boring backend details, let's move onto the new and exciting things.</p>
<h4>The Result</h4>
<p>You can see the final result of my HTML5 and CSS3 experiment at <a href="http://me.evanblack.com/" title="Evan's Mashup">me.evanblack.com</a>. Make sure to check it out in any GOOD browser, like Firefox, Safari or Chrome.</p>
<p><a href="http://me.evanblack.com/" title="Evan's Lifestream"><img alt="Lifestream Preview" height="400" src="/uploads/images/blog_lifestream_site_preview.jpg" width="600" /></a></p>
<h4>HTML5</h4>
<p>If you take a look at the source code, you should notice how clean it is. HTML5 is a semantic wet dream. Pretty much every element, from &lt;<strong>nav&gt;</strong>&nbsp;to &lt;<strong>header&gt;</strong>&nbsp;to &lt;<strong>article&gt;,&nbsp;</strong>has a semantic meaning. This, coupled with some <a href="http://www.456bereastreet.com/archive/200601/css_3_selectors_explained/" title="Advanced CSS3 Selectors">advanced CSS3 selectors</a>, means you hardly ever need to use IDs or even classes! I think the hardest thing to get used to is the fact that not only is your page going to have a header and footer structure, but so is each article within your section.</p>
<p>If you're looking to read more about the new structural elements in HTML5, I'd recommend reading Steve Smith's article on <a href="http://orderedlist.com/our-writing/resources/html-css/structural-tags-in-html5/" title="Structural Tags in HTML5">Structural Tags in HTML5</a>. Unfortunately, I didn't get the chance to do too much experimenting with the new <strong>&lt;video&gt;</strong>, <strong>&lt;audio&gt;</strong> and <strong>&lt;canvas&gt; </strong>elements, or with the new <a href="http://24ways.org/2009/have-a-field-day-with-html5-forms" title="HTML5 Form Features">form features</a>, but these are sure to make HTML5 even more robust once the spec is approved.</p>
<p><strong>Note:</strong> Once the W3C agrees on a standard video format for the  <strong>&lt;video&gt;</strong>&nbsp;element  (my guess is h.264),&nbsp;and browser vendors get it implemented, it will make this element much more widely used because of iPhones and iPod Touches.</p>
<h4>Design and CSS3</h4>
<p>The main CSS3 features I implemented - aside from the usual border radius and text shadow properties - were <strong>@font-family</strong>, <strong>rgba</strong>, <strong>box-shadow</strong> and <strong>CSS gradients</strong>. I've used Yanone's awesome free font, <a href="http://www.yanone.de/typedesign/kaffeesatz/" title="Yanone Kaffeesatz">Yanone Kaffeesatz</a>, via @font-family for all the headlines. I also played around with a combination of border radius, rgba and CSS gradients for the navigation tabs, which I think turned out pretty well. I even tried to do some CSS transform magic for the tab animation, but alas, I had to resort to Javascript. Be sure to check out the <a href="http://me.evanblack.com/system/application/views/themes/eb/layout.css" title="CSS">CSS</a>&nbsp;to take a closer look at how I put some of the new CSS3 features to work.</p>
<h4>Javascript Finishing Touches (jQuery of Course!)</h4>
<p>For some finishing touches I added a bit of jQuery magic to handle the navigation tab animation, the endless scrolling, and thus needed 'back to top' link. There's also some other javascript to help bitch-slap IE into submission, although I haven't really done much testing to see how the site's looking in it. IE8, at the very least, should not completely crash.</p>
<h4>Conclusion</h4>
<p>Please take a look at the <a href="http://me.evanblack.com/">final result</a>&nbsp;and let me know what you think! Unfortunately, there's a lot of twitter content right now, so be sure to check out the different categories to see the alternate post designs. Building this thing was quite a learning experience and it's nice to see front-end development going in a good direction.</p>
<p>I'll also be adapting this baby into a Tumblr theme so stay tuned for that!</p>]]></content:encoded>
      		<dc:subject>Design, Development</dc:subject>
      		<dc:date>2010-05-07T02:29:59+00:00</dc:date>
    	</item>

    	<item>
      		<title>It&#8217;s Been a While&#8230;</title>
      		<link>http://www.evanblack.com/blog/its-been-a-while/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/its-been-a-while/#comments</comments>
      		<pubDate>Mon, 03 May 2010 23:28:38 -0700</pubDate>
      		<guid>http://www.evanblack.com/blog/its-been-a-while/#When:23:28:38</guid>
      		<description>After my last post admitting that I had neglected to keep my previous personal site up to date, I&#8217;m a little embarrassed to say that I haven&#8217;t made an update to this site since it&#8217;s launch. Mostly the reason was because of a major career move, but I am now determined to dedicate my time and effort to this site and other personal projects.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/its-been-a-while/"><img src="/images/sized/uploads/images/blog_dk-280x190.jpg" width="280" height="190"  alt="It&#8217;s Been a While&#8230;" /></a><p>After my last post admitting that I had neglected to keep my previous personal site up to date, I'm a little embarrassed to say that I haven't made an update to this site since it's launch. Mostly the reason was because of a major career move, but I am now determined to dedicate my time and effort to this site and other personal projects.</p>
<p>Back in February I accepted an offer to join the <abbr title="User Interface">UI</abbr> team at <a href="http://designkitchen.com/" title="Designkitchen">Designkitchen</a> as a Front-end Developer. This meant I'd be moving from Indianapolis 3 hours north to Chicago, and rather suddenly (within a week). Since then I've been busy with a couple of big projects at work, but have also been working on a couple of other projects on my own. I'll be posting some updates about these projects later on this week or next week, so stay tuned!</p>]]></content:encoded>
      		<dc:subject>Notes</dc:subject>
      		<dc:date>2010-05-03T23:28:38+00:00</dc:date>
    	</item>

    	<item>
      		<title>New Year, New Site</title>
      		<link>http://www.evanblack.com/blog/new-year-new-site/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/new-year-new-site/#comments</comments>
      		<pubDate>Wed, 06 Jan 2010 22:44:07 -0800</pubDate>
      		<guid>http://www.evanblack.com/blog/new-year-new-site/#When:22:44:07</guid>
      		<description>Five months ago when I decided to go about a much&#45;needed redesign of my portfolio site, I didn&#8217;t expect it to be nearly as difficult or take as much time as it has. Fortunately, it became much more of a priority when I parted ways with MediaSauce at the end of October. I also needed to write some good articles for the new blog in addition to basically generating all new content for the site.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/new-year-new-site/"><img src="/images/sized/uploads/images/blog_new-site-280x190.jpg" width="280" height="190"  alt="New Year, New Site" /></a><p>Five months ago when I decided to go about a much-needed redesign of my portfolio site, I didn't expect it to be nearly as difficult or take as much time as it has. Fortunately, it became much more of a priority when I parted ways with <a href="http://www.mediasauce.com">MediaSauce</a> at the end of October. I also needed to write some good articles for the new blog in addition to basically generating all new content for the site.</p>
<p>When I looked at my old site I saw something that hadn't really been updated in 2 years. It also didn't portray what I wanted to show as my online presence or how I'd grown personally and professionally since graduating. This is the 2nd version of my portfolio and I decided to switch directions from the dark design of <a href="/v1/">version 1</a> to something light and simple. Most of the portfolio work is from projects I've worked on in the last 2 years while working at <a href="http://www.hirons.com" title="Hirons &amp; Company">Hirons &amp; Company</a> and MediaSauce.</p>
<p>Over the next several months, I will be continuing to make slight design changes and tweaks to enhance the site, for example, using <a href="http://typekit.com/" title="typekit">TypeKit</a> for the some of the headings. For now, take a look around and let me know what you think!</p>
<p>If you'd like to know more about the technologies behind the site, check out the <a href="/about/" title="About this site">About</a> page.</p>]]></content:encoded>
      		<dc:subject>Notes</dc:subject>
      		<dc:date>2010-01-06T22:44:07+00:00</dc:date>
    	</item>

    	<item>
      		<title>Change ExpressionEngine Image Sizer Plugin to Crop From the Top</title>
      		<link>http://www.evanblack.com/blog/change-expressionengine-image-sizer-plugin-to-crop-from-the-top/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/change-expressionengine-image-sizer-plugin-to-crop-from-the-top/#comments</comments>
      		<pubDate>Mon, 23 Nov 2009 23:33:58 -0800</pubDate>
      		<guid>http://www.evanblack.com/blog/change-expressionengine-image-sizer-plugin-to-crop-from-the-top/#When:23:33:58</guid>
      		<description>For those of you that don&#8217;t know, ExpressionEngine&#8217;s ImageSizer Plugin is awesome. Anytime you have a client that will be uploading content images to a site that need to be certain dimensions this plugin is crucial. It will dynamically resize the image to whatever dimensions you need, and even cache the resized image for you. Also, if you specify a width and a height for the image in the plugin parameters, and the source&#8217;s dimensions are different, it will even crop the image for you. This is great, but it also has a downside.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/change-expressionengine-image-sizer-plugin-to-crop-from-the-top/"><img src="/images/sized/uploads/images/blog_imagesizer-280x160.jpg" width="280" height="160"  alt="Change ExpressionEngine Image Sizer Plugin to Crop From the Top" /></a><p>For those of you that don't know, ExpressionEngine's <a href="http://www.lumis.com/page/imgsizer/" title="ImageSizer Plugin">ImageSizer Plugin</a> is awesome. Anytime you have a client that will be uploading content images to a site that need to be certain dimensions this plugin is crucial. It will dynamically resize the image to whatever dimensions you need, and even cache the resized image for you. Also, if you specify a width and a height for the image in the plugin parameters, and the source's dimensions are different, it will even crop the image for you. This is great, but it also has a downside.</p>
<p>By default, the plugin will crop the image to the specified width and height from the center of the image. This works great in some cases, but recently (on this site actually) I wanted the plugin to crop my images from the top of the image. This, for example, would be desirable if web screenshots were going to be uploaded and used.</p>
<p>I would've expected this to be a simple parameter passed to the plugin, but unfortunately, it wasn't. I decided to take matters into my own hands and popped open the plugin code. Around line <strong>595</strong> I found this:</p>
<pre class="brush: php;">if ($crop) 
{   
	imagecopyresampled($image_resized, $image, -$int_width, -$int_height, 0, 0, $adjusted_width, $adjusted_height, $width_old, $height_old);
}
</pre>
<h4>Now to Crop from the Top</h4>
<p>I quickly diagnosed that the <strong>-$int_height</strong> variable was forcing the crop from the center. Changing that variable to a 0 would have the plugin cropping from the top. Here's the code with the change:</p>
<pre class="brush: php;">if ($crop) 
{   
	imagecopyresampled($image_resized, $image, -$int_width, 0, 0, 0, $adjusted_width, $adjusted_height, $width_old, $height_old);
}
</pre>
<p>You could also have the plugin crop from the top left corner if you also changed the <strong>-$int_width</strong> variable to 0. Ideally, you could make some updates to the plugin to pass in a <strong>crop_from</strong> parameter and have it accept a "topleft", "topcenter", "topright", "bottomleft", "bottomcenter", "bottomright", or "center" string.</p>]]></content:encoded>
      		<dc:subject>Quick Tips</dc:subject>
      		<dc:date>2009-11-23T23:33:58+00:00</dc:date>
    	</item>

    	<item>
      		<title>CodeIgniter Image Upload and Resize</title>
      		<link>http://www.evanblack.com/blog/codeigniter-image-upload-and-resize/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/codeigniter-image-upload-and-resize/#comments</comments>
      		<pubDate>Fri, 20 Nov 2009 17:06:15 -0800</pubDate>
      		<guid>http://www.evanblack.com/blog/codeigniter-image-upload-and-resize/#When:17:06:15</guid>
      		<description>One common thing that most developers will want to do when creating a web application with CodeIgniter is to give their users the ability to upload a profile image. Your code should be able to resize that profile image to the standard size that your design calls for. CodeIgniter provides two great classes to help make this a piece of cake. The two library classes we will be working with are the File Uploading and Image Manipulation classes. With these two classes and the CodeIgniter&#8230;</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/codeigniter-image-upload-and-resize/"><img src="/images/sized/uploads/images/blog_codeigniter-280x180.jpg" width="280" height="180"  alt="CodeIgniter Image Upload and Resize" /></a><p>One common thing that most developers will want to do when creating a web application with <a href="http://codeigniter.com/" title="CodeIgniter PHP Framework">CodeIgniter</a> is to give their users the ability to upload a profile image. Your code should be able to resize that profile image to the standard size that your design calls for. CodeIgniter provides two great classes to help make this a piece of cake.</p>
<p>The two library classes we will be working with are the <strong>File Uploading</strong> and <strong>Image Manipulation</strong> classes. With these two classes and the <a href="http://codeigniter.com/user_guide/" title="CodeIgniter User Guide">CodeIgniter User Guide</a> you can probably figure out most of what you need, but I'll make it even easier for you. First, we will start with what you need in the View. This will create your file upload field:</p>
<h4>The View</h4>
<pre class="brush: php;">$Fdata = array('name' =&gt; 'user_avatar', 'class' =&gt; 'file');
echo form_upload($Fdata);
</pre>
<p>Also, make sure your form is using '<strong>form_open_multipart</strong>'. Now we will move on to the Controller, where the bulk of the code is. The process here is to configure the upload, do the upload, configure the image resizing and then do the image resize. Here's what you should end up with:</p>
<h4>The Controller</h4>
<pre class="brush: php;">if($_FILES['user_avatar']['error'] == 0){
	//upload and update the file
	$config['upload_path'] = './images/profile/';
	$config['allowed_types'] = 'gif|jpg|png';
	$config['overwrite'] = false;
	$config['remove_spaces'] = true;
	//$config['max_size']	= '100';// in KB
	
	$this-&gt;load-&gt;library('upload', $config);

	if ( ! $this-&gt;upload-&gt;do_upload('user_avatar'))
	{
		$this-&gt;session-&gt;set_flashdata('message', $this-&gt;upload-&gt;display_errors('<p class="error">', '</p>'));
		redirect('profile');
	}	
	else
	{
		//Image Resizing
		$config['source_image'] = $this-&gt;upload-&gt;upload_path.$this-&gt;upload-&gt;file_name;
		$config['maintain_ratio'] = FALSE;
		$config['width'] = 40;
		$config['height'] = 40;

		$this-&gt;load-&gt;library('image_lib', $config);

		if ( ! $this-&gt;image_lib-&gt;resize()){
			$this-&gt;session-&gt;set_flashdata('message', $this-&gt;image_lib-&gt;display_errors('<p class="error">', '</p>'));				
		}
		
		$this-&gt;MUser-&gt;updateProfile($this-&gt;input-&gt;post('user_id'));
		//Need to update the session information if email was changed
		$this-&gt;session-&gt;set_userdata('email', $this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_email')));
		$this-&gt;session-&gt;set_flashdata('message', '<p class="message">Your Profile has been Updated!</p>');
		redirect('profile');
	}
}
</pre>
<p>You may need to make some changes to a couple of the configuration options to get what you want. You'll also notice at the bottom that I update some of my user session information afterwards. Next up, we'll handle the <strong>updateProfile</strong> function within the User Model. This part is pretty simple:</p>
<h4>The Model</h4>
<pre class="brush: php;">function updateProfile($user_id){
	$profile_data = array(
	'name' =&gt; $this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_name')),
	'email' =&gt; $this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_email')),
	'role' =&gt; $this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_role')),
	'website' =&gt; $this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_website'))
	);
	//check if password was updated
	if($this-&gt;input-&gt;post('user_password') != ''){
		$profile_data['password'] = md5($this-&gt;input-&gt;xss_clean($this-&gt;input-&gt;post('user_password')));
	}
	if($_FILES['user_avatar']['error'] == 0){
		$relative_url = 'images/profile/'.$this-&gt;upload-&gt;file_name;
		$profile_data['avatar'] = $relative_url;
	}
	$this-&gt;db-&gt;where('id', $user_id);
	$this-&gt;db-&gt;update('user', $profile_data);
}
</pre>
<p>Normally you would want your path to pull from the configuration options you set using $upload['full_path'], but for some reason I've had issues pulling that data from the upload.</p>]]></content:encoded>
      		<dc:subject>Development</dc:subject>
      		<dc:date>2009-11-20T17:06:15+00:00</dc:date>
    	</item>

    	<item>
      		<title>Getting the ExpressionEngine Member List to Display Custom Member Fields</title>
      		<link>http://www.evanblack.com/blog/getting-expressionengine-member-list-to-display-custom-member-fields/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/getting-expressionengine-member-list-to-display-custom-member-fields/#comments</comments>
      		<pubDate>Thu, 19 Nov 2009 04:11:21 -0800</pubDate>
      		<guid>http://www.evanblack.com/blog/getting-expressionengine-member-list-to-display-custom-member-fields/#When:04:11:21</guid>
      		<description>Back when I was working with ExpressionEngine on the NIC Indy website, I needed to display custom member data fields in the member directory list. I actually found it quite surprising that ExpressionEngine didn&#8217;t already have an option that allowed you to do this. After some fiddling around with the &#8220;memberlist&#8221; function, I found a pretty quick and simple way to make this happen.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/getting-expressionengine-member-list-to-display-custom-member-fields/"><img src="/images/sized/uploads/images/blog_member-directory-280x180.jpg" width="280" height="180"  alt="Getting the ExpressionEngine Member List to Display Custom Member Fields" /></a><p>Back when I was working with ExpressionEngine on the <a href="http://www.nicindy.org/" title="NIC Indy">NIC Indy website</a>, I needed to display custom member data fields in the member directory list. I actually found it quite surprising that ExpressionEngine didn't already have an option that allowed you to do this. After some fiddling around with the "memberlist" function, I found a pretty quick and simple way to make this happen.</p>
<p>First of all, you will need to open up the <strong>mod.member_memberlist.php </strong>file. It will be in the Member Management module, usually located here: "/system/modules/member". Go down to around line number 510. It should look something like this:</p>
<h4>Before</h4>
<pre class="brush: php;">$f_sql="SELECT m.member_id, m.username, m.screen_name, m.email, m.url, m.location, m.icq, m.aol_im, m.yahoo_im, m.msn_im, m.location, m.join_date, m.last_visit, m.last_activity, m.last_entry_date, m.last_comment_date, m.last_forum_post_date, m.total_entries, m.total_comments, m.total_forum_topics, m.total_forum_posts, m.language, m.timezone, m.daylight_savings, m.bday_d, m.bday_m, m.bday_y, m.accept_user_email, m.avatar_filename, m.avatar_width, m.avatar_height, (m.total_forum_topics + m.total_forum_posts) AS total_posts, g.group_title ";		
$p_sql="SELECT COUNT(member_id) AS count ";
$sql="FROM exp_members m, exp_member_groups g 
WHERE m.group_id = g.group_id 
AND g.group_id != '3' 
AND g.group_id != '4' 
AND g.site_id = '".$DB-&gt;escape_str($PREFS-&gt;ini('site_id'))."'
AND g.include_in_memberlist = 'y' ";
</pre>
<p>You will be adding to these SQL select statements so that it also pulls from the <strong>exp_member_data</strong> table. Here is what you'll need to change the SQL statements to:</p>
<h4>After</h4>
<pre class="brush: php;">$f_sql="SELECT m.member_id, m.username, m.screen_name, m.email, m.url, m.location, m.icq, m.aol_im, m.yahoo_im, m.msn_im, m.location, m.join_date, m.last_visit, m.last_activity, m.last_entry_date, m.last_comment_date, m.last_forum_post_date, m.total_entries, m.total_comments, m.total_forum_topics, m.total_forum_posts, m.language, m.timezone, m.daylight_savings, m.bday_d, m.bday_m, m.bday_y, m.accept_user_email, m.avatar_filename, m.avatar_width, m.avatar_height, (m.total_forum_topics + m.total_forum_posts) AS total_posts, g.group_title, md.m_field_id_1, md.m_field_id_2, md.m_field_id_3, md.m_field_id_4, md.m_field_id_5, md.m_field_id_6, md.m_field_id_7, md.m_field_id_8, md.m_field_id_9, md.m_field_id_10, md.m_field_id_11, md.m_field_id_12, md.m_field_id_13, md.m_field_id_14 ";       
$p_sql="SELECT COUNT(m.member_id) AS count ";
$sql="FROM exp_members m, exp_member_groups g, exp_member_data md 
WHERE m.group_id = g.group_id 
AND m.member_id = md.member_id 
AND g.group_id != '3' 
AND g.group_id != '4' 
AND g.site_id = '".$DB-&gt;escape_str($PREFS-&gt;ini('site_id'))."'
AND g.include_in_memberlist = 'y' ";
</pre>
<p>The important changes here are on lines 1, 3 and 5. Unfortunately, you will need to manually add as many "m_field_id_x"s for as many custom member fields that have been created.</p>
<h4>Now to Display the Custom Fields</h4>
<p>To display the newly selected custom fields on the front-end of the member list, you will need to edit the <strong>Member Templates</strong>. You can do this in the Control Panel by going to your Member Profile Theme and finding the <strong>Member List Rows</strong> template. You can display the custom member fields simply by using the normal ExpressionEngine template tags like this - {m_field_id_x} - replacing "x" with whichever member profile field you want. Here is a section of mine:</p>
<pre class="brush: html;">&lt;ul&gt;
    &lt;li&gt;&lt;h6&gt;Contact Information&lt;/h6&gt;&lt;/li&gt;
    &lt;li&gt;title: &lt;span&gt;{m_field_id_8}&lt;/span&gt;&lt;/li&gt;
    &lt;li&gt;phone: &lt;span&gt;{m_field_id_5}&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>That's pretty much it. The only bad thing here is if Custom Member Fields are ever added you will also need to add them to the SQL statement.</p>
<h4>The Result</h4>
<p>As you can see from the image below, I was able to pull out the data I needed for the directory from these custom member fields.</p>
<p><img height="356" src="/uploads/images/nic_result.png" width="600" /></p>]]></content:encoded>
      		<dc:subject>Development</dc:subject>
      		<dc:date>2009-11-19T04:11:21+00:00</dc:date>
    	</item>

    	<item>
      		<title>Semantic Inline Form Labels with JQuery</title>
      		<link>http://www.evanblack.com/blog/semantic-inline-form-labels-with-jquery/</link>
      		<author><![CDATA[Evan]]></author>
      		<comments>http://www.evanblack.com/blog/semantic-inline-form-labels-with-jquery/#comments</comments>
      		<pubDate>Mon, 02 Nov 2009 23:45:19 -0800</pubDate>
      		<guid>http://www.evanblack.com/blog/semantic-inline-form-labels-with-jquery/#When:23:45:19</guid>
      		<description>A very common thing I see in designs I get these days are form labels that are written within the value of their associated input field. This is handy way for designers to save space and make their designs cleaner all&#45;around. Unfortunately for us developers, simply setting the input value isn&#8217;t very semantic or usable.</description>
      		<content:encoded><![CDATA[<a href="http://www.evanblack.com/blog/semantic-inline-form-labels-with-jquery/"><img src="/images/sized/uploads/images/blog_inline-labels-280x150.jpg" width="280" height="150"  alt="Semantic Inline Form Labels with JQuery" /></a><p>A very common thing I see in designs I get these days are form labels that are written within the value of their associated input field. This is handy way for designers to save space and make their designs cleaner all-around. Unfortunately for us developers, simply setting the input value isn't very semantic or usable. Thanks to JQuery there's plenty of easy ways to take care of this.</p>
<h4>The HTML</h4>
<p>We'll start with the HTML. Nothing fancy here, just your standard form with labels and inputs.</p>
<pre class="brush: html;">&lt;form id="signup" name="signup"&gt;<br />	&lt;label for="email"&gt;Email Address&lt;/label&gt;<br />	&lt;input class="text" name="email" type="text" /&gt;<br />	&lt;label for="zip"&gt;Zip Code&lt;/label&gt;<br />	&lt;input class="text zip" name="zip" type="text" /&gt;<br />	&lt;input class="btn" type="submit" value="Sign Up" /&gt;<br />&lt;/form&gt;<br /></pre>
<p>The CSS isn't important at all to what we're trying to accomplish, so I won't cover any of that. The JQuery on the other hand, is what does most of the work. First of all, we will want to loop through our label elements and assign their values to the inputs that immediately follow. Then you'll want to hide those labels. After that, we will handle the focus and blur events to get rid of those values when people click the form input. Here's the JQuery:</p>
<h4>The JQuery</h4>
<pre class="brush: js;">$(document).ready(function() {<br />    $("#signup label").each(function (i) {<br />        $(this).next("input").attr("value",$(this).html()+"...");<br />        $(this).hide();<br />    });<br />    $("#signup input").focus(function() {<br />        if($(this).prev("label").html()+"..." == this.value){<br />            this.value = "";<br />        }<br />    });<br />    $("#signup input").blur(function() {<br />        if(this.value == ""){<br />            this.value = $(this).prev("label").html()+"...";<br />        }<br />    });<br />});<br /></pre>
<p>Now this is by no means is a new or innovative technique. There are plenty of solutions out there that will accomplish the same goal. This tip is simply what I tend to use to sematically code the designs I get.</p>
<p><strong>Update (12-18-2009): </strong>Smashing Magazine recently published an article by <a href="http://www.zurb.com/">Zurb</a> called <a href="http://www.smashingmagazine.com/2009/12/16/stronger-better-faster-design-with-css3/">Stronger, Better, Faster Design with CSS3</a> that expands on this technique and makes it even better with CSS3 by just masking the label so even when you click into the input you can still read the label.</p>]]></content:encoded>
      		<dc:subject>Quick Tips</dc:subject>
      		<dc:date>2009-11-02T23:45:19+00:00</dc:date>
    	</item>

    
    	</channel>
</rss>
