<?xml version="1.0"?>
<News hasArchived="true" page="8514" pageCount="10809" pageSize="10" timestamp="Mon, 14 Sep 2026 09:15:01 -0400" url="https://my3.my.umbc.edu/posts.xml?mode=recent&amp;page=8514">
<NewsItem contentIssues="true" id="33877" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33877">
<Title>What type of technology is available in Math/Psychology Rooms 101 &#8211; 106?</Title>
<Body>
<![CDATA[
    <div class="html-content"><div>    <p>
            Page
                <strong>edited</strong> by
                        <a href="https://wiki.umbc.edu/display/~amocko1%0A" rel="nofollow external" class="bo">Andrea Mocko</a>
                </p>
            <div>
            <div><div>
    <div><div>
    <h2>Show Me</h2>
    <p><a href="http://www.youtube.com/watch?v=Gb1V02Pqrvg" rel="nofollow external" class="bo"><img src="http://img.youtube.com/vi/Gb1V02Pqrvg/1.jpg" style="max-width: 100%; height: auto;"></a></p>
    <p>Video Length - 01:50</p>
    <h2>Tell Me</h2>
    <ol>
    <li>The Control is located on the left-hand side of the screen as you face it. Press the "ON" button which will flash as the projector warms up</li>
    <li>Wait for ceiling mounted projector to warm up then select your Source</li>
    <li>Plug in your Laptop to the provided VGA Cable and start your Laptop</li>
    </ol>
    <div><table><tbody>
    <tr>
    <td><div><img height="225" width="300" src="http://www.umbc.edu/oit/classroomtechnology/instructions/MP/MP_1.jpg" style="max-width: 100%; height: auto;"></div></td>
    <td><div><img height="225" width="300" src="http://www.umbc.edu/oit/classroomtechnology/instructions/MP/MP_2.jpg" style="max-width: 100%; height: auto;"></div></td>
    </tr>
    <tr>
    <td><div><img height="225" width="300" src="http://www.umbc.edu/oit/classroomtechnology/instructions/MP/MP_3.jpg" style="max-width: 100%; height: auto;"></div></td>
    <td><div><img height="225" width="300" src="http://www.umbc.edu/oit/classroomtechnology/instructions/MP/MP_4.jpg" style="max-width: 100%; height: auto;"></div></td>
    </tr>
    </tbody></table></div>
    <p>4. Press and hold Display ON button for 2 seconds.<br>5. WAIT 30-60 seconds for projector to warm up.<br>6. Choose desired input (PC, VCR/DVD, HDMI).<br>7. Attach appropriate cable to your external device or load DVD/VHS media.<br>8. Volume is adjusted by knob under Display power buttons.<br>9. When done, press and hold Display OFF button for 2 seconds.</p>
    <h2>Rate this Article</h2>
    <p>
    
    
    
    
    <strong>Was this helpful?</strong>
    <a href="https://apps-my.umbc.edu/apps/rt-track/script.php?u=http://wiki.umbc.edu%2Fpages%2Fviewpage.action%3FpageId%3D31198069&amp;q=0&amp;v=1&amp;s=faq&amp;l=" rel="nofollow external" class="bo">Yes</a>
     | <a href="https://docs.google.com/a/umbc.edu/spreadsheet/viewform?formkey=dEpyOEZxa29QY05BaVpBVzZSYmRMM0E6MA&amp;entry_15=http%3A%2F%2Fwiki.umbc.edu%2Fpages%2Fviewpage.action%3FpageId%3D31198069" rel="nofollow external" class="bo">No</a>
     | <a href="https://docs.google.com/a/umbc.edu/spreadsheet/viewform?formkey=dEpyOEZxa29QY05BaVpBVzZSYmRMM0E6MA&amp;entry_15=http%3A%2F%2Fwiki.umbc.edu%2Fpages%2Fviewpage.action%3FpageId%3D31198069" rel="nofollow external" class="bo">Correct or Suggest an Article</a>
     | <a href="https://apps-my.umbc.edu/apps/rt-track/script.php?u=http://wiki.umbc.edu%2Fpages%2Fviewpage.action%3FpageId%3D31198069&amp;q=0&amp;v=0&amp;s=faq&amp;l=" rel="nofollow external" class="bo">Request Help</a></p>
    </div></div>
    <div><div>
    <div>
    <div><strong>What These Rooms Can Do:</strong></div>
    <div>
    <ul>
    <li>Project user’s laptop/tablet video using either VGA or HDMI cable; audio via mini audio cable</li>
    <li>Project DVD and VHS media</li>
    <li>The large rooms have an IR microphone attached to a charging cable in the drawer. (MP101, 103, 104, 106)</li>
    </ul>
    </div>
    </div>
    <p> </p>
    </div></div>
    </div></div>
        </div>
            <div>
           <a href="https://wiki.umbc.edu/pages/viewpage.action?pageId=31198069" rel="nofollow external" class="bo">View Online</a>
                  ·
           <a href="https://wiki.umbc.edu/pages/diffpagesbyversion.action?pageId=31198069&amp;revisedVersion=4&amp;originalVersion=3" rel="nofollow external" class="bo">View Changes Online</a>       
                      </div>
    </div></div>
]]>
</Body>
<Summary>Page             edited by                     Andrea Mocko                                      Show Me    Video Length - 01:50  Tell Me   The Control is located on the left-hand side of the...</Summary>
<Website>https://wiki.umbc.edu/pages/viewpage.action?pageId=31198069</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33877/guest@my.umbc.edu/1256998ec73b09d1f5a41d763644abf3/api/pixel</TrackingUrl>
<Tag>faq</Tag>
<Group token="retired-428">UMBC FAQ</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-428</GroupUrl>
<AvatarUrl>https://assets4-my.umbc.edu/images/avatars/group/1/xsmall.png?1789141848</AvatarUrl>
<AvatarUrl size="original">https://assets2-my.umbc.edu/images/avatars/group/1/original.png?1789141848</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets3-my.umbc.edu/images/avatars/group/1/xxlarge.png?1789141848</AvatarUrl>
<AvatarUrl size="xlarge">https://assets2-my.umbc.edu/images/avatars/group/1/xlarge.png?1789141848</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/images/avatars/group/1/large.png?1789141848</AvatarUrl>
<AvatarUrl size="medium">https://assets4-my.umbc.edu/images/avatars/group/1/medium.png?1789141848</AvatarUrl>
<AvatarUrl size="small">https://assets1-my.umbc.edu/images/avatars/group/1/small.png?1789141848</AvatarUrl>
<AvatarUrl size="xsmall">https://assets4-my.umbc.edu/images/avatars/group/1/xsmall.png?1789141848</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/images/avatars/group/1/xxsmall.png?1789141848</AvatarUrl>
<Sponsor>UMBC FAQ</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 11:38:54 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33881" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33881">
<Title>Turn HTML and CSS into a hosted CMS in seconds</Title>
<Body>
<![CDATA[
    <div class="html-content">Place your code into Dropbox and Cloud Cannon fixes it so your clients can add content and edit their live site<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.netmagazine.com%2Fnews%2Fturn-html-and-css-hosted-cms-seconds-132948&amp;t=Turn+HTML+and+CSS+into+a+hosted+CMS+in+seconds" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.netmagazine.com%2Fnews%2Fturn-html-and-css-hosted-cms-seconds-132948&amp;t=Turn+HTML+and+CSS+into+a+hosted+CMS+in+seconds" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.netmagazine.com%2Fnews%2Fturn-html-and-css-hosted-cms-seconds-132948&amp;t=Turn+HTML+and+CSS+into+a+hosted+CMS+in+seconds" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.netmagazine.com%2Fnews%2Fturn-html-and-css-hosted-cms-seconds-132948&amp;t=Turn+HTML+and+CSS+into+a+hosted+CMS+in+seconds" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.netmagazine.com%2Fnews%2Fturn-html-and-css-hosted-cms-seconds-132948&amp;t=Turn+HTML+and+CSS+into+a+hosted+CMS+in+seconds" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/173607679357/u/49/f/502346/c/32632/s/2fc40c28/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/173607679357/u/49/f/502346/c/32632/s/2fc40c28/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Place your code into Dropbox and Cloud Cannon fixes it so your clients can add content and edit their live site      </Summary>
<Website>http://feedproxy.google.com/~r/net/topstories/~3/NXnxQoQ3t7k/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33881/guest@my.umbc.edu/44ac84304e26bb7552a39cd2dfcb164d/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>net</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 11:26:38 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33874" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33874">
<Title>Free Download: Flattastic UI kit</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><img alt="thumbnail" src="http://netdna.webdesignerdepot.com/uploads/2013/08/thumbnail3.jpg" width="200" height="160" style="max-width: 100%; height: auto;">Give your flat design a boost with this Flattastic UI kit, designed by <a href="http://vladedimovski.com/" rel="nofollow external" class="bo">Vlade Dimovski,</a> free to download and simple to use.</p> <p>The PSD is properly layered, with intuitive naming, making modifying it for your own projects a synch.</p> <p>The design features four pairs of complimentary colors perfect for any flat design: bittersweet, which is #FC6E51 and #E9573F; lavender, which is #AC92EC and #967ADC; grass, which is #A0D468 and #8CC152; and aqua, which is #4FC1E9 and #3BAFDA. But of course, download the PSD and you won’t need the hex codes, just use your trusty eyedropper tool!</p> <p>The design uses Open Sans, which is free for use from <a href="http://www.google.com/fonts/" rel="nofollow external" class="bo">Google Web Fonts</a> and the icons provided work beautifully with it (note: photos are not included).</p> <p>Download the kit below and start playing. If you enjoy it, you might want to take a look at the <a href="http://graphicriver.net/item/flattastic-pro/5200080?ref=vladedimovski" rel="nofollow external" class="bo">premium version</a> too.</p> <p><img src="http://netdna.webdesignerdepot.com/uploads/2013/08/flattastic-free.jpg" width="650" alt="Free Download: Flattastic UI kit" style="max-width: 100%; height: auto;"></p> <p> </p> <p><em><strong>Have you used the Flatastic UI kit for a project? What other UI elements would you like to see included? Let us know in the comments. </strong></em></p> <div>
    <div> <a href="/widget/pay-tweet.php?refID=wdd_flattastic&amp;code=d3f4f687cff5112984f898f11ef4f8c6&amp;post_id=57095&amp;msg=Free+Download%3A+Flattastic+UI+kit+http%3A%2F%2Fbit.ly%2F17ckEyx" rel="nofollow external" class="bo">Pay with a Tweet</a> </div> <div> <a rel="nofollow external" class="bo">Download now</a> </div> <div> <p>Please enter your email address below and click the download button. The download link will be sent to you by email, or if you have already subscribed, the download will begin immediately.</p>       <div>I agree to receive exclusive deals from <a href="http://www.MightyDeals.com" rel="nofollow external" class="bo"><span>MightyDeals.com</span></a> and monthly/weekly newsletters from <a href="http://www.WebdesignerDepot.com" rel="nofollow external" class="bo"><span>WebdesignerDepot.com</span></a>. Unsubscribe at any time. Your email will not be sold/rented.</div>   <div>         </div>  <div><img src="http://forms.aweber.com/form/displays.htm?id=jJwczBwMnIwMrA==" alt="" style="max-width: 100%; height: auto;"></div>  </div>   </div> <p><br><br> </p>
    <table width="100%"> <tbody>
    <tr> <td> <a href="http://www.mightydeals.com/deal/inventicons-design-bundle.html?ref=inwidget" rel="nofollow external" class="bo"><strong>Mega Design Bundle from Inventicons – only $49! </strong></a> </td> <td> <a href="http://www.mightydeals.com/?ref=inwidget" rel="nofollow external" class="bo"><br> <img src="http://mightydeals.com/web/images/widget-logo.png" height="40" width="90" alt="Free Download: Flattastic UI kit" style="max-width: 100%; height: auto;"><br> </a> </td> </tr> </tbody>
    </table> <p><br> </p> <a href="http://www.webdesignerdepot.com/2013/08/free-download-flattastic-ui-kit/" rel="nofollow external" class="bo">Source</a> <br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F08%2Ffree-download-flattastic-ui-kit%2F&amp;t=Free+Download%3A+Flattastic+UI+kit" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F08%2Ffree-download-flattastic-ui-kit%2F&amp;t=Free+Download%3A+Flattastic+UI+kit" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F08%2Ffree-download-flattastic-ui-kit%2F&amp;t=Free+Download%3A+Flattastic+UI+kit" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F08%2Ffree-download-flattastic-ui-kit%2F&amp;t=Free+Download%3A+Flattastic+UI+kit" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.webdesignerdepot.com%2F2013%2F08%2Ffree-download-flattastic-ui-kit%2F&amp;t=Free+Download%3A+Flattastic+UI+kit" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/173607726590/u/49/f/661066/c/35285/s/2fc325ec/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/173607726590/u/49/f/661066/c/35285/s/2fc325ec/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Give your flat design a boost with this Flattastic UI kit, designed by Vlade Dimovski, free to download and simple to use.   The PSD is properly layered, with intuitive naming, making modifying it...</Summary>
<Website>http://rss.feedsportal.com/c/35285/f/661066/s/2fc325ec/sc/4/l/0L0Swebdesignerdepot0N0C20A130C0A80Cfree0Edownload0Eflattastic0Eui0Ekit0C/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33874/guest@my.umbc.edu/79a589a4a9cf3eabbbf82e5c01b4592a/api/pixel</TrackingUrl>
<Tag>art</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>flat-design</Tag>
<Tag>flat-ui-kit</Tag>
<Tag>flatastic</Tag>
<Tag>free-flat-design-resources</Tag>
<Tag>free-ui-kits</Tag>
<Tag>freebies</Tag>
<Tag>html</Tag>
<Tag>html5</Tag>
<Tag>illustrator</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>oracle</Tag>
<Tag>photoshop</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 10:15:16 -0400</PostedAt>
<EditAt>Fri, 09 Aug 2013 10:15:16 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="33878" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33878">
<Title>The client as a user</Title>
<Body>
<![CDATA[
    <div class="html-content">Ren Walker says we must learn to balance user and business goals for user-centred design<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fclient-user&amp;t=The+client+as+a+user" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fclient-user&amp;t=The+client+as+a+user" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fclient-user&amp;t=The+client+as+a+user" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fclient-user&amp;t=The+client+as+a+user" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.netmagazine.com%2Ffeatures%2Fclient-user&amp;t=The+client+as+a+user" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/173607653236/u/49/f/502346/c/32632/s/2fc340af/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/173607653236/u/49/f/502346/c/32632/s/2fc340af/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Ren Walker says we must learn to balance user and business goals for user-centred design      </Summary>
<Website>http://feedproxy.google.com/~r/net/topstories/~3/d4kGgeUfIDE/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33878/guest@my.umbc.edu/ffc2c418120fb14022616f969c0a42bf/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>net</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 10:09:27 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33871" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33871">
<Title>Network Analysis Reveals World's Most Influential Thinkers</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Want to become a leading thinker? A new network analysis reveals the thinkers who most influence the rest of us and suggests ways to join this elite list</p>
    <p><img src="https://www.technologyreview.com/sites/default/files/images/Thinkers.png" alt="" width="268" height="275" style="max-width: 100%; height: auto;"></p>
    </div>
]]>
</Body>
<Summary>Want to become a leading thinker? A new network analysis reveals the thinkers who most influence the rest of us and suggests ways to join this elite list</Summary>
<Website>http://www.technologyreview.com/view/518026/network-analysis-reveals-worlds-most-influential-thinkers/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33871/guest@my.umbc.edu/29cb4e1c7dfe40c95692a03279718248/api/pixel</TrackingUrl>
<Tag>development</Tag>
<Tag>internet</Tag>
<Tag>mit</Tag>
<Tag>technology</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 10:08:21 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33872" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33872">
<Title>Implementing Custom Domains on Roon</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Recently, I launched a product with my friend <a href="https://twitter.com/drewwilson.com" rel="nofollow external" class="bo">Drew Wilson</a> called <a href="https://roon.io" rel="nofollow external" class="bo">Roon</a>. It’s a really simple and beautiful blogging platform. Roon has a web app, iOS app, and API. I thought it would be good to write some about how I built various pieces of Roon’s infrastructure.</p>
    <p>A few weeks ago, <a href="http://blog.roon.io/custom-domain" rel="nofollow external" class="bo">we rolled out custom domain support</a>. This allows people to pay a yearly fee to have the option to use a custom domain instead of something like <a href="http://sam.roon.io" rel="nofollow external" class="bo">sam.roon.io</a>. A few folks on Twitter replied with stuff like “I have no idea how you would even begin to implement something like that”. It’s actually surprisingly easier than you’d think.</p>
    <p>First, a little about Roon’s infrastructure. It’s a Rails app running on Heroku. It’s decently straight forward as most blogging apps are. I really wanted to stay on Heroku so I don’t have to manage servers and such. Even though we’re on <a href="http://heroku.com" rel="nofollow external" class="bo">Heroku</a>, it’s still pretty easy to add custom domains.</p>
    <p>We implemented <a href="http://stripe.com" rel="nofollow external" class="bo">Stripe</a> so we can take money from people that want to enable this add-on. (Maybe in the future I’ll write more about that if that’s interesting. Let me know <a href="https://twitter.com/soffes" rel="nofollow external" class="bo">on Twitter</a>.) Once a user has paid for the feature, we enable an extra field in the settings to let them input a custom domain. Nothing crazy here.</p>
    <p>Once they have paid, we use the <a href="https://devcenter.heroku.com/articles/platform-api-reference" rel="nofollow external" class="bo">Heroku API</a> to add their custom domain to our app on Heroku and setup some redirects for their old subdomain. Pretty simple. I’ll walk you through the code.</p>
    <p>In the Blog model, we do a few things. First, I include the `ActiveModel::Dirty` mixin so it’s easy to see if the user changed their custom domain. Next, I simply add a `before_save` callback to check if they have changed their custom domain. If the user has changed their custom domain, I fire off a <a href="http://sidekiq.org" rel="nofollow external" class="bo">Sidekiq</a> worker to add or remove domains. Here’s the code:</p>
    <pre>include ActiveModel::Dirty&#x000A;    &#x000A;    before_save :add_custom_domain&#x000A;    &#x000A;    def add_custom_domain&#x000A;      # Only run the worker if they have changed their domain and&#x000A;      # if we have the Heroku API token environment variable set.&#x000A;      if custom_domain_changed? &amp;&amp; ENV['HEROKU_API_TOKEN']&#x000A;        # The same worker adds and removes domains&#x000A;        CustomDomainWorker.perform_async('add' =&gt; custom_domain, 'remove' =&gt; custom_domain_was)&#x000A;      end&#x000A;    end</pre>
    <p>All pretty straight forward. Obviously there’s some validation to make sure it’s a valid domain, it’s not a domain they’re not allowed to use, and that they’ve paid for the add-on.</p>
    <p>The worker to do the actual work is pretty simple too. All this does is hit the Heroku API and add or remove domains. Here’s the code:</p>
    <pre># Setup some exceptions so we can see more information errors when things fail&#x000A;    class FailedToAddDomainToHeroku &lt; Exception; end&#x000A;    class FailedToRemoveDomainToHeroku &lt; Exception; end&#x000A;    &#x000A;    class CustomDomainWorker&#x000A;      include Sidekiq::Worker&#x000A;      include Sidekiq::Logging&#x000A;    &#x000A;      # Don't retry if things fail because it will probably always fail. This&#x000A;      # may or may not be the best idea.&#x000A;      sidekiq_options retry: false&#x000A;    &#x000A;      # Setup the logger so we can get more info from the workers&#x000A;      def initialize&#x000A;        logger.level = Logger::INFO&#x000A;      end&#x000A;    &#x000A;      # This is the main method the worker calls&#x000A;      def perform(domains)&#x000A;        # Grab the API token from the environment variable&#x000A;        @api_token = ENV['HEROKU_API_TOKEN']&#x000A;    &#x000A;        # Add a domain&#x000A;        add = domains['add']&#x000A;        if add &amp;&amp; add.length &gt; 0&#x000A;          logger.info "Adding #{add}"&#x000A;          add_domain(add)&#x000A;        end&#x000A;    &#x000A;        # Remove a domain&#x000A;        remove = domains['remove']&#x000A;        if remove &amp;&amp; remove.length &gt; 0&#x000A;          logger.info "Removing #{remove}"&#x000A;          remove_domain(remove)&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      # Add a domain to heroku&#x000A;      def add_domain(domain)&#x000A;        # Make a POST request to add the domain&#x000A;        response = HTTParty.post '<a href="https://api.heroku.com/apps/roon/domains">https://api.heroku.com/apps/roon/domains</a>', headers: {&#x000A;          'Authorization' =&gt; @api_token,&#x000A;          'Accept' =&gt; 'application/vnd.heroku+json; version=3',&#x000A;          'Content-Type' =&gt; 'application/json'&#x000A;        }, body: {&#x000A;          hostname: domain&#x000A;        }.to_json&#x000A;    &#x000A;        logger.info response.body&#x000A;    &#x000A;        # If it wasn't a created response code, it failed. &#x000A;        unless response.code == 201&#x000A;          raise FailedToAddDomainToHeroku, JSON(response.body)['message'] and return&#x000A;        end&#x000A;    &#x000A;        logger.info "Added #{domain} to Heroku"&#x000A;      end&#x000A;    &#x000A;      # Remove a domain&#x000A;      def remove_domain(domain)&#x000A;        # Make a DELETE request to the domain&#x000A;        response = HTTParty.delete "<a href="https://api.heroku.com/apps/roon/domains/#%7Bdomain%7D">https://api.heroku.com/apps/roon/domains/#{domain}</a>", headers: {&#x000A;          'Authorization' =&gt; @api_token,&#x000A;          'Accept' =&gt; 'application/vnd.heroku+json; version=3',&#x000A;        }&#x000A;    &#x000A;        # It failed if it wasn't a 200&#x000A;        unless response.code == 200&#x000A;          raise FailedToAddDomainToHeroku, JSON(response.body)['message'] and return&#x000A;        end&#x000A;    &#x000A;        logger.info "Removed #{domain} from Heroku"&#x000A;      end&#x000A;    end</pre>
    <p>So overall, it’s pretty simple. If you’re unfamiliar with Sidekiq or other queueing system, I highly recommend learning about them. Making network requests to third-party services should be done in the background if possible. You don’t want to make your other requests slow if you’re waiting on something like Twitter, Facebook, Heroku, etc.</p>
    <p>Anyway, custom domains are pretty easy to support. Hopefully that was helpful! Go make stuff.</p>
    <p>The post <a href="http://blog.teamtreehouse.com/implementing-custom-domains-on-roon" rel="nofollow external" class="bo">Implementing Custom Domains on Roon</a> appeared first on <a href="http://blog.teamtreehouse.com" rel="nofollow external" class="bo">Treehouse Blog</a>.</p>
    </div>
]]>
</Body>
<Summary>Recently, I launched a product with my friend Drew Wilson called Roon. It’s a really simple and beautiful blogging platform. Roon has a web app, iOS app, and API. I thought it would be good to...</Summary>
<Website>http://feedproxy.google.com/~r/teamtreehouse/~3/BkCaUPpFxtM/implementing-custom-domains-on-roon</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33872/guest@my.umbc.edu/98ef984a9a2c8160a8f2814cca2fd316/api/pixel</TrackingUrl>
<Tag>android</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>ios</Tag>
<Tag>javascript</Tag>
<Tag>learn-to-code</Tag>
<Tag>responsive</Tag>
<Tag>web</Tag>
<Tag>web-apps</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 10:00:30 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33868" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33868">
<Title>DealBook: America Movil Offers to Buy Dutch Phone Company KPN</Title>
<Body>
<![CDATA[
    <div class="html-content">The phone giant owned by the Mexican billionaire Carlos Slim Helú offered to buy the remaining 70 percent stake in the Dutch cellphone operator KPN that it does not already own.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2013%2F08%2F09%2Famerica-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+America+Movil+Offers+to+Buy+Dutch+Phone+Company+KPN" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2013%2F08%2F09%2Famerica-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+America+Movil+Offers+to+Buy+Dutch+Phone+Company+KPN" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2013%2F08%2F09%2Famerica-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+America+Movil+Offers+to+Buy+Dutch+Phone+Company+KPN" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2013%2F08%2F09%2Famerica-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+America+Movil+Offers+to+Buy+Dutch+Phone+Company+KPN" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2013%2F08%2F09%2Famerica-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+America+Movil+Offers+to+Buy+Dutch+Phone+Company+KPN" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/173607730226/u/0/f/640387/c/34625/s/2fc19f4c/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/173607730226/u/0/f/640387/c/34625/s/2fc19f4c/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>The phone giant owned by the Mexican billionaire Carlos Slim Helú offered to buy the remaining 70 percent stake in the Dutch cellphone operator KPN that it does not already own.      </Summary>
<Website>http://dealbook.nytimes.com/2013/08/09/america-movil-offers-9-6-billion-for-dutch-cellphone-operator-kpn/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33868/guest@my.umbc.edu/6d32a44f1324299399bbae0cf1b9a7c2/api/pixel</TrackingUrl>
<Tag>america-movil-sab-de-cv</Tag>
<Tag>america-movil-sab-de-cv-amx-nyse</Tag>
<Tag>koninklijke-kpn-nv</Tag>
<Tag>mergers-acquisitions-and-divestitures</Tag>
<Tag>mergers-and-acquisitions</Tag>
<Tag>new</Tag>
<Tag>slim-helu-carlos</Tag>
<Tag>technology</Tag>
<Tag>telecommunications</Tag>
<Tag>telefonica-sa</Tag>
<Tag>telefonica-sa-tef-nyse</Tag>
<Tag>top-headline-2</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 07:21:52 -0400</PostedAt>
<EditAt>Fri, 09 Aug 2013 21:47:19 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="33867" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33867">
<Title>Building a web app with Ruby on Rails</Title>
<Body>
<![CDATA[
    <div class="html-content">If you're having trouble deciding between Sinatra and Rails, Tim Millwood can help<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.netmagazine.com%2Ftutorials%2Fbuilding-web-app-ruby-rails&amp;t=Building+a+web+app+with+Ruby+on+Rails" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fwww.netmagazine.com%2Ftutorials%2Fbuilding-web-app-ruby-rails&amp;t=Building+a+web+app+with+Ruby+on+Rails" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fwww.netmagazine.com%2Ftutorials%2Fbuilding-web-app-ruby-rails&amp;t=Building+a+web+app+with+Ruby+on+Rails" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fwww.netmagazine.com%2Ftutorials%2Fbuilding-web-app-ruby-rails&amp;t=Building+a+web+app+with+Ruby+on+Rails" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fwww.netmagazine.com%2Ftutorials%2Fbuilding-web-app-ruby-rails&amp;t=Building+a+web+app+with+Ruby+on+Rails" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/173607645436/u/49/f/502346/c/32632/s/2fc14e8c/kg/391/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/173607645436/u/49/f/502346/c/32632/s/2fc14e8c/kg/391/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>If you're having trouble deciding between Sinatra and Rails, Tim Millwood can help      </Summary>
<Website>http://feedproxy.google.com/~r/net/topstories/~3/g9jOqysaZpU/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33867/guest@my.umbc.edu/5819e1592732b5f6f89d341b2c54d894/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>net</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 06:21:00 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33866" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33866">
<Title>Free Flat Icons</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><a href="http://sixrevisions.com/freebies/icons/flat-icons-free/" rel="nofollow external" class="bo"><img src="http://cdn.sixrevisions.com/0366-01_flat_icons_free_thumbnail.png" width="550" height="200" alt="Free Flat Icons" style="max-width: 100%; height: auto;"></a></p>
    <p>This is a <strong>free flat icon set</strong> that embodies the recently popular Flat Design aesthetic. This freebie containing <strong>10 icons</strong> is provided to you in <strong>PNG</strong> and <strong>PSD</strong> formats.</p>
    <p></p>
    <p>These free icons were designed exclusively for Six Revisions by the design team at <a href="http://www.whoishostingthis.com/" rel="nofollow external" class="bo">WhoIsHostingThis.com</a>.</p>
    <h3>Preview</h3>
    <p><img src="http://cdn.sixrevisions.com/0366-02_flat_icons_free_preview.png" width="550" height="367" alt="Free Flat Icons" style="max-width: 100%; height: auto;"></p>
    <h3>Download</h3>
    <ul>
    <li>
    <a href="http://cdn.sixrevisions.com/0366-03_flat_icons_free.zip" rel="nofollow external" class="bo">Flat Icons Free</a> (ZIP, 404 KB)</li>
    </ul>
    <h3>Related Content</h3>
    <ul>
    <li><a href="http://sixrevisions.com/freebies/icons/free-icons-1000/" rel="nofollow external" class="bo">Ultimate Free Icon Set: 1000 Free Icons</a></li>
    <li><a href="http://sixrevisions.com/freebies/icons/375-retina-display-ready-icons/" rel="nofollow external" class="bo">Free Icon Pack: 375 Retina-Display-Ready Icons</a></li>
    <li><a href="http://sixrevisions.com/freebies/icons/socialmate-free/" rel="nofollow external" class="bo">SocialMate: 28 Free Social Media Icons (Includes PSDs)</a></li>
    <li>
    <em>Related categories</em>: <a href="http://sixrevisions.com/category/freebies/" rel="nofollow external" class="bo">Freebies</a> and <a href="http://sixrevisions.com/category/resources/" rel="nofollow external" class="bo">Resources</a>
    </li>
    </ul>
    <h3>About the Author</h3>
    <p><img src="http://cdn.sixrevisions.com/authors/amie_andrews_small.jpg" alt="" width="80" height="80" style="max-width: 100%; height: auto;"><strong>Amie Andrews</strong> is a web fanatic working at <a href="http://www.whoishostingthis.com/" rel="nofollow external" class="bo">WhoIsHostingThis.com</a> where she manages the design and marketing team on creative projects. WhoIsHostingThis.com is a webmaster tool that lets you discover which web hosting company any site is hosted with. To find out more about the company’s work, visit their <a href="http://www.whoishostingthis.com/blog/" rel="nofollow external" class="bo">blog</a>.</p>
    <p>The post <a href="http://sixrevisions.com/freebies/icons/flat-icons-free/" rel="nofollow external" class="bo">Free Flat Icons</a> appeared first on <a href="http://sixrevisions.com" rel="nofollow external" class="bo">Six Revisions</a>.</p>
    </div>
]]>
</Body>
<Summary>This is a free flat icon set that embodies the recently popular Flat Design aesthetic. This freebie containing 10 icons is provided to you in PNG and PSD formats.     These free icons were...</Summary>
<Website>http://feedproxy.google.com/~r/SixRevisions/~3/bTIdURTzNQo/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33866/guest@my.umbc.edu/6bbaafcdedcfd92020c8aaf86269ac7b/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>database</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>icons</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 06:00:07 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="33864" important="false" status="posted" url="https://my3.my.umbc.edu/posts/33864">
<Title>Backbone.js Tips And Patterns</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <table width="650">
    <tbody>
    <tr>
    <td>
    <div>
    <img src="http://statisches.auslieferung.commindo-media-ressourcen.de/advertisement.gif" alt="" style="max-width: 100%; height: auto;"><br><a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=1" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=1" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=2" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=2" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=3" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=3" alt="" style="max-width: 100%; height: auto;"></a>
    </div>
    </td>
    </tr>
    </tbody>
    </table>
    <p><a href="http://backbonejs.org/" title="Backbone.js" rel="nofollow external" class="bo">Backbone.js</a> is a popular open-source <strong>JavaScript “MV*” framework</strong> that has gained significant traction since its first release a little over three years ago. Although Backbone.js provides structure to JavaScript applications, it leaves a lot of design patterns and decisions up to the developer, for better or worse, and developers run into many common problems when they first begin developing in Backbone.js.</p>
    <p>Therefore, in this article, we’ll explore different design patterns that you can use in your Backbone.js applications, and we’ll look at many of the common gotchas that trip up developers.</p>
    <p><a href="http://www.flickr.com/photos/rutlo/5220159766/" title="Austin, Texas in autumn by rutlo, on Flickr" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/08/a5220159766_c2f06fa1dd.jpg" width="500" height="333" alt="Austin, Texas in autumn" style="max-width: 100%; height: auto;"></a><br>
    <em>Applications, like buildings, are best built following known patterns. (Image: <a href="http://www.flickr.com/photos/rutlo/5220159766/" title="Austin, Texas in autumn by rutlo, on Flickr" rel="nofollow external" class="bo">Matthew Rutledge</a>)</em></p>
    <h3>Perform Deep Copies Of Objects</h3>
    <p>JavaScript treats all primitive-type variables as pass-by-value. So, the value of a variable is passed when the variable is referenced.</p>
    <pre><code>&#x000A;    var helloWorld = “Hello World”;&#x000A;    var helloWorldCopy = helloWorld;&#x000A;    </code></pre>
    <p>For example, the code above will set <code>helloWorldCopy</code> equal to the value of <code>helloWorld</code>. So, any modification to <code>helloWorldCopy</code> would not modify <code>helloWorld</code>, since it is a copy. JavaScript <strong>treats all non-primitive-type variables as pass-by-reference</strong>, meaning that JavaScript will pass a reference of the memory address of the variable when the variable is referenced.</p>
    <pre><code>&#x000A;    var helloWorld = {&#x000A;        ‘hello’: ‘world’&#x000A;    }&#x000A;    var helloWorldCopy = helloWorld;&#x000A;    </code></pre>
    <p>For example, the code above will set <code>helloWorldCopy</code> equal to the reference of <code>helloWorld</code>, and, as you might guess, any modifications to <code>helloWorldCopy</code> would directly manipulate <code>helloWorld</code>. If you’d like to have a copy of <code>helloWorld</code>, you will have to create a copy of the object.</p>
    <p>You’re probably wondering, “Why is he explaining all of this pass-by-reference and pass-by-value stuff?” Well, <strong>Backbone.js does not copy objects</strong>, which means that if you <code>.get()</code> an object from a model, any modifications to that object will directly manipulate the object! Let’s look at an example to illustrate where this can become an issue. Let’s say you have a <code>Person</code> model like the following:</p>
    <pre><code>&#x000A;    var Person = Backbone.Model.extend({&#x000A;       defaults: {&#x000A;            'name': 'John Doe',&#x000A;            'address': {&#x000A;                'street': '1st Street'&#x000A;                'city': 'Austin',&#x000A;                'state': 'TX'&#x000A;                'zipCode': 78701&#x000A;            }&#x000A;       }&#x000A;    });&#x000A;    </code></pre>
    <p>And let’s say you create a new <code>person</code> object:</p>
    <pre><code>&#x000A;    var person = new Person({&#x000A;        'name': 'Phillip W'&#x000A;    });&#x000A;    </code></pre>
    <p>Now, let’s manipulate some of the attributes of the new <code>person</code> object:</p>
    <pre><code>&#x000A;    person.set('name', 'Phillip W.');&#x000A;    </code></pre>
    <p>The code above successfully manipulates the <code>name</code> attribute of the <code>person</code> object. Now let’s try to manipulate the address of the <code>person</code> object. However, before doing so, let’s add some validation for the address.</p>
    <pre><code>&#x000A;    var Person = Backbone.Model.extend({&#x000A;        validate: function(attributes) {&#x000A;    &#x000A;            if(isNaN(attributes.address.zipCode)) return "Address ZIP code must be a number!";&#x000A;        },&#x000A;    &#x000A;        defaults: {&#x000A;            'name': 'John Doe',&#x000A;            'address': {&#x000A;                'street': '1st Street'&#x000A;                'city': 'Austin',&#x000A;                'state': 'TX'&#x000A;                'zipCode': 78701&#x000A;            }&#x000A;        } &#x000A;    });&#x000A;    </code></pre>
    <p>Now, let’s attempt to manipulate the address with an incorrect ZIP code.</p>
    <pre><code>&#x000A;    var address = person.get('address');&#x000A;    address.zipCode = 'Hello World';&#x000A;    // Raises an error since the ZIP code is invalid&#x000A;    person.set('address', address);&#x000A;    console.log(person.get('address'));&#x000A;    /* Prints an object with these properties.&#x000A;    {&#x000A;        'street': '1st Street'&#x000A;        'city': 'Austin',&#x000A;        'state': 'TX'&#x000A;        'zipCode': 'Hello World'&#x000A;    }&#x000A;    */&#x000A;    </code></pre>
    <p>How can this be? Our validation has raised an error! Why are the attributes still changed? As mentioned, <strong>Backbone.js does not copy model attributes</strong>; it simply returns whatever you’re asking for. So, as you might guess, if you ask for an object, you will get a reference to that object, and any manipulation to the object will directly manipulate the actual object in the model. This can quickly lead you down a very dark rabbit hole that can take you hours of debugging to diagnose.</p>
    <p><a href="http://www.flickr.com/photos/davidorban/4004632688/" title="Rabbit hole by david.orban, on Flickr" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/08/a4004632688_1392c1827c.jpg" width="500" height="387" alt="Rabbit hole" style="max-width: 100%; height: auto;"></a><br>
    <em>Performing a deep copy of model objects can save you from going down a rabbit hole of debugging. (Image: <a href="http://www.flickr.com/photos/davidorban/4004632688/" title="Rabbit hole by david.orban, on Flickr" rel="nofollow external" class="bo">David Orban</a>)</em></p>
    <p>This issue catches developers who are new to Backbone.js and even seasoned JavaScript developers off guard. This issue has been heavily discussed <a href="https://github.com/documentcloud/backbone/issues/2315" rel="nofollow external" class="bo">in the GitHub issues</a> section of Backbone.js. As <a title="Jeremy Ashkenas" href="http://ashkenas.com/" rel="nofollow external" class="bo">Jeremy Ashkenas</a> points out there, <strong>performing a deep copy is a very difficult problem to solve</strong>, and it can become an expensive operation for very large, deep objects.</p>
    <p>Luckily, jQuery provides an implementation of deep copying, <a title="jQuery .extend" href="http://api.jquery.com/jQuery.extend/" rel="nofollow external" class="bo"><code>$.extend</code></a>. As an aside, <a title="Underscore.js" href="http://underscorejs.org/" rel="nofollow external" class="bo">Underscore.js</a>, a dependency of Backbone.js, provides the <a title="Underscore.js .extend" href="http://underscorejs.org/#extend" rel="nofollow external" class="bo"><code>_.extend</code></a> function, but I would avoid using it because it does not perform a deep copy. I use <a title="jQuery .extend" href="http://api.jquery.com/jQuery.extend/" rel="nofollow external" class="bo"><code>$.extend</code></a> to perform a deep copy of any object that I <code>.get()</code> from a model using the following syntax. Remember to pass <code>true</code>, so that it performs a deep copy of the object.</p>
    <pre><code>&#x000A;    var address = $.extend(true, {}, person.address);&#x000A;    </code></pre>
    <p>We now have an exact copy of the <code>address</code> object, and we can modify it to our heart’s content without worrying about modifying the actual model. You should know that there is a small performance hit from performing a deep copy, but I have never seen this cause noticeable problems. However, if you’re deep copying massive objects, or thousands of objects all at once, you’ll likely want to do some performance profiling. This leads us directly to the next pattern.</p>
    <h3>Create Facades To Objects</h3>
    <p>In the real world, requirements change often, and so does the JavaScript Object Notation (or <a title="JSON" href="http://www.json.org/" rel="nofollow external" class="bo">JSON</a>) returned by the endpoints that your models and collections hit. This can become a really big pain point in your code base if your view is tightly coupled to the underlying data model. Therefore, I <strong>create getters and setters for all objects</strong>.</p>
    <p>The pros of this pattern are many. If any of the underlying data structures change, then the view layers shouldn’t have to update that much; you will have one point of access to the data, so you are less likely to forget to do a deep copy, and your code will be more maintainable and much easier to debug. The downside is that this pattern can cause a bit of bloat in your models or collections.</p>
    <p>Let’s look at an example to illustrate this pattern. Imagine we have a <code>Hotel</code> model that contains rooms and the currently available rooms, and that we want to be able to retrieve rooms by bed size.</p>
    <pre><code>&#x000A;    var Hotel = Backbone.Model.extend({&#x000A;        defaults: {&#x000A;            "availableRooms": ["a"],&#x000A;            "rooms": {&#x000A;                "a": {&#x000A;                    "size": 1200,&#x000A;                    "bed": "queen"&#x000A;                },&#x000A;                "b": {&#x000A;                    "size": 900,&#x000A;                    "bed": "twin"&#x000A;                },&#x000A;                "c": {&#x000A;                    "size": 1100,&#x000A;                    "bed": "twin"&#x000A;                }&#x000A;            },&#x000A;    &#x000A;            getRooms: function() {&#x000A;                $.extend(true, {}, this.get("rooms"));&#x000A;            },&#x000A;    &#x000A;            getRoomsByBed: function(bed) {&#x000A;                return _.where(this.getRooms(), function() {&#x000A;                    { "bed": bed }&#x000A;                });&#x000A;            }&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>Now let’s imagine that tomorrow you will be releasing your code, and you find out that the endpoint developers forgot to tell you that the data structure of rooms has changed from an object to an array. Your code now looks like the following.</p>
    <pre><code>&#x000A;    var Hotel = Backbone.Model.extend({&#x000A;        defaults: {&#x000A;            "availableRooms": ["a"],&#x000A;            "rooms": [&#x000A;                {&#x000A;                    "name": "a",&#x000A;                    "size": 1200,&#x000A;                    "bed": "queen"&#x000A;                },&#x000A;                {&#x000A;                    "name": "b",&#x000A;                    "size": 900,&#x000A;                    "bed": "twin"&#x000A;                },&#x000A;                {&#x000A;                    "name": "c",&#x000A;                    "size": 1100,&#x000A;                    "bed": "twin"&#x000A;                }&#x000A;            ],&#x000A;    &#x000A;            getRooms: function() {&#x000A;                var rooms = $.extend(true, {}, this.get("rooms")),&#x000A;                 newRooms = {};&#x000A;    &#x000A;                // transform rooms from an array back into an object&#x000A;                _.each(rooms, function(room) {&#x000A;                    newRooms[room.name] = {&#x000A;                        "size": room.size,&#x000A;                        "bed": room.bed&#x000A;                    }&#x000A;                });&#x000A;            },&#x000A;    &#x000A;            getRoomsByBed: function(bed) {&#x000A;                return _.where(this.getRooms(), function() {&#x000A;                    { "bed": bed }&#x000A;                });&#x000A;            }&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>We updated only one function in order to transform the <code>Hotel</code> structure into the structure that the rest of our application expects, and our entire app still behaves as expected. If we didn’t have a getter here, we might potentially have to update each point of access to <code>rooms</code>. Ideally, you would want to update all of your functions to work with the new data structure, but if you’re pressed for time and have to release, this pattern can save you.</p>
    <p>As an aside, this pattern can be thought of as both a <a title="Facade Design Pattern" href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/#facadepatternjavascript" rel="nofollow external" class="bo">facade design pattern</a>, because it hides the complexity of creating a copy of your objects, or a <a title="Bridge Design Pattern" href="http://en.wikipedia.org/wiki/Bridge_pattern" rel="nofollow external" class="bo">bridge design pattern</a>, because it can be used to transform data into what is expected. A good rule of thumb is to <strong>use getters and setters on anything that is an object</strong>.</p>
    <h3>Store Data Not Persisted By The Server</h3>
    <p>Although Backbone.js prescribes that models and collections map to <a title="Representational State Transfer" href="http://en.wikipedia.org/wiki/Representational_state_transfer" rel="nofollow external" class="bo">representational state transfer</a> (or REST-ful) endpoints, you will sometimes find that you want to store data in your models or collections that is not persisted on the server. Many other articles about Backbone.js, such as “<a title="Backbone.js Tips: Lessons from the trenches." href="https://supportbee.com/devblog/2011/07/29/backbone-js-tips-lessons-from-the-trenches/" rel="nofollow external" class="bo">Backbone.js Tips: Lessons From the Trenches</a>” by Prateek Dayal of SupportBee, describe this pattern. Let’s look at a quick example to help explain where this might come in handy. Suppose you have a <code>ul</code> list.</p>
    <pre><code>&#x000A;    &lt;ul&gt;&#x000A;    	&lt;li&gt;&lt;a href="#" data-id="1"&gt;One&lt;/a&gt;&lt;/li&gt;&#x000A;    	&lt;li&gt;&lt;a href="#" data-id="2"&gt;Two&lt;/a&gt;&lt;/li&gt;&#x000A;        . . .&#x000A;    	&lt;li&gt;&lt;a href="#" data-id="n"&gt;n&lt;/a&gt;&lt;/li&gt;&#x000A;    &lt;/ul&gt;&#x000A;    </code></pre>
    <p>Where <code>n</code> is 200 and when the user clicks on one of the items, that item becomes selected and is visualized to the user as the chosen item by a <code>selected</code> class being added. One approach to this would be the following:</p>
    <pre><code>&#x000A;    var Model = Backbone.Model.extend({&#x000A;        defaults: {&#x000A;            items: [&#x000A;                {&#x000A;                    "name": "One",&#x000A;                    "id": 1           &#x000A;                },&#x000A;                {&#x000A;                    "name": "Two",&#x000A;                    "id": 2           &#x000A;                },&#x000A;                {&#x000A;                    "name": "Three",&#x000A;                    "id": 3           &#x000A;                }&#x000A;            ]&#x000A;        }&#x000A;    });&#x000A;    &#x000A;    var View = Backbone.View.extend({&#x000A;        template: _.template($('#list-template').html()),&#x000A;    &#x000A;        events: {&#x000A;            "#items li a": "setSelectedItem"&#x000A;        },&#x000A;    &#x000A;        render: function() {&#x000A;            $(this.el).html(this.template(this.model.toJSON()));&#x000A;        },&#x000A;    &#x000A;        setSelectedItem: function(event) {&#x000A;            var selectedItem = $(event.currentTarget);&#x000A;            // Set all of the items to not have the selected class&#x000A;            $('#items li a').removeClass('selected');&#x000A;            selectedItem.addClass('selected');&#x000A;            return false;&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <pre><code>&#x000A;    &lt;script id="list-template" type="template"&gt;&#x000A;    &lt;ul id="items"&gt;&#x000A;            &lt;% for(i = items.length - 1; i &gt;= 0; i--) { %&gt;&#x000A;    	&lt;li&gt;&#x000A;                    &lt;a href="#" data-id="&lt;%= item[i].id %&gt;"&gt;&lt;%= item[i].name %&gt;&lt;/a&gt;&lt;/li&gt;&#x000A;    &lt;% } %&gt;&lt;/ul&gt;&#x000A;    &lt;/script&gt;&#x000A;    </code></pre>
    <p>Now let’s say we want to figure out which item has been selected. One way would be to traverse the list. But if the list is really long, this could become quite an expensive task. Therefore, <strong>let’s also store which item is selected when the user clicks on a list item</strong>.</p>
    <pre><code>&#x000A;    var Model = Backbone.Model.extend({&#x000A;        defaults: {&#x000A;            selectedId: undefined,&#x000A;            items: [&#x000A;                {&#x000A;                    "name": "One",&#x000A;                    "id": 1&#x000A;                },&#x000A;                {&#x000A;                    "name": "Two",&#x000A;                    "id": 2&#x000A;                },&#x000A;                {&#x000A;                    "name": "Three",&#x000A;                    "id": 3&#x000A;                }&#x000A;            ]&#x000A;        }&#x000A;    });&#x000A;    &#x000A;    var View = Backbone.View.extend({&#x000A;        initialize: function(options) {&#x000A;            // Re-render when the model changes&#x000A;            this.model.on('change:items', this.render, this);&#x000A;        },&#x000A;    &#x000A;        template: _.template($('#list-template').html()),&#x000A;    &#x000A;        events: {&#x000A;            "#items li a": "setSelectedItem"&#x000A;        },&#x000A;    &#x000A;        render: function() {&#x000A;            $(this.el).html(this.template(this.model.toJSON()));&#x000A;        },&#x000A;    &#x000A;        setSelectedItem: function(event) {&#x000A;            var selectedItem = $(event.currentTarget);&#x000A;            // Set all of the items to not have the selected class&#x000A;            $('#items li a').removeClass('selected');&#x000A;            selectedItem.addClass('selected');&#x000A;            // Store a reference to what item was selected&#x000A;            this.model.set('selectedId', selectedItem..data('id'));&#x000A;            return false;&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>Now we can easily query our model to determine which item has been selected, and we don’t have to traverse the <a href="http://en.wikipedia.org/wiki/Document_Object_Model" title="Document Object Model" rel="nofollow external" class="bo">Document Object Model</a> (DOM). This pattern is extremely useful for storing extraneous data that you might want to keep track of; keep in mind also that you can create models and collections that don’t necessarily have endpoints associated with them.</p>
    <p>The downsides to this pattern are that your models or collections won’t really follow a RESTful architecture since they won’t map perfectly to a Web resource; also, this pattern can cause a bit of bloat in your models; and it can cause a bit of pain when saving your models if your endpoint strictly accepts only the JSON it expects.</p>
    <h3>Render Parts Of Views Instead Of Entire Views</h3>
    <p>When you first begin developing Backbone.js applications, your views will typically be structured something like this:</p>
    <pre><code>&#x000A;    var View = Backbone.View.extend({&#x000A;        initialize: function(options) {&#x000A;            this.model.on('change', this.render, this);&#x000A;        },&#x000A;    &#x000A;        template: _.template($(‘#template’).html()),&#x000A;    &#x000A;        render: function() {&#x000A;            this.$el.html(template(this.model.toJSON());&#x000A;            $(‘#a’, this.$el).html(this.model.get(‘a’));&#x000A;            $(‘#b’, this.$el).html(this.model.get(‘b’));&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>Here, any change to your model will trigger a complete re-rendering of the view. I was a practitioner of this pattern when I first began developing with Backbone.js. But as my view code grew in size, I quickly realized that this approach was not maintainable or optimal because the view was being completely re-rendered when any attribute of the model changed.</p>
    <p>When I ran into this problem, I did a quick Google search to see what others had done and found Ian Storm Taylor’s blog post, “<a title="Break Apart Your Backbone.js Render Methods" href="http://ianstormtaylor.com/break-apart-your-backbonejs-render-methods/" rel="nofollow external" class="bo">Break Apart Your Backbone.js Render Methods</a>,” in which he describes listening for individual attribute changes in the model and then <strong>re-rendering only the part of the view corresponding to the changed attribute</strong>. Taylor also describes returning a reference to the object so that the individual rendering functions can be easily chained together. The example above now transforms into something much more maintainable and performant because we are only updating portions of the view that correspond to the model attributes that have changed.</p>
    <pre><code>&#x000A;    var View = Backbone.View.extend({&#x000A;        initialize: function(options) {&#x000A;            this.model.on('change:a', this.renderA, this);&#x000A;            this.model.on('change:b', this.renderB, this);&#x000A;        },&#x000A;    &#x000A;        renderA: function() {&#x000A;            $(‘#a’, this.$el).html(this.model.get(‘a’));&#x000A;            return this;&#x000A;        },&#x000A;    &#x000A;        renderB: function() {&#x000A;            $(‘#b’, this.$el).html(this.model.get(‘b’));&#x000A;            return this;&#x000A;        },&#x000A;    &#x000A;        render: function() {&#x000A;            this&#x000A;                .renderA()&#x000A;                .renderB();&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>I should mention that many plugins, such as <a title="Backbone.StickIt" href="http://nytimes.github.io/backbone.stickit/" rel="nofollow external" class="bo">Backbone.StickIt</a> and <a title="Backbone.ModelBinder" href="https://github.com/theironcook/Backbone.ModelBinder" rel="nofollow external" class="bo">Backbone.ModelBinder</a>, provide key-value bindings between model attributes and view elements, which can save you from a lot of boilerplate code. So, check them out if you have complex form fields.</p>
    <h3>Keep Models Agnostic To Views</h3>
    <p>As Jeremy Ashkenas points out in one of Backbone.js’ <a href="https://github.com/documentcloud/backbone/issues/21" rel="nofollow external" class="bo">GitHub issues</a>, Backbone.js doesn’t enforce any real separation of concerns between the data and view layer, except that models are not created with a reference to their view. Because Backbone.js doesn’t enforce a separation of concerns, should you? I and many other Backbone.js developers, such as <a title="avoiding common backbone.js pitfalls" href="http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html" rel="nofollow external" class="bo">Oz Katz</a> and <a title="Backbone.js Tips: Lessons From The Trenches" href="https://supportbee.com/devblog/2011/07/29/backbone-js-tips-lessons-from-the-trenches/" rel="nofollow external" class="bo">Dayal</a>, believe the answer is overwhelmingly yes: Models and collections, the data layer, should be entirely agnostic of the views that are bound to them, keeping a clear separation of concerns. If you don’t follow a separation of concerns, your code base could quickly turn into spaghetti code, and <strong>no one likes spaghetti code</strong>.</p>
    <p><a href="http://www.flickr.com/photos/gotosira/4699302559/" title="spaghetti by gotosira, on Flickr" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2013/08/a4699302559_eeeaab770f.jpg" width="500" height="375" alt="Spaghetti." style="max-width: 100%; height: auto;"></a><br>
    <em>Keeping your models agnostic to your views will help prevent spaghetti code, and no one likes spaghetti code! (Image: <a title="spaghetti by gotosira, on Flickr" rel="nofollow external" class="bo">Sira Hanchana</a>)</em></p>
    <p>Keeping your data layer completely agnostic to the view layer allows for a more modular, reusable and maintainable code base. You can easily reuse and extend models and collections throughout your application without concern for the views that are tying into them. Following this pattern <strong>enables developers who are new to your project to quickly dive into the code base</strong>, because they will know exactly where rendering takes place and where all of the business logic of your application should live.</p>
    <p>This pattern also enforces the <a title="Single Responsibility Principle" href="http://en.wikipedia.org/wiki/Single_responsibility_principle" rel="nofollow external" class="bo">single responsibility principle</a>, which dictates that each class should have a single responsibility, and its responsibility should be encapsulated in the class, since your models and collections should handle data and your views should handle rendering.</p>
    <h3>Parameter Mapping In Routers</h3>
    <p>The best way to demonstrate how this pattern came about is through an example. Let’s say you have some sort of search page, and that the search page allows users to add two different filter types, <code>foo</code> and <code>bar</code>, each of which has a multitude of options. Therefore, your URL structure would start off looking something like this:</p>
    <pre><code>&#x000A;    'search/:foo'&#x000A;    'search/:bar'&#x000A;    'search/:foo/:bar'&#x000A;    </code></pre>
    <p>Now, all of these routes use the exact same view and model, so you would ideally like them all to use the same function, <code>search()</code>. However, if you examine Backbone.js, there isn’t any sort of parameter mapping; the parameters are just plopped into the function from left to right. So, in order for them all to use the same function, you would end up creating different functions to correctly map the parameters to <code>search()</code>.</p>
    <pre><code>&#x000A;    routes: {&#x000A;        'search/:foo': 'searchFoo',&#x000A;        'search/:bar': 'searchBar',&#x000A;        'search/:foo/:bar': 'search'&#x000A;    },&#x000A;    &#x000A;    search: function(foo, bar) {    &#x000A;    },&#x000A;    &#x000A;    // I know this function will actually still map correctly, but for explanatory purposes, it's left in.&#x000A;    searchFoo: function(foo) {&#x000A;        this.search(foo, undefined);&#x000A;    },&#x000A;    &#x000A;    searchBar: function(bar) {&#x000A;        this.search(undefined, bar);&#x000A;    },&#x000A;    </code></pre>
    <p>As you can imagine, this pattern could quickly bloat your routers. When I first ran into this problem, I attempted to do some parsing of the actual function definitions with regular expressions to “magically” map the parameters, which would have worked — but only if I had followed specific constraints. So, I scrapped the idea (I might still throw this into a Backbone plugin sometime). I opened an <a href="https://github.com/documentcloud/backbone/issues/1833" rel="nofollow external" class="bo">issue on GitHub</a>, and Ashkenas suggested mapping all of the parameters in the search function.</p>
    <p>The code above now transforms into something much more maintainable:</p>
    <pre><code>&#x000A;    routes: {&#x000A;        'base/:foo': 'search',&#x000A;        'base/:bar': 'search',&#x000A;        'base/:foo/:bar': 'search'&#x000A;    },&#x000A;    &#x000A;    search: function() {&#x000A;        var foo, bar, i;&#x000A;    &#x000A;        for(i = arguments.length - 1; i &gt;= 0; i--) {&#x000A;    &#x000A;            if(arguments[i] === 'something to determine foo') {&#x000A;                foo = arguments[i];&#x000A;                continue;&#x000A;            }&#x000A;            else if(arguments[i] === 'something to determine bar') {&#x000A;                bar = arguments[i];&#x000A;                continue;&#x000A;            }&#x000A;        }&#x000A;    },&#x000A;    </code></pre>
    <p>This pattern can drastically reduce router bloat. However, be aware that it will not work for parameters that are not distinguishable. For example, if you had two parameters that were both IDs and followed the pattern <code>XXXX-XXXX</code>, you would not be able to identify which ID corresponded to which parameter.</p>
    <h3>model.fetch() Won’t Clear Your Model</h3>
    <p>This usually trips up those who are new to Backbone.js: <code>model.fetch()</code> will not clear out your model, but rather <strong>extends the attributes of your model</strong>. Therefore, if your model has attributes <code>x</code>, <code>y</code> and <code>z</code> and your fetch returns <code>y</code> and <code>z</code>, then <code>x</code> will still be in the model and only <code>y</code> and <code>z</code> will be updated. The following example visualizes this concept.</p>
    <pre><code>&#x000A;    var Model = Backbone.Model.extend({&#x000A;        defaults: {&#x000A;            x: 1,&#x000A;            y: 1,&#x000A;            z: 1&#x000A;        }&#x000A;    });&#x000A;    var model = new Model();&#x000A;    /* model.attributes yields&#x000A;    {&#x000A;        x: 1,&#x000A;        y: 1,&#x000A;        z: 1&#x000A;    } */&#x000A;    model.fetch();&#x000A;    /* let’s assume that the endpoint returns this&#x000A;    {&#x000A;        y: 2,&#x000A;        z: 2,&#x000A;    } */&#x000A;    /* model.attributes now yields&#x000A;    {&#x000A;        x: 1,&#x000A;        y: 2,&#x000A;        z: 2&#x000A;    } */&#x000A;    </code></pre>
    <h3>PUTs Require An ID Attribute</h3>
    <p>This one also usually trips up those who are new to Backbone.js. To have your models send a <a title="HTTP PUT Verb" href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods" rel="nofollow external" class="bo">HTTP PUT</a> request when you call <code>.save()</code>, your model is required to have an ID attribute set. Remember that the HTTP PUT verb is designed to be an update, so it makes sense that to send a PUT request, your model is required to have an ID. In an ideal world, all of your models would have a perfect ID attribute named ID, but the JSON data that you receive from your endpoints will likely not always have perfectly named IDs.</p>
    <p>Therefore, if you need to update a model, <strong>be sure that an ID is on the model before saving it</strong>. Backbone.js versions 0.5 and greater allow you to change the name of the ID attribute of your models using <code>idAttribute</code>, in case your endpoint doesn’t return IDs named <code>id</code>.</p>
    <p>If are stuck using a version of Backbone.js lower than 0.5, I suggest that you modify the <code>parse</code> function of your collection or model to map your expected ID attribute to the attribute ID. Here’s a quick example of how you can achieve this by modifying your parse function. Let’s imagine you have a collection of cars whose IDs are <code>carID</code>.</p>
    <pre><code>&#x000A;    parse: function(response) {&#x000A;    &#x000A;        _.each(response.cars, function(car, i) {&#x000A;            // map the returned ID of carID to the correct attribute ID&#x000A;            response.cars[i].id = response.cars[i].carID;&#x000A;        });&#x000A;    &#x000A;        return response;&#x000A;    },</code></pre>
    
    <h3>Model Data On Page Load</h3>
    <p>Sometimes you will find that your models or collections need to be initialized with data on page load. Many articles about Backbone.js patterns, such as Rico Sta Cruz’ “<a title="Backbone patterns" href="http://ricostacruz.com/backbone-patterns/" rel="nofollow external" class="bo">Backbone Patterns</a>” and Katz’ “<a title="Avoiding Common Backbone.js Pitfalls" href="http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html" rel="nofollow external" class="bo">Avoiding Common Backbone.js Pitfalls</a>,” discuss this pattern. This pattern is easily achieved by inlining a script on the page and rendering out the data in either single-model attributes or JSON, using the server-side language of your choice. For example, in Rails, I use one of the following:</p>
    <pre><code>&#x000A;    // a single attribute&#x000A;    var model = new Model({&#x000A;        hello: &lt;%= @world %&gt;&#x000A;    });&#x000A;    // or to have json&#x000A;    var model = new Model(&lt;%= @hello_world.to_json %&gt;);&#x000A;    </code></pre>
    <p>Using this pattern could improve your search engine rankings by “instantly” rendering out your page, and it could drastically shorten the time it takes for your application to be up and running by limiting the application’s initial HTTP requests.</p>
    <h3>Handling Failed Model Attribute Validation</h3>
    <p>Very often, you will want to know what model attributes have failed validation. For example, if you have an extremely complex form field, you might want to know which model attribute has failed validation so that you can highlight the input field corresponding to the attribute. Unfortunately, alerting your views as to which model attributes have failed validation is not directly baked into Backbone.js, but you can use a few different pattern to handle this.</p>
    <h4>Return an Error Object</h4>
    <p>One pattern to notify your views of which model attributes have failed validation is to pass back an object with some sort of flag detailing which attribute has failed validation, such as the following:</p>
    <pre><code>&#x000A;    // Inside your model&#x000A;    validate: function(attrs) {&#x000A;        var errors = [];&#x000A;    &#x000A;        if(attrs.a &lt; 0) {&#x000A;            errors.push({&#x000A;                'message': 'Form field a is messed up!',&#x000A;                'class': 'a'&#x000A;            });&#x000A;        }&#x000A;        if(attrs.b &lt; 0) {&#x000A;            errors.push({&#x000A;                'message': 'Form field b is messed up!',&#x000A;                'class': 'b'&#x000A;            });&#x000A;        }&#x000A;    &#x000A;        if(errors.length) {&#x000A;            return errors;&#x000A;        }&#x000A;    }&#x000A;    // Inside your view&#x000A;    this.model.on('invalid’, function(model, errors) {&#x000A;        _.each(errors, function(error, i) {&#x000A;            $(‘.’ + error.class).addClass('error');&#x000A;            alert(error.message);&#x000A;        });&#x000A;    });&#x000A;    </code></pre>
    <p>The advantage of this pattern is that you are handling all invalid messages in one location. The disadvantage is that your invalid method could become a large <code>switch</code> or <code>if</code> statement if you deal with invalid attributes differently.</p>
    <h4>Broadcast Custom Error Event</h4>
    <p>An alternative pattern, suggested by a friend of mine, <a title="Derick Bailey" href="http://lostechies.com/derickbailey/" rel="nofollow external" class="bo">Derick Bailey</a>, is to trigger custom errors events for each model attribute. This allows your views to bind to specific error events for individual attributes:</p>
    <pre><code>&#x000A;    // Inside your model&#x000A;    validate: function(attrs) {&#x000A;    &#x000A;        if(attrs.a &lt; 0) {&#x000A;                this.trigger(‘invalid:a’, 'Form field a is messed up!', this);&#x000A;        }&#x000A;        if(attrs.b &lt; 0) {&#x000A;                this.trigger(‘invalid:b’, 'Form field b is messed up!', this);&#x000A;        }&#x000A;    }&#x000A;    // Inside your view&#x000A;    this.model.on('invalid:a’, function(error) {&#x000A;            $(‘a’).addClass('error');&#x000A;            alert(error);&#x000A;    });&#x000A;    this.model.on('invalid:b’, function(error) {&#x000A;            $(‘b’).addClass('error');&#x000A;            alert(error);&#x000A;    });&#x000A;    </code></pre>
    <p>The advantage of this pattern is that your view bindings are explicit in the type of error they are bound to, and if you have specific instructions for each type of attribute error, it can clean up your view code and make it more maintainable. The one downside of this pattern is that your views could become rather bloated if there aren’t many differences in how you handle different attribute errors.</p>
    <p>Both patterns have their pros and cons, and you should think about which pattern is best for your use case. If you treat all failed validation errors the same way, then the first approach would probably be best; if you have specific UI changes per model attribute, then the latter approach would be better.</p>
    <h3>HTTP Status Code 200 Trigger Error</h3>
    <p>If the endpoint that your model or collection is hitting returns invalid JSON, then your model or collection will trigger an “error” event, even if the endpoint returns a 200 HTTP status code. This issue mostly comes up when developing locally against mock JSON data. So, a good rule of thumb is to throw any mock JSON files you’re developing through a <a title="JSON Formatter" href="http://jsonformatter.curiousconcept.com/" rel="nofollow external" class="bo"><strong>JSON validator</strong></a>. Or get a <strong>plugin</strong> for your IDE that will catch any ill-formatted JSON.</p>
    <h3>Create A Generic Error Display</h3>
    <p>This one could save you time and create a uniform pattern for handling and visualizing error messages, which will improve your user’s overall experience. In any Backbone.js app that I develop, I create a generic view that handles alerts:</p>
    <pre><code>&#x000A;    var AlertView = Backbone.View.extend({&#x000A;        set: function(typeOfError, message) {&#x000A;            var alert = $(‘.in-page-alert’).length ? $(‘.in-page-alert’): $(‘.body-alert’);&#x000A;            alert&#x000A;                .removeClass(‘error success warning’)&#x000A;                .html(message)&#x000A;                .fadeIn()&#x000A;                .delay(5000)&#x000A;                .fadeOut();&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <p>The view above first looks to see whether there is a view-specific <code>in-page-alert</code> div, which you would declare inside of your view’s markup. If there is no view-specific div, then it falls back to a generic <code>body-alert</code> div, which you would declare somewhere in the layout. This enables you to deliver a consistent error message to your users and provides a useful fallback in case you forget to specify a view-specific <code>in-page-alert</code> div. The pattern above streamlines how you handle error messages in your views, as follows:</p>
    <pre><code>&#x000A;    this.model.on('error', function(model, error) {&#x000A;        alert.set('TYPE-OF-ERROR', error);&#x000A;    });&#x000A;    </code></pre>
    <h3>Update Single-Page App Document Titles</h3>
    <p>This is more of a usability concern than anything. If you’re developing a single-page application, remember to <strong>update the document title of each page</strong>! I’ve written a simple Backbone.js plugin, <a title="Backbone.js Router Title Helper" href="https://github.com/pwhisenhunt/Backbonejs-Router-Title-Helper" rel="nofollow external" class="bo">Backbone.js Router Title Helper</a>, that does this in a simple and elegant format by extending the Backbone.js router. It allows you to specify a title’s object literal, whose keys map to route function names and whose values are page titles.</p>
    <pre><code>&#x000A;    Backbone.Router = Backbone.Router.extend({&#x000A;    &#x000A;        initialize: function(options){&#x000A;            var that = this;&#x000A;    &#x000A;            this.on('route', function(router, route, params) {&#x000A;    &#x000A;                if(that.titles) {&#x000A;                    if(that.titles[router]) document.title = that.titles[router];&#x000A;                    else if(that.titles.default) document.title = that.titles.default;&#x000A;                    else throw 'Backbone.js Router Title Helper: No title found for route:' + router + ' and no default route specified.';&#x000A;                }&#x000A;            });&#x000A;        }&#x000A;    });&#x000A;    </code></pre>
    <h4>Cache Objects In Single-Page Applications</h4>
    <p>While we are on the topic of single-page applications, another pattern you could follow is to cache objects that will be reused! This case is fairly straightforward and simple:</p>
    <pre><code>&#x000A;    // Inside a router&#x000A;    initialize: function() {&#x000A;    &#x000A;        this.cached = {&#x000A;            view: undefined,&#x000A;            model: undefined&#x000A;        }&#x000A;    },&#x000A;    &#x000A;    index: function(parameter) {&#x000A;        this.cached.model = this.cached.model || new Model({&#x000A;            parameter: parameter&#x000A;        });&#x000A;        this.cached.view = this.cached.view || new View({&#x000A;            model: this.cached.model&#x000A;        });&#x000A;    }&#x000A;    </code></pre>
    <p>This pattern will give your application a small bump in speed because you won’t have to reinitialize your Backbone.js objects. However, it could cause your application’s memory footprint to grow rather large; so, I’ll typically only cache objects that are commonly used throughout an application. If you’ve developed Backbone.js apps in the past, then you’re likely asking yourself, <strong>“What if I want to refetch data?”</strong> You can refetch data each time the route is triggered:</p>
    <pre><code>&#x000A;    // Inside a router&#x000A;    initialize: function() {&#x000A;    &#x000A;        this.cached = {&#x000A;            view: undefined,&#x000A;            model: undefined&#x000A;        }&#x000A;    },&#x000A;    &#x000A;    index: function(parameter) {&#x000A;        this.cached.model = this.cached.model || new Model({&#x000A;            parameter: parameter&#x000A;        });&#x000A;        this.cached.view = this.cached.view || new View({&#x000A;            model: this.cached.model&#x000A;        });&#x000A;        this.cached.model.fetch();&#x000A;    }&#x000A;    </code></pre>
    <p>This pattern will work when your application must retrieve the latest data from the endpoint (for example, an inbox). However, if the data that you’re fetching is dependent on the state of the application (assuming that the state is maintained through your URL and parameters), then you would be refetching data even if the application’s state hasn’t changed since the user was last on the page. A better solution would be to refetch data only when the state of the application (<code>parameter</code>) has changed:</p>
    <pre><code>&#x000A;    // Inside a router&#x000A;    initialize: function() {&#x000A;    &#x000A;        this.cached = {&#x000A;            view: undefined,&#x000A;            model: undefined&#x000A;        }&#x000A;    },&#x000A;    &#x000A;    index: function(parameter) {&#x000A;        this.cached.model = this.cached.model || new Model({&#x000A;            parameter:parameter&#x000A;        });&#x000A;        this.cached.model.set('parameter', parameter);&#x000A;        this.cached.view = this.cached.view || new View({&#x000A;            model: this.cached.model&#x000A;        });&#x000A;    }&#x000A;    &#x000A;    // Inside of the model&#x000A;    initialize: function() {&#x000A;        this.on("change:parameter", this.fetchData, this);&#x000A;    }&#x000A;    </code></pre>
    <h3>JSDoc Functions And Backbone.js Classes</h3>
    <p>I’m a huge fan of documentation and <a href="http://en.wikipedia.org/wiki/JSDoc" rel="nofollow external" class="bo">JSDoc</a>. I JSDoc all Backbone classes and functions in the following format:</p>
    <pre><code>&#x000A;    var Thing = Backbone.View.extend(/** @lends Thing.prototype */{&#x000A;        /** @class Thing&#x000A;         * @author Phillip Whisenhunt&#x000A;         * @augments Backbone.View&#x000A;         * @contructs Thing object */&#x000A;        initialize() {},&#x000A;    &#x000A;        /** Gets data by ID from the thing. If the thing doesn't have data based on the ID, an empty string is returned.&#x000A;         * @param {String} id The id of get data for.&#x000A;         * @return {String} The data. */&#x000A;        getDataById: function(id) {}&#x000A;    });&#x000A;    </code></pre>
    <p>If you document your Backbone classes in the format above, then you can generate beautiful documentation that contains all of your classes and functions with parameters, return types and descriptions. Be sure to keep the <code>initialize</code> function as the first function declared, which helps when generating JSDoc. If you’d like to see an example of a project that uses JSDoc, check out the <a title="HomeAway Calendar Widget" href="https://github.com/homeaway/calendar-widget" rel="nofollow external" class="bo">HomeAway Calendar Widget</a>. There is also a <a title="Grunt.js" href="http://gruntjs.com/" rel="nofollow external" class="bo">Grunt.js</a> plugin, <a title="Grunt-JSDoc-Plugin" href="https://github.com/krampstudio/grunt-jsdoc-plugin" rel="nofollow external" class="bo">grunt-jsdoc-plugin</a>, to generate documentation as part of your build process.</p>
    <h3>Practice Test-Driven Development</h3>
    <p>In my opinion, if you’re writing in Backbone.js, you should be following <a title="Test Driven Development" href="http://en.wikipedia.org/wiki/Test-driven_development" rel="nofollow external" class="bo">test-driven development</a> (TDD) for your models and collections. I follow TDD by first writing failing <a title="Jasmine.js" href="https://github.com/pivotal/jasmine" rel="nofollow external" class="bo">Jasmine.js</a> unit tests against my models or collections. Once the unit tests are written and failing, I flush out the model or collection.</p>
    <p>By this point, all of my Jasmine tests will have been passing, and I have confidence that my model functions all work as expected. Since I’ve been following TDD, my view layer has been super-easy to write and also extremely thin. When you begin practicing TDD, you will definitely slow down; but once you wrap your head around it, your <strong>productivity and the quality of your code will dramatically increase</strong>.</p>
    <p>I hope these tips and patterns have helped! If you have suggestions for other patterns or you’ve found a typo or you think that one of these patterns isn’t the best approach, please leave a comment below or <a title="Phillip Whisenhunt Twiter" href="https://twitter.com/pwhisenhunt" rel="nofollow external" class="bo">tweet me</a>.</p>
    <p><em>Thanks to <a title="Patrick Lewis" href="http://www.mountaindrawn.com/" rel="nofollow external" class="bo">Patrick Lewis</a>, <a title="Addy Osmani" href="http://addyosmani.com/blog/" rel="nofollow external" class="bo">Addy Osmani</a>, <a title="Derick Bailey" href="http://lostechies.com/derickbailey/" rel="nofollow external" class="bo">Derick Bailey</a> and <a title="Iam Storm Taylor" href="http://ianstormtaylor.com/" rel="nofollow external" class="bo">Ian Storm Taylor</a> for reviewing this article.</em></p>
    <p><em>(al) (ea)</em></p>
    <hr>
    <p><small>© Phillip Whisenhunt for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2013.</small></p>
    </div>
]]>
</Body>
<Summary>        Backbone.js is a popular open-source JavaScript “MV*” framework that has gained significant traction since its first release a little over three years ago. Although Backbone.js provides...</Summary>
<Website>http://www.smashingmagazine.com/2013/08/09/backbone-js-tips-patterns/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/33864/guest@my.umbc.edu/a29f1501b3014c7d9bd16631b042b954/api/pixel</TrackingUrl>
<Tag>coding</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Fri, 09 Aug 2013 05:34:14 -0400</PostedAt>
<EditAt>Fri, 09 Aug 2013 05:34:14 -0400</EditAt>
</NewsItem>

</News>
