<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">

<channel><generator>http://textpattern.com/?v=4.0.4</generator>
<title>Articles from DavidNBrooks.com</title>
<link>http://davidnbrooks.com/</link>
<description>Writings on Photography, Design and Development by David Brooks</description>
<pubDate>Thu, 14 Feb 2008 08:00:00 EST</pubDate>

<item><title>To Framework, or Not To Framework: Part 2</title>
<description>
<![CDATA[

	<p>In part 1 of &#8220;<a href="http://davidnbrooks.com/journal/to-framework-or-not-to-framework">To Framework, or Not To Framework</a>&#8220;, I wrote about why I don&#8217;t tend to use frameworks like Bootstrap or Foundation. If you haven&#8217;t read that, it gives a bit of context to the &#8220;why&#8221; part of this article. </p>

	<p>The first thing people use in a framework (at least it feels that way) is the grid system. In <a href=“http://getbootstrap.com/css/“>Bootstrap</a> you have classes like .col-md-1 to indicate one grid unit, in <a href=“http://foundation.zurb.com/grid.html”>Foundation</a> .large-1 accomplishes the same thing. </p>

	<p>Both Bootstrap and Foundation are based on a 12 column grid. So those classes above are asking for 1/12 of the grid. Bootstrap implies we&#8217;re working with desktop styles. Foundation makes it a bit more obvious by adding “large” to the class.</p>

	<p>If you want to assign a column to be 1/2 of the width of the screen on mobile, you would write:</p>

	<p><strong>Bootstrap:</strong> .col-xs-6 (xs = extra small)</p>

	<p><strong>Foundation:</strong> .small-6</p>

	<p>When you want to make things responsive, you can mix and match those classes to get it right.</p>

	<p><strong>Bootstrap</strong></p>

	<p><code>&lt;div class=“col-xs-6 col-md-3”&gt;&lt;/div&gt;</code></p>

	<p><strong>Foundation</strong></p>

	<p><code>&lt;div class=“small-6 large-3”&gt;&lt;/div&gt;</code></p>

	<h2>Freedom</h2>

	<p>Now there’s nothing wrong with those grid systems. But for me, I don&#8217;t use Bootstrap or Foundation because of all the overwriting of styles that I have to do to make something look unique. So, I don&#8217;t include Bootstrap or Foundation just for their grid system. For me, since I’m not bound to a framework, I get to choose the grid system that makes the most sense to me. Instead, I use <a href=“http://unsemantic.com/“>Unsemantic</a> on most of my projects. </p>

	<p><a href=“http://sonspring.com/“>Nathan Smith</a>, who wrote Unsemantic, used percentages to build the grid system. So, if I want a div that sits at 50% width on mobile and 10% on desktop, that looks like this:</p>

	<p><code>&lt;div class=“mobile-grid-50 grid-10”&gt;&lt;/div&gt;</code></p>

	<p>By just using .grid-10, I get the desktop styles. Adding mobile- or tablet- to the class applies that style if the reader is on a mobile or tablet device. </p>

	<h2>Application</h2>

	<p>Now, for a long time, I wrote my divs exactly as seen above so that other people could figure out what I was doing:</p>

	<p><code>&lt;div class=“sidebar mobile-grid-100 grid-25”&gt;&lt;/div&gt;</code></p>

	<p>Usually there’s another class in there anyway, in this case .sidebar. So instead of adding a series of classes in my <span class="caps">HTML</span>, I’m now making use of Unsemantic inside my <span class="caps">SASS</span> files as often as I can. So I write something like:</p>

<pre><code>.sidebar {
    @extend .grid-25;
    @extend .mobile-grid-100;
    /* More styles go here */
}
</code></pre>

	<p>By adding them in the <span class="caps">SASS</span> file they’re included in the <span class="caps">CSS</span> files when that’s all combined. As a result, my <span class="caps">HTML</span> is more minimal. My <span class="caps">SASS</span> files stay cleaner, too. By using @extend, I can do widths, margins, padding, and responsive styles all in one single line.</p>

	<h2>Impacts on Design</h2>

	<p>The biggest departure isn’t the grid-10 vs col-1 vs large-1, it’s in the design phase. If you design for Bootstrap or Foundation (or just prefer 12 columns), not having 12 columns as a basis can be a little jarring. But for me, if I look around at other designs, most of the basics exist in all three systems. 1/3 is still 1/3, regardless of whether it’s 4 columns or 25%, for example. But Unsemantic doesn’t break down into twelve parts you get ten instead.</p>

	<p>If that bugs you for some reason, I’d recommend <a href=“https://gridsetapp.com/“>Gridset</a>. You can get as granular or particular with your grids as you want. If a 5 column system appeals to you, hey, you can make that. What about a 7 of varying sizes? Yep.</p>

	<p>I used Gridset for a long time, and I love it. But most of the time I don’t need that level of complexity with my work. Most often it’s a 66% content block and a 33% sidebar or something like that. </p>

	<p>So whichever way you need to work, you have options. But you don’t have to feel as if the only way to build something is by using a full framework. </p>

	<p>In the next article, I’ll cover Typography. </p>

]]>

</description>
<link>http://davidnbrooks.com/journal/to-framework-or-not-to-framework-part-2</link>
<pubDate>Tue, 09 Feb 2016 10:02:58 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/to-framework-or-not-to-framework-part-2</guid>

</item>
<item><title>To Framework, or Not To&#160;Framework</title>
<description>
<![CDATA[

	<p>When I interviewed for my current role, I was asked &#8220;what would you say you’re the best in? What’s your specialty?&#8221; </p>

	<p>I thought, as the question was being asked, that my honest answer was going to cost me the role. </p>

	<p>My exact response is really blurry at this point, but the gist of it is that…</p>

	<p>1. I wouldn’t consider myself the best in anything, because there are a lot of smart people who specialize in things.<br />
2. I focus my time on <span class="caps">HTML</span> and <span class="caps">CSS</span>, because regardless of what back-end languages, or JavaScript libraries are in play, they all tend to need <span class="caps">HTML</span> and <span class="caps">CSS</span> at the core of it.</p>

	<p>Apparently it was the right answer for this team, however. </p>

	<p>At the time I had worked in web apps, where the entire thing was written in Rails/Java/.NET and I just had to make the front-end work. And I had also worked on apps that were front-end heavy, written in AngularJS or Backbone. Even the iOS development work that I’ve done fell into that second category.</p>

	<p>If you can write <span class="caps">HTML</span> and <span class="caps">CSS</span> well, it takes away a whole lot of cruft from the interface. You don’t have random unnecessary tags floating around. Things aren’t in tables, unless you’re working with tabular data. And you can often speed up the UI by not leaning on JavaScript in the first place. </p>

	<h2>Frameworks</h2>

	<p>But there was a bigger context to that question, which revolved around Bootstrap and AngularJS. </p>

	<p>At the time, I had been working on apps that used (and occasionally abused) Bootstrap or Foundation. One of those apps also happened to use AngularJS. Another still used Bootstrap, AngularJs, and a few random bits of CoffeeScript because someone wanted to upgrade their resume.</p>

	<p>I could certainly write Bootstrap specific <span class="caps">HTML</span>, I didn’t consider it hard or a big, scary unknown. It’s just not for me. I’ve built my career on being a minimalist <span class="caps">HTML</span> and <span class="caps">CSS</span> writer, and that has never failed me. Not once. </p>

	<p>But having that skill gives me an opinion about Bootstrap and the <span class="caps">HTML</span> and <span class="caps">CSS</span> that it expects.</p>

	<p>Now, I’m not at all hating on Bootstrap. Use it or don&#8217;t, I don’t really care. But for me, I never use 95% of Bootstrap, or any other framework. There’s a ton of stuff that nobody uses. But yet, if I choose it, it sits there in my project. Sometimes, Bootstrap updates, and things break. I have to rewrite code, update classes, etc. But minimalist stuff just doesn’t move. It stays in place.</p>

	<p>And of course, the more weight my scripts and <span class="caps">CSS</span> files have in them, the more of a pain it is to get that stuff loaded into a browser or mobile device. (One of my recent Angular projects had about 500KB of scripts alone.)</p>

	<p>I see so many job posts asking for something particular, like Foundation or Bootstrap that it’s easy to see why young front-end developers focus on it. And with the variety of things that a framework like that can do, it’s easy to see why they’re often &#8220;the obvious choice.&#8221;</p>

	<p>But I think there’s a better way forward. In the next few articles, I’ll be writing about my own processes  and how I go about building sites. I’ll be starting with the bits of <span class="caps">CSS</span> and <span class="caps">HTML</span> that I use in almost everything I build.</p>

	<p><a href="http://davidnbrooks.com/journal/to-framework-or-not-to-framework-part-2">Part 2: Grid Systems</a></p>

]]>

</description>
<link>http://davidnbrooks.com/journal/to-framework-or-not-to-framework</link>
<pubDate>Tue, 17 Nov 2015 09:11:58 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/to-framework-or-not-to-framework</guid>

</item>
<item><title>The Question of&#160;Rates</title>
<description>
<![CDATA[

	<p>Months ago, <a href="http://northwardcompass.com">we</a> were over our head in the learning curve that is game development. It wasn&#8217;t the &#8220;big picture&#8221; stuff, but the subtle parts of making a car drive properly that were dragging us down. </p>

	<p>I had spent two or three weeks on a car that, while it could drive, it was too eager to roll and flip. (It was as if the tires were made of springs.) Though I have a lot of experience programming on the web, I needed to find someone to help get the nuances figured out in Unity. </p>

	<p>So I sent word to a popular job board that I was in search of a <a href="http://unity3d.com">Unity</a> developer. It was a short note, but I was clear up front that I wanted to see their work, and I needed to know their rates. </p>

	<p>In the dozens of responses, only one person sent both rates and examples of their work in the first email. Most people would send over their resume and ignore that second part.</p>

	<p>At first, I just assumed people had overlooked that detail. So, when someone who seemed qualified sent me their resume, I politely asked for their rates. </p>

	<p>For whatever reason, that turned out to be the fastest way to remove applicants from the pool. When I asked for their rates, people with whom I had been in conversation about the role would walk away without another word. It was as if I had just asked them to sell their soul. (I wasn&#8217;t, I promise.)</p>

	<p>But the uneasiness wasn&#8217;t always blatant. One person kept me in conversation for well over a day, getting various details about the project. I appreciated his interest in the details, and getting to the bottom of how our relationship would work. But in the end, he misjudged how large our company is and bid the project at over double our company rate. When I looked back at the conversation transcripts, it occurred to me that he too had been stalling to figure out how to answer the question.</p>

	<h2>Money is Odd</h2>

	<p>In modern society we need it to survive, and some people even allow it to own them. It&#8217;s this awkward transactional thing that lets us feed our families and keep the lights on. </p>

	<p>I understand how unnerving it is to talk about rates, too. As a contractor, you know you have to hit the number right on the head to even stay in the running. Bid high and you&#8217;re off the project, bid low and you’ll be perceived as inexperienced and unable to take the project. </p>

	<p>Believe me, I would much rather not have to deal with the financial side of business. I would do this stuff as a hobby if money weren&#8217;t a thing. But part of being a professional is getting past the aversion to talking about what things cost. </p>

	<p>You aren&#8217;t your hourly rate or your yearly salary. Your skills and time aren&#8217;t so easy to match with a value. If that were the case, nobody could ever afford any of us. Somewhere deep down we all know this. </p>

	<p>But as someone who has needed to set an hourly rate for a long time now, I can tell you that it does get easier. And perhaps you don&#8217;t want to work under an hourly scheme. That&#8217;s fine too. But be able to explain your pricing structure to someone who is looking to hire you. </p>

	<p>Being unable to answer the question shows a lot more professional immaturity than giving the wrong number. If you bid high (within reason) I can ask you to take a lower number if your skills match. If you&#8217;re young and don&#8217;t really know what to charge, put a number out there. Make it a realistic number of course. I can&#8217;t speak for every &#8220;boss&#8221;, but I&#8217;ll often raise a person&#8217;s salary if they&#8217;re not asking for enough. In my opinion, a fair wage is on both parties. </p>

	<p>So when someone asks you for a number, just give it to them. And don&#8217;t apologize for it. </p>

]]>

</description>
<link>http://davidnbrooks.com/journal/the-question-of-rates</link>
<pubDate>Thu, 26 Mar 2015 11:03:10 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/the-question-of-rates</guid>

</item>
<item><title>War of the Roaches - Part 1</title>
<description>
<![CDATA[

	<p><img src="/images/457.jpg" alt="A dead cockroach" /></p>

	<p>As the poor creature spun around in circles on its way to a watery grave, I replayed the events over and over in my head. I still cannot be certain my report is completely accurate, I was both sleep-deprived and under intense stress.</p>

	<p>Like a political lobbyist’s intern, my alarm clock faced great difficulty in calling me to action. And so it was that morning. I was nowhere near deep sleep, though I was closer to it than I was to being awake. In the past forty minutes I had tapped the snooze button on my alarm clock no less than 5 times. </p>

	<p>I lay there rolling the idea of being awake around in the back of my mind, but it was a lofty goal that I wasn&#8217;t sure I would reach. </p>

	<p>And then I felt it, a subtle brushing across the back of my neck. It came in quick flutters against the base of my hairline, a strange alien motion that I couldn&#8217;t compare in my sleepy state. </p>

	<p>My subconscious could. It nudged me awake with the urgency of a small house fire.</p>

	<p>When my eyes were open, I brushed it all off as any other dream. But as soon as my eyes closed and I let myself relax, I felt it again. </p>

	<p>My subconscious forced me to action and I reached up in self-defense, slinging whatever it was as far away as I could manage. I sat up in bed, scanning the room for whatever it was, but I saw no sign of it anywhere.</p>

	<p>I cannot explain how the next part happened. Even something as cliche as a dream within a dream seems as likely a scenario as any. I don&#8217;t recall putting my head on the pillow again, but the next thing I remember is a sound echoing through the pillow. </p>

	<p>It was the sound of fluttering wings against the light material of the pillowcase.</p>

	<p><img src="/images/454.jpg" alt="A single cockroach" class="floated_image" style="float: left; width: 200px; margin-right: 20px;" /> I bolted upright, completely alert. At the top of the pillow a giant cockroach looked up at me with an evil glint in its eye. It did not speak, not with a voice you could hear. Instead, it twitched its antennae back and forth until I understood its telepathic message.</p>

	<p>&#8220;I claim this house in the name of our queen. You are to report to the palace at once for registration.&#8221;</p>

	<p>I assume by “palace” he meant the cabinet beneath our sink.</p>

	<p>Out of respect for the diplomatic process, or maybe because it rested on MY pillow and I could not kill it outright, I captured it in a glass. (It is the same courtesy I show spiders after all.)</p>

	<p>In hindsight, the glass was neither covered nor deep, and it was a terrible choice of vessels in which to transport a prisoner. The poor decision was obvious when I flipped the glass upside down to shake the roach into the toilet. Instead of falling to its demise, it leapt with gazelle-like agility to safety.</p>

	<p>But that safety was short-lived. Inside the nearby closet, my old trusty boot was ready for action. The now aging leather, though cracked, met the ground with a loud thud.</p>

	<p>I take no pleasure in the death of a cockroach. But by its own telepathic admission of guilt, it was in my apartment on a mission of conquest. And our apartment is not large by any stretch of the imagination. We would have needed another bedroom for a cockroach of that size.</p>

	<p>A shower was in order, perhaps to wash the blood of war from my hands. After that my daughter woke up, meeting me in time for breakfast at the dining room table. </p>

	<p><img src="/images/455.jpg" alt="A cockroach, with a parachute" class="floated_image" style="float: left; width: 200px; margin-right: 20px;" /> I had already put the bacon in the oven, and the eggs were on the stove when I heard her shriek. She was across the room, but the open-plan of the kitchen and living area gave her a clear line of sight to where I stood. </p>

	<p>&#8220;Look!&#8221; She yelled, pointing in my direction.<br />
&#8220;What?&#8221; I asked, not entirely sure her cries were warranted.<br />
&#8220;A bug!&#8221; </p>

	<p>On the ledge just above the stove crept a lone scout. It wore the marks of its clan across its face like a tribal warrior. With a twitch of its body, and a flick of its antennae, it stopped forward motion and reached out with its telepathic fingers. </p>

	<p>&#8220;I know what you did,&#8221; a slippery voice in the back of my mind scolded.</p>

	<p>And I believed it. </p>

	<p>But it could not escape fate. There was a fancy candle with enough heft to get the job done, and leaving a witness is a bad idea. </p>

	<p>There would be one more death before the sun had risen above the top of the moss-covered trees. But knowing that one cockroach was agile enough to escape is what keeps me on edge today. The war has begun indeed.</p>

	<p><img src="/images/456.jpg" alt="A roach in a tank, charging into battle" /></p>

]]>

</description>
<link>http://davidnbrooks.com/journal/war-of-the-roaches-part-1</link>
<pubDate>Wed, 19 Nov 2014 08:11:40 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/war-of-the-roaches-part-1</guid>

</item>
<item><title>Gearheads -&#160;Site</title>
<description>
<![CDATA[

	<p>One of my long-standing clients asked me to redesign his site, <a href="http://gearheads.org">Gearheads</a>. So, I crafted an overall layout and passed it along to my wife, and <a href="http://adrianrodriguez.me/">Adrian Rodriguez</a>, who work on <a href="http://northwardcompass.com">Northward Compass</a> projects with me. After a round or two of revisions, we arrived at this design. </p>

	<p>For the development phase, I teamed up with the newest member of Northward Compass, Kyler. Together we built out the <span class="caps">HTML</span>, and <span class="caps">CSS</span>. The site runs on the WordPress <span class="caps">CMS</span>. </p>

	<p><img src="/images/452.jpg" alt="Gearheads.org Front Page" /><br />
<img src="/images/453.jpg" alt="Gearheads.org Secondary Page" /></p>

]]>

</description>
<link>http://davidnbrooks.com/design/gearheads-site</link>
<pubDate>Tue, 12 Aug 2014 08:08:31 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/design/gearheads-site</guid>

</item>
<item><title>Thunderbomb Surf Camp -&#160;Site</title>
<description>
<![CDATA[

	<p>I was approached by Thunderbomb Surf Camp in Nicaragua to build a site. The first thing I knew about Nicaragua is how gorgeous it is, and I wanted to showcase that. Plus, when you&#8217;re looking for a place to surf, you want to make sure the waves are going to deliver. So I put all of that natural beauty into this design by including large-scale imagery. </p>

	<p>Each page of the main site is different, and it builds a collection on the front page using the <a href="http://textpattern.com">Textpattern</a> <span class="caps">CMS</span>. </p>

	<p><img src="/images/449.jpg" alt="ThunderbombSurf Front Page" /><br />
<img src="/images/450.jpg" alt="ThunderbombSurf Surf Spots" /><br />
<img src="/images/451.jpg" alt="ThunderbombSurf Typical Day" /></p>

]]>

</description>
<link>http://davidnbrooks.com/design/thunderbomb-surf-camp-site</link>
<pubDate>Tue, 12 Aug 2014 08:08:07 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/design/thunderbomb-surf-camp-site</guid>

</item>
<item><title>Christine Parker Music -&#160;Site</title>
<description>
<![CDATA[

	<p>I had the privilege of working with <a href="http://christineparkermusic.com/">Christine Parker</a> on the art for her first album, as well as her site. </p>

	<p>We built this on the <a href="http://textpattern.com">Textpattern</a> <span class="caps">CMS</span>, and incorporated some of the photos taken for her album. </p>

	<p><img src="/images/448.jpg" alt="ChristineParkerMusic.com" /></p>

]]>

</description>
<link>http://davidnbrooks.com/design/christine-parker-music-site</link>
<pubDate>Tue, 12 Aug 2014 08:08:34 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/design/christine-parker-music-site</guid>

</item>
<item><title>Paleo: 1 Month&#160;Down</title>
<description>
<![CDATA[

	<p><img src="/images/447.jpg" alt="Fruits and vegetables" /></p>

	<p>One month ago, I started on the paleo diet. My goal was to make it a year, being as consistent as I could. Well, the first month is down and so far (aside from a few things here and there) all is well.</p>

	<p>I haven&#8217;t downed a cake, or eaten bread. Those are my two biggest cravings when I actually have them. (Like now, because I&#8217;m writing about it.) </p>

	<p>Sometimes it&#8217;s still a pain to eat at restaurants because there just isn&#8217;t a true paleo option. So I end up eating a salad, which of course isn&#8217;t always filling (or good). But that&#8217;s not to complain, just to state the reality of it. It&#8217;s impossible to eat outside of the house and be truly on paleo. Even the steak I had the other day was covered in preservatives. But it was my wife&#8217;s favorite restaurant, and the only thing on the menu pretending to be paleo-esque.</p>

	<h2>Weight Loss</h2>

	<p>In the month of July, I lost 18.5 lb. But that&#8217;s without trying. I never really felt hungry except for the initial phase of breaking out of sugar and carb addiction. (That first week back on Paleo, I just want to hijack every bakery truck I see.) And while lately I&#8217;ve been eating more salads, I&#8217;m not feeling like I&#8217;m starving. It&#8217;s just easier now to eat reasonable meals since the actual calories add up just fine.</p>

	<h2>Other Symptoms</h2>

	<p>A couple weeks ago I was getting heartburn pretty consistently. I dropped the amount of coconut oil I was using and it went away. I think the culprit was how I was cooking my eggs in the morning, though it never felt greasy. </p>

	<p>Before getting back to Paleo, I was getting an occasional chest pain. But that hasn&#8217;t happened once since I started Paleo. I was diagnosed with reflux disease a few years back, so I knew ahead of time that it isn&#8217;t tied to my heart, just diet/caffeine.</p>

	<p>A friend of ours reported that when she cut gluten, her sinuses cleared up, and I was hoping that by dropping dairy and gluten the same might happen for me. It&#8217;s possible that my sinus issues have gone down a little bit, in fact, now that I&#8217;m actively writing it I&#8217;d say they probably have. But it&#8217;s not completely &#8220;fixed&#8221;, which is something I was hoping would just happen. </p>

	<h2>Overall</h2>

	<p>Though the progress is good, I&#8217;m not stopping. I assume that in this next month I&#8217;ll notice a plateau in my weight loss, but it&#8217;s too early to say. My goal is to continue eating right within my calorie allotment without adding any exercise. And, this month I&#8217;ve not stood up to work a single day. So anything I&#8217;ve lost is because of the diet. Seriously, I&#8217;m sitting down more than is actually healthy. I do need to fix that.</p>

	<p>But so far, so good. If you&#8217;re curious about how the progress worked out for any given day, I&#8217;m keeping a log of the progress <a href="http://davidnbrooks.com/365-days-paleo/">in a paleo journal</a>.</p>

]]>

</description>
<link>http://davidnbrooks.com/journal/paleo-1-month-down</link>
<pubDate>Fri, 01 Aug 2014 09:08:16 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/paleo-1-month-down</guid>

</item>
<item><title>Web Standards and JavaScript for Aging&#160;Devices</title>
<description>
<![CDATA[

	<p><img src="/images/446.jpg" alt="JavaScript code in an Commodore64-themed editor" /></p>

	<p>The first thing I learned about web development was that there was this thing called &#8220;Web Standards&#8221;, and it was awesome. We as an industry are better for it because it’s inclusive and altruistic. People with screen readers, for example, benefit from it because we knew better than to just use Flash on everything. You&#8217;re probably not writing your <span class="caps">HTML</span> into tables these days, so thank the web standards movement for that too.</p>

	<p>But web standards also ventures into things like removing onClick=&#8220;Insert your JavaScript Here&#8221; from your <span class="caps">HTML</span>, and instead advocates for placing that JavaScript in your actual JavaScript file. And that’s smart, because when you’re working on a web app, or a site with a lot of pages, you don’t want to go through and pull out references to things you use over and over again. </p>

	<p>In fact, that has been one of my primary frustrations with AngularJS. It’s so much of ng-click=&#8221;&#8220; that it’s basically a collection of “bad practices”.</p>

	<h2>The Problem With that</h2>

	<p>We’ve been working hard on an iOS app over at <a href=“http://artletic.com”>Artletic</a>. We opted to use the <a href="http://ionicframework.com/">Ionic Framework</a>, but not all of the Angular JS stuff because, well, at the time it didn’t seem to be necessary when all we wanted was some <span class="caps">HTML</span> and some JS. I set the thing up on day one and it just flew. Seriously, it was quick. </p>

	<p>Fast forward to last week and the app was just dragging on my actual iPhone 4. Now, that’s on a 4. It was semi-usable on a 5, but not everyone has a 5. In fact, I could hardly test the latest features because it was so slow on my phone. </p>

	<p>So I remembered something that happened to me a few years ago when I worked at (what was then) <a href=“http://www.fellowshipone.com/>Fellowship Technologies</a>. I created this nice and orderly list wherein people could interact with their data. However, we never tested it with thousands of entries. Shortly after, <a href=“http://sonspring.com”>Nathan Smith</a> and I (mostly Nathan) refactored my code to work for larger sets of data because it had a serious performance drain under those conditions.</p>

	<h2>The Wisdom in Being &#8220;Wrong&#8221;</h2>

	<p>The way he did it, was to rework and then reference the JavaScript function with an onClick. Why did it work? By registering click events for every last one of those thousand items, there was just so much extra memory weight that it dragged down the app. Putting things in the <span class="caps">HTML</span> itself meant that the browser didn’t have to roll through every entry and create those events, then watch each and every one of them. It meant that the browser didn’t have to care until you interacted with that data. Then, it would see the onClick event and take action… But only when you clicked it.</p>

	<p>In my Ionic project it was the same thing, but on a much smaller and finicky scale. My browser was completely fine with the JavaScript, the simulator was fine with the JavaScript, but the actual device was not. The iPhone is a much lighter device than my Macbook (obviously), there should be no expectation of comparability. </p>

	<p>I had been using the <a href="http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html">module pattern</a>, and each click event was already referencing functions. </p>

	<p>Before, it looked like this:</p>

<pre><code>$(&#39;body&#39;).on(&#39;click&#39;, &#39;#something&#39;, function ( ){
	interaction.load_something();
});
</code></pre>

	<p>But for performance&#8217;s sake, I changed it to be this:</p>

<pre><code>&lt;a href=&quot;#whatever&quot; id=&quot;something&quot; onClick=&quot;interaction.load_something();&quot;&gt;Whatever&lt;/a&gt;
</code></pre>

	<p>When there are large sets of data, that markup is neatly placed in a Handlebars template that gets added and subtracted from the <span class="caps">DOM</span> as necessary. It&#8217;s just as performant if there are one or a hundred things in the list, and because it’s included in a partial, I&#8217;m not having to maintain that code in 100 pages across an app. And I think that’s why AngularJS uses hg-click as well.</p>

	<p>The speed increase was immediately apparent. I removed the click function in my JS file for one of the biggest offenders, and the app was suddenly very usable. It wasn’t as usable as I wanted it to be, however, but when we removed a good number of the click events it sped up quite a bit.</p>

	<p>So while it wasn’t exactly a tactic that I&#8217;ll be applauded for in the web standards community, it saved our app and, thanks to Handlebars, still kept me from having to weed through too much JavaScript in my <span class="caps">HTML</span>.</p>

	<h2>In Reality</h2>

	<p>This really isn&#8217;t an anti-web standards post. Honestly, the old wisdom is so good that most of my sites will still use the same module pattern and click events routine. But when I&#8217;m building something mobile/hybrid, inline click events are a small price to pay for what could be a large number of happier users on aging, lightweight devices.</p>

]]>

</description>
<link>http://davidnbrooks.com/journal/web-standards-and-javascript-for-aging-devices</link>
<pubDate>Thu, 17 Jul 2014 08:07:00 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/web-standards-and-javascript-for-aging-devices</guid>

</item>
<item><title>Better Team Projects with Grunt&#160;JS</title>
<description>
<![CDATA[

	<p>For years I pre-processed my <span class="caps">SASS</span>/LESS files and minified my JavaScript with apps like Codekit. And while those are great, they don&#8217;t always work nicely with whatever apps your coworkers are using. That&#8217;s where Grunt JS shines.</p>

	<h2>What I Was Doing</h2>

	<p>Because I had mostly been working by myself on things, I was running CodeKit or even <span class="caps">SASS</span>/Compass from the command line. It works, obviously, but when your teammates want to run something else, like Prepros, for example, not all apps build things the same way.</p>

	<p>Sometimes it was a minor difference. The first thing we noticed, for example, was that one of our apps was adding in line-numbers while the other one was not. It’s fine, until you work in a shared Git repo and suddenly those line numbers are all changes that need to be merged.</p>

	<p>Or in some cases, because I was using CodeKit to also minify my JavaScript and lint it for errors, we would run into differences in which files were being included at what points. So while it worked fine for me, my coworkers were throwing errors because one library was being included before jQuery, or it just wasn’t being pulled in at all. </p>

	<p>It was a mess, an actual mess. </p>

	<h2>Enter GruntJS</h2>

	<p>I had heard things about Grunt, but I wasn’t buying into the hype. Until I got really frustrated one night and decided that it was either give it a shot or hate working with pre-processors and minify everything by hand. </p>

	<p>Within an hour, I was up and running on Grunt. I now use it for every last project because, well, I have too much to do to fight inconsistencies with teammates. (Totally not their fault.)</p>

	<h2>Configuring Grunt</h2>

	<p>I won’t get into the install steps, because the Grunt site does that rather well: <a href=“http://gruntjs.com/getting-started”>Getting Started</a>. </p>

	<p>But what might be more useful is to show how my Grunt file is helping me.</p>

<pre><code>module.exports = function(grunt) {
	&#39;use strict&#39;;
	grunt.initConfig({
		pkg: grunt.file.readJSON(&#39;package.json&#39;),
		concat: {
			options: {
				separator: &#39;;&#39;
			},
			dist: {
				src: [&#39;/_js/jquery.js&#39;, &#39;/_js/handlebars.js&#39;, &#39;/_js/raphael.js&#39;, &#39;/v10/_js/g.raphael.js&#39;, &#39;/_js/g.line.js&#39;, &#39;/_js/interaction.js&#39;],
				dest: /_js/interaction.min.js&#39;
			}
		},
		jslint: { // configure the task
			// lint your project&#39;s client code
			client: {
				src: [
				&#39;/_js/interaction.js&#39;
				],
				directives: {
					browser: true,
					predef: [
					&#39;jQuery&#39;
					]
				},
				options: {
					junit: &#39;out/client-junit.xml&#39;
				}
			}
		},
		sass: {
			dist: {
				files: {
					&#39;/_css/screen.css&#39;: &#39;/_css/screen.scss&#39;
				}
			}
		},
		uglify: {
			options: {
				banner: &#39;/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today(&quot;dd-mm-yyyy&quot;) %&gt; */\n&#39;
			},
			dist: {
				files: {
					&#39;/_js/interaction.min.js&#39;: [&#39;/_js/interaction.min.js&#39;]
				}
			}
		},
		watch: {
			files: [&#39;/_js/interaction.js&#39;, &#39;/_css/*.scss&#39;],
			tasks: [&#39;concat&#39;, &#39;uglify&#39;, &#39;sass&#39;]
		}
	});
	grunt.loadNpmTasks(&#39;grunt-contrib-concat&#39;);
	grunt.loadNpmTasks(&#39;grunt-contrib-uglify&#39;);
	grunt.loadNpmTasks(&#39;grunt-contrib-watch&#39;);
	grunt.loadNpmTasks(&#39;grunt-contrib-sass&#39;);
	grunt.loadNpmTasks(&#39;grunt-jslint&#39;);
	grunt.registerTask(&#39;default&#39;, [&#39;concat&#39;, &#39;uglify&#39;, &#39;sass&#39;]);
	grunt.registerTask(&#39;tests&#39;, [&#39;jslint&#39;]);
};
</code></pre>

	<h2>Grunt and Concatenation</h2>

	<p>To break that down, there’s a bit of configuration before we get to this important bit here:</p>

<pre><code>concat: {
	options: {
		separator: &#39;;&#39;
	},
	dist: {
		src: [‘/_js/jquery.js&#39;, &#39;/_js/handlebars.js&#39;, &#39;/_js/raphael.js&#39;, ‘/_js/g.raphael.js&#39;, &#39;/_js/g.line.js&#39;, &#39;/_js/interaction.js&#39;],
		dest: &#39;/_js/interaction.min.js&#39;
		}
	},
</code></pre>

	<p>As you might have guessed, that’s the concatenation function. It grabs everything listed in the “src” array and uses it to create interaction.min.js. If you were to run just that, it would be as if you manually copied and pasted all those files into one, large JavaScript file. </p>

	<p>Next up, we have the <span class="caps">JSL</span>int plugin which opens up just my custom JavaScript file, and looks for errors or syntax issues. A point of consideration here is that I’m working only with the &#8220;client&#8221; code block. If you’re a NodeJS developer, (you probably already use Grunt), but you can also separate your server code to be linted. </p>

	<h2>Grunt and <span class="caps">SASS</span></h2>

	<p>The <span class="caps">SASS</span> section caught me a bit off guard at first, because it reads backwards to me, but it looks like this:</p>

<pre><code>sass: {
	dist: {
		files: {
			&#39;/_css/screen.css&#39;: &#39;/_css/screen.scss&#39;
		}
	}
},
</code></pre>

	<p>All it’s doing is taking that second file (/_css/screen.scss’) and using compiling it to the first (/_css/screen.css). Now for me, I have a bunch of other <span class="caps">SCSS</span> and <span class="caps">CSS</span> files that I include in screen.scss, but they don’t need to be pre-compiled. So this is the extent of it.</p>

	<h2>Grunt and JavaScript Minification</h2>

	<p>The next function is Uglify, which is this block:</p>

<pre><code>uglify: {
	options: {
		banner: &#39;/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today(&quot;dd-mm-yyyy&quot;) %&gt; */\n&#39;
	},
	dist: {
		files: {
			&#39;/_js/interaction.min.js&#39;: [&#39;/_js/interaction.min.js&#39;]
		}
	}
},
</code></pre>

	<p>The options section just creates a stamp at the top of your file, in this case I have the package name and the timestamp for today. But the &#8220;dist&#8221; section is the important part. In the concat function, we’re building interaction.js into interaction.min.js, which until this function runs, isn’t actually minified. If I were to point this function at interaction.js, it would minify my source, and that would be awful to maintain. So all we&#8217;re doing is taking that temporary file from above and minifying it instead.</p>

	<h2>Watching for Changes</h2>

	<p>And lastly, we have the watch section:</p>

<pre><code>watch: {
	files: [&#39;/_js/interaction.js&#39;, &#39;/_css/*.scss&#39;],
	tasks: [‘concat&#39;, &#39;uglify&#39;, &#39;sass&#39;]
}
</code></pre>

	<p>All this does, is keep an eye on anything listed in the &#8220;files&#8221; array for changes. If any of them change, it runs the other functions in order. (Concat, uglify, <span class="caps">SASS</span>). And this is key here. If you were to switch concat and uglify, you’d always see unminified code. And, if you’re only working on the <span class="caps">CSS</span> side of your project at any given time, you can move &#8220;sass&#8221; to the front of the list and have your output faster.</p>

	<p>After the functions are all defined, we get to some Grunt commands that load the actual modules to do the work, but the last bit of importance for us is this:</p>

<pre><code>grunt.registerTask(&#39;default&#39;, [&#39;concat&#39;, &#39;uglify&#39;, &#39;sass&#39;]);
	grunt.registerTask(&#39;tests&#39;, [&#39;jslint&#39;]);
</code></pre>

	<p>The first line instructs what should happen if I were to run Grunt without any other options. It would roll through concat, uglify, and sass, just like in the watch function. The second line, only runs the <span class="caps">JSL</span>int function. Personally, I don’t like to have <span class="caps">JSL</span>int yelling at me every time I need to compile the scripts, or worse, <span class="caps">CSS</span>. Sublime text can already do basic linting as I write.</p>

	<h2>Running Grunt</h2>

	<p>Now, once this file is in place, I can open terminal and find the root of my project. Then, it&#8217;s just as easy as typing &#8220;grunt.&#8221; Doing that would load the default function. But, I don’t do that very often since I’d have to do it over and over again. Instead, I usually run:</p>

<pre><code>grunt watch
</code></pre>

	<p>That invokes the watch function and keeps an eye on the JS and <span class="caps">SCSS</span> files I work with. </p>

	<p>And while there’s a lot more you can do with Grunt, I personally don’t need anything more than this. I’m sure as I get deeper into Angular JS and Node JS that will change, but for now, I’m content with just having a way to get my whole team onto the same page without conflict over the files we work with most often. </p>

]]>

</description>
<link>http://davidnbrooks.com/journal/better-team-projects-with-grunt-js</link>
<pubDate>Thu, 10 Jul 2014 08:07:13 EST</pubDate>
<dc:creator>David Brooks</dc:creator>
<guid>http://davidnbrooks.com/journal/better-team-projects-with-grunt-js</guid>

</item>

<atom:link href="http://www.davidnbrooks.com/journal" rel="self" type="application/rss+xml" />

</channel> 
</rss>