<?xml version="1.0"?>
<News hasArchived="true" page="7819" pageCount="10769" pageSize="10" timestamp="Wed, 26 Aug 2026 07:32:39 -0400" url="https://my3.my.umbc.edu/posts.xml?mode=activity&amp;page=7819">
<NewsItem contentIssues="true" id="41279" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41279">
<Title>Submit your Artwork to ArtWeek '14!</Title>
<Tagline>Calling all artists at UMBC!</Tagline>
<Body>
<![CDATA[
    <div class="html-content">To download a submission form click "visit website" below for more details and information.<div><br></div>
    <div>Deadlines vary depending on media.</div>
    </div>
]]>
</Body>
<Summary>To download a submission form click "visit website" below for more details and information.    Deadlines vary depending on media.</Summary>
<Website>http://www.umbc.edu/thecommons/artweek/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41279/guest@my.umbc.edu/c85ddcd83495bb54462547a33b8a716c/api/pixel</TrackingUrl>
<Group token="commonvision">commonvision</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/commonvision</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/xsmall.png?1725997445</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/original.png?1725997445</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/xxlarge.png?1725997445</AvatarUrl>
<AvatarUrl size="xlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/xlarge.png?1725997445</AvatarUrl>
<AvatarUrl size="large">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/large.png?1725997445</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/medium.png?1725997445</AvatarUrl>
<AvatarUrl size="small">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/small.png?1725997445</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/xsmall.png?1725997445</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/023/f4c5202312d4c6e3dfd6f414c6da13a4/xxsmall.png?1725997445</AvatarUrl>
<Sponsor>commonvision</Sponsor>
<ThumbnailUrl size="xxlarge">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/xxlarge.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/xlarge.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="large">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/large.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="medium">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/medium.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="small">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/small.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="xsmall">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/xsmall.jpg?1392217177</ThumbnailUrl>
<ThumbnailUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/041/279/7d3127564701596547e48748c4810e13/xxsmall.jpg?1392217177</ThumbnailUrl>
<PawCount>9</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 10:04:41 -0500</PostedAt>
<EditAt>Wed, 12 Feb 2014 10:07:35 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="41278" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41278">
<Title>NEW Technical Full Time Positions Posted!</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><span>During the last week, multiple full-time positions have been posted to UMBCworks. Check out these key positions today!</span></p>
    <br><p>ARNIC- On Campus Interviews</p>
    <p><span>Entry Level Python Developer</span></p>
    <p><span>UMBCworks ID: </span><span>9263391</span></p>
    <p><span>Application Deadline: 2/26/14</span></p>
    <p><br></p>
    <pre>Symantec<br><span>Software Quality Assurance Engineer in Columbia, MD</span><br>UMBCworks ID: 9263695<br>Application Deadline: 3/7/14<br></pre>
    <span>AT&amp;T Inc.</span><br><div>
    <p><span>AT&amp;T Business Sales Leadership Development Program and BSLDP - Technical Sales Consultant</span></p>UMBCworks ID: <span>9263639</span>
    </div>
    <div><span>Application Deadline: 3/11/14</span></div>
    <div><span><br></span></div>
    <div><span>Systems-Logic</span></div>
    <div><span>Sr. Software Engineer</span></div>
    <div>
    <div>
    <span>UMBCworks ID: </span><span>9263760</span>
    </div>
    <div><span>Application Deadline: 3/10/14</span></div>
    </div>
    <div><span><br></span></div>
    <div><span>RDA Corporation</span></div>
    <div><span>Entry-Level Software Developer (.NET)</span></div>
    <div>
    <div>
    <span>UMBCworks ID: </span><span>9263596</span>
    </div>
    <div><span>Application Deadline: 5/7/14</span></div>
    </div>
    <div>
    <span><br></span><p><span>To access these positions, login to your UMBCworks account (via the link in the Jobs &amp; Internships topic in myUMBC) and find details and application instructions as well as hundreds of other job postings!</span></p>
    <br><p><span>Please note you MUST have an approved resume to apply to positions.  To schedule an appointment, access our online system in UMBCworks or call 410-455-2216.</span></p>
    </div>
    </div>
]]>
</Body>
<Summary>During the last week, multiple full-time positions have been posted to UMBCworks. Check out these key positions today!   ARNIC- On Campus Interviews  Entry Level Python Developer  UMBCworks...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41278/guest@my.umbc.edu/f53e9439006b52d0d7f1c9459bf0dde4/api/pixel</TrackingUrl>
<Group token="careers">Career Center</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/careers</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xsmall.png?1411655278</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/original.jpg?1411655278</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xxlarge.png?1411655278</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xlarge.png?1411655278</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/large.png?1411655278</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/medium.png?1411655278</AvatarUrl>
<AvatarUrl size="small">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/small.png?1411655278</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xsmall.png?1411655278</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xxsmall.png?1411655278</AvatarUrl>
<Sponsor>Career Services Center</Sponsor>
<PawCount>2</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 09:56:37 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 10:27:59 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="41276" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41276">
<Title>NEW Internships posted for Technical Majors</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><span>During the last week, multiple internships and research positions have been posted to UMBCworks. Check out these key positions today! Many more can be found by logging into UMBCworks!</span></p>
    <br><p><span>WaveStrike</span></p>
    <p><span>Software Engineer Intern</span></p>
    <p><span>UMBCworks ID: </span><span>9263654</span></p>
    <p><span>Application Deadline: 3/6/14</span></p>
    <p><span><br></span></p>
    <p><span><span>Quality Training Systems</span></span></p>
    <p><span>Quality Training Systems Intern and Co-Op Position</span><span>.</span></p>
    <div>UMBCworks ID: <span>9263732</span>
    </div>
    <div><span>Application Deadline: 3/8/14</span></div>
    <div><span><br></span></div>
    <div><span>UMBC Language, Literacy and Culture</span></div>
    <div><span>Spring 2014 Web Developer Internship</span></div>
    <div>
    <div>
    <span>UMBCworks ID: </span><span>9263660</span>
    </div>
    <div><span>Application Deadline: 2/28/14</span></div>
    </div>
    <div><span><br></span></div>
    <div><a href="https://umbc-csm.symplicity.com/manager/index.php?s=employers&amp;mode=form&amp;id=1ac45d2a7e3c702991ad8e47d3e31f62" rel="nofollow external" class="bo">a2z, Inc.</a></div>
    <div><a href="https://umbc-csm.symplicity.com/manager/index.php?mode=form&amp;id=b27c8e9ee9345445cfa7d9801c4bc70c" rel="nofollow external" class="bo">Techincal Intern</a></div>
    <div>
    <div>
    <span>UMBCworks ID: </span><span>9261715</span>
    </div>
    <div><span>Application Deadline: 3/23/14</span></div>
    </div>
    <div>
    <span><br></span><p><span>To access these positions, login to your UMBCworks account (via the link in the Jobs &amp; Internships topic in myUMBC) and find details and application instructions as well as hundreds of other job postings!</span></p>
    <br><p><span>Please note you MUST have an approved resume to apply to positions.  To schedule an appointment, access our online system in UMBCworks or call 410-455-2216.</span></p>
    </div>
    </div>
]]>
</Body>
<Summary>During the last week, multiple internships and research positions have been posted to UMBCworks. Check out these key positions today! Many more can be found by logging into UMBCworks!   WaveStrike...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41276/guest@my.umbc.edu/b20cc340e42d1c1f634aad2d2217cd6f/api/pixel</TrackingUrl>
<Group token="careers">Career Center</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/careers</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xsmall.png?1411655278</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/original.jpg?1411655278</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xxlarge.png?1411655278</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xlarge.png?1411655278</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/large.png?1411655278</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/medium.png?1411655278</AvatarUrl>
<AvatarUrl size="small">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/small.png?1411655278</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xsmall.png?1411655278</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/018/729f2c7eeeab66f50f4ab3677539a585/xxsmall.png?1411655278</AvatarUrl>
<Sponsor>Career Services Center</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 09:40:03 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="41281" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41281">
<Title>Bits Blog: For Wearable Computers, a New User Interface Challenge</Title>
<Body>
<![CDATA[
    <div class="html-content">The battery life of smart watches and computerized glasses could prove to be the most important aspect of wearable gadgets.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Ffor-wearable-computers-a-new-kind-of-user-interface-challenge%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+For+Wearable+Computers%2C+a+New+User+Interface+Challenge" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Ffor-wearable-computers-a-new-kind-of-user-interface-challenge%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+For+Wearable+Computers%2C+a+New+User+Interface+Challenge" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Ffor-wearable-computers-a-new-kind-of-user-interface-challenge%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+For+Wearable+Computers%2C+a+New+User+Interface+Challenge" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Ffor-wearable-computers-a-new-kind-of-user-interface-challenge%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+For+Wearable+Computers%2C+a+New+User+Interface+Challenge" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Ffor-wearable-computers-a-new-kind-of-user-interface-challenge%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+For+Wearable+Computers%2C+a+New+User+Interface+Challenge" 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/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/sc/15/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530555733/u/0/f/640387/c/34625/s/370499f7/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>The battery life of smart watches and computerized glasses could prove to be the most important aspect of wearable gadgets.      </Summary>
<Website>http://bits.blogs.nytimes.com/2014/02/12/for-wearable-computers-a-new-kind-of-user-interface-challenge/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41281/guest@my.umbc.edu/9a70e7365530f4c2b4f0a4edaf38fd66/api/pixel</TrackingUrl>
<Tag>apple-inc</Tag>
<Tag>apple-inc-aapl-nasdaq</Tag>
<Tag>computers-and-the-internet</Tag>
<Tag>google-glass</Tag>
<Tag>mobile</Tag>
<Tag>new</Tag>
<Tag>technology</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>Wed, 12 Feb 2014 09:00:48 -0500</PostedAt>
<EditAt>Wed, 12 Feb 2014 13:50:03 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="41274" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41274">
<Title>Important Financial Aid Info for 2014-2015 Academic Year</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><strong><span>UMBC Deadline</span></strong><span><br>
    </span><span>Submit the </span><a href="http://www.fafsa.ed.gov/" rel="nofollow external" class="bo"><span>Free Application for
    Federal Student Aid</span></a><span> (FAFSA) by
    February 14 for priority consideration of financial aid. Include our school
    code, 002105, and keep your confirmation page for your records.</span></p>
    
    <p><strong><span>State Deadline</span></strong><span></span></p>
    
    <p><span>Maryland - March 1, 2014
    by midnight, Central Time.</span></p>
    
    <p><strong><span>                               </span></strong></p>
    
    <p><strong><span> </span></strong></p>
    
    <p><strong><span>Federal Deadline</span></strong><span></span></p>
    
    <p><span>Online applications must be submitted by midnight
    Central Time, June 30, 2015. Any corrections or updates must be submitted by
    midnight Central Time, September 19, 2015.</span></p>
    
    <p><span>What's Next?</span></p>
    
    <ul>
     <li>
    <span>Beginning in late March
         electronic notifications will be sent advising students to view their </span><span><a href="http://www.umbc.edu/financialaid/notification.html" rel="nofollow external" class="bo"><span>Financial
         Aid Packages</span></a></span><span> on <em>my</em>UMBC.</span>
    </li>
     <li>
    <strong><span>All required documents must be
         submitted and reviewed <u>before</u> an award notice will be
         generated. Failure to respond within the requested timeframe may reduce
         your student’s financial aid funding.</span></strong><span></span>
    </li>
     <li><span>The awards listed on the
         initial Award Notification are based on full-time enrollment. If your
         student plans to enroll for less than 12 credits (undergrad students),
         they must contact the Office of Financial Aid and Scholarships to discuss
         how part-time enrollment may affect their award.</span></li>
     <li>
    <span>If you would like
         to speak to the financial aid office concerning your student’s financial
         aid please have your student submit the </span><span><a href="http://www.umbc.edu/financialaid/forms/ferpa.pdf" rel="nofollow external" class="bo"><span>Authorization
         to Disclose Information</span></a></span><span> form.</span><span></span>
    </li>
    </ul>
    
    <p><span>For
    additional questions or concerns feel free to contact the Financial Aid Office
    directly at 410-455-2387 or </span><a href="mailto:finaid@umbc.edu" rel="nofollow external" class="bo"><strong><span>finaid@umbc.edu</span></strong></a><strong><span>.</span></strong></p>
    </div>
]]>
</Body>
<Summary>UMBC Deadline  Submit the Free Application for Federal Student Aid (FAFSA) by February 14 for priority consideration of financial aid. Include our school code, 002105, and keep your confirmation...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41274/guest@my.umbc.edu/faed09731cbf8b25c68db1915408de8c/api/pixel</TrackingUrl>
<Group token="retired-420">UMBC Family Connection </Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-420</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xsmall.png?1340914772</AvatarUrl>
<AvatarUrl size="original">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/original.png?1340914772</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xxlarge.png?1340914772</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xlarge.png?1340914772</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/large.png?1340914772</AvatarUrl>
<AvatarUrl size="medium">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/medium.png?1340914772</AvatarUrl>
<AvatarUrl size="small">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/small.png?1340914772</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xsmall.png?1340914772</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xxsmall.png?1340914772</AvatarUrl>
<Sponsor>UMBC Family Connection</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 08:54:51 -0500</PostedAt>
<EditAt>Wed, 12 Feb 2014 09:21:29 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41273" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41273">
<Title>Princeton Neuroscience Institute Summer Program!</Title>
<Tagline>Deadline: March 15, 2014</Tagline>
<Body>
<![CDATA[
    <div class="html-content">
    <p><span>The Princeton Neuroscience Institute (PNI) is offering a summer internship program for highly motivated undergraduates, providing education and hands-on research experience in the field of neuroscience. Participants will closely collaborate with students and faculty at the PNI on original research projects, and thereby gain invaluable first-hand experience on what it is like to be a neuroscientist.</span></p>
    <p><span>Summer interns will also participate in group educational activities, including weekly foundational overview lectures from PNI faculty, lab meetings with the researchers with whom they will work, journal club reading groups, plus special forums on topics such as career advice and graduate school application preparation.</span></p>
    <p><em><span>Applicants must be current undergraduates, US citizens, permanent residents, or foreign undergraduates attending a US educational institution.</span></em></p>
    <p><span>No stipend, housing expenses or other compensation will be provided to most interns during this summer research program.  This opportunity is offered strictly as an educational experience for highly motivated students interested in pursuing neuroscience in graduate school and beyond.</span></p>
    </div>
]]>
</Body>
<Summary>The Princeton Neuroscience Institute (PNI) is offering a summer internship program for highly motivated undergraduates, providing education and hands-on research experience in the field of...</Summary>
<Website>http://www.princeton.edu/neuroscience/summer-internship-program/definitions/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41273/guest@my.umbc.edu/e22fb02726a80f2f48df3f583690a5d9/api/pixel</TrackingUrl>
<Tag>research</Tag>
<Group token="undergradresearch">Undergraduate Research</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/undergradresearch</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xsmall.png?1600355057</AvatarUrl>
<AvatarUrl size="original">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/original.jpg?1600355057</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xxlarge.png?1600355057</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xlarge.png?1600355057</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/large.png?1600355057</AvatarUrl>
<AvatarUrl size="medium">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/medium.png?1600355057</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/small.png?1600355057</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xsmall.png?1600355057</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xxsmall.png?1600355057</AvatarUrl>
<Sponsor>Undergraduate Research</Sponsor>
<ThumbnailUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/xxlarge.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/xlarge.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="large">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/large.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="medium">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/medium.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="small">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/small.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/xsmall.jpg?1392212859</ThumbnailUrl>
<ThumbnailUrl size="xxsmall">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/041/273/476d9ee280c59ed43b3f813c6d3a44c6/xxsmall.jpg?1392212859</ThumbnailUrl>
<PawCount>13</PawCount>
<CommentCount>1</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 08:48:02 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="false" id="41272" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41272">
<Title>Cabin Fever</Title>
<Tagline>How Students Can Remain Engaged During the Winter</Tagline>
<Body>
<![CDATA[
    <div class="html-content">
    <p><span>The
    winter season this year on the east coast has been a little chilly.  Long winter nights and cold days can impact
    one’s mood and energy level. Some may find themselves even struggling with a
    bit of cabin fever. Well fortunately for UMBC students there are plenty of
    great things happening on campus that will keep them engaged regardless of the
    weather outside. Here are few tips that can be offered to your son or daughter
    during times of cabin fever:</span></p>
    
    <p><span>·<span>        
    </span></span><span>Attend a weekly </span><a href="http://my.umbc.edu/groups/seb/events/22423" rel="nofollow external" class="bo"><span>movie</span></a><span> – Each week students have an opportunity to
    view showings of a popular movie in Lecture Hall 1.</span></p>
    
    <p><span>·<span>        
    </span></span><span>Attend an Athletic
    Events – Spring sports are in full swing. Check out the schedules </span><a href="http://www.umbcretrievers.com/landing/index" rel="nofollow external" class="bo"><span>here!</span></a><span> </span></p>
    
    <p><span>·<span>        
    </span></span><span>Become involved or stay
    actively involved in campus organizations. Click </span><a href="http://osl.umbc.edu/orgs/" rel="nofollow external" class="bo"><span>here</span></a><span> for more info.</span></p>
    
    <p><span>·<span>        
    </span></span><span>Attend a UMBC event,
    these can be anything from bingo, video game tournaments, open mic nights and
    more. Check out </span><a href="http://my.umbc.edu/events" rel="nofollow external" class="bo"><span>myUMBC events page</span></a><span> for all the events happening on campus. </span></p>
    </div>
]]>
</Body>
<Summary>The winter season this year on the east coast has been a little chilly.  Long winter nights and cold days can impact one’s mood and energy level. Some may find themselves even struggling with a...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41272/guest@my.umbc.edu/cf0a68d74c3ba6e1a2a87f077aaaa5db/api/pixel</TrackingUrl>
<Group token="retired-420">UMBC Family Connection </Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-420</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xsmall.png?1340914772</AvatarUrl>
<AvatarUrl size="original">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/original.png?1340914772</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xxlarge.png?1340914772</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xlarge.png?1340914772</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/large.png?1340914772</AvatarUrl>
<AvatarUrl size="medium">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/medium.png?1340914772</AvatarUrl>
<AvatarUrl size="small">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/small.png?1340914772</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xsmall.png?1340914772</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/420/30293457191c29e0d0d7a715d26041bd/xxsmall.png?1340914772</AvatarUrl>
<Sponsor>UMBC Family Connection</Sponsor>
<PawCount>1</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Wed, 12 Feb 2014 08:45:04 -0500</PostedAt>
<EditAt>Wed, 12 Feb 2014 09:33:19 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41294" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41294">
<Title>The Tech Start-Up: Leaning In Can Be Uncomfortable</Title>
<Body>
<![CDATA[
    <div class="html-content">Something odd was in the air, but what? Then I noticed. In a room of sixty investors, there were no other women.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fboss.blogs.nytimes.com%2F2014%2F02%2F12%2Fleaning-in-can-be-uncomfortable%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=The+Tech+Start-Up%3A+Leaning+In+Can+Be+Uncomfortable" 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%2Fboss.blogs.nytimes.com%2F2014%2F02%2F12%2Fleaning-in-can-be-uncomfortable%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=The+Tech+Start-Up%3A+Leaning+In+Can+Be+Uncomfortable" 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%2Fboss.blogs.nytimes.com%2F2014%2F02%2F12%2Fleaning-in-can-be-uncomfortable%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=The+Tech+Start-Up%3A+Leaning+In+Can+Be+Uncomfortable" 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%2Fboss.blogs.nytimes.com%2F2014%2F02%2F12%2Fleaning-in-can-be-uncomfortable%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=The+Tech+Start-Up%3A+Leaning+In+Can+Be+Uncomfortable" 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%2Fboss.blogs.nytimes.com%2F2014%2F02%2F12%2Fleaning-in-can-be-uncomfortable%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=The+Tech+Start-Up%3A+Leaning+In+Can+Be+Uncomfortable" 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>
    </div>
]]>
</Body>
<Summary>Something odd was in the air, but what? Then I noticed. In a room of sixty investors, there were no other women.      </Summary>
<Website>http://boss.blogs.nytimes.com/2014/02/12/leaning-in-can-be-uncomfortable/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41294/guest@my.umbc.edu/651219322fe48b020b3abbfb1e35b32e/api/pixel</TrackingUrl>
<Tag>entrepreneurship</Tag>
<Tag>new</Tag>
<Tag>silicon-valley-calif</Tag>
<Tag>small-business</Tag>
<Tag>technology</Tag>
<Tag>the-tech-start-up</Tag>
<Tag>venture-capital</Tag>
<Tag>women-and-girls</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>Wed, 12 Feb 2014 07:00:54 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="41269" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41269">
<Title>Bits: Identity Theft Hits Home: The Aftermath</Title>
<Body>
<![CDATA[
    <div class="html-content">Store-branded credit cards are not terribly difficult to acquire. That’s bad news when your personal information has been stolen.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Fidentity-theft-hits-home-the-aftermath%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits%3A+Identity+Theft+Hits+Home%3A+The+Aftermath" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Fidentity-theft-hits-home-the-aftermath%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits%3A+Identity+Theft+Hits+Home%3A+The+Aftermath" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Fidentity-theft-hits-home-the-aftermath%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits%3A+Identity+Theft+Hits+Home%3A+The+Aftermath" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Fidentity-theft-hits-home-the-aftermath%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits%3A+Identity+Theft+Hits+Home%3A+The+Aftermath" 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%2Fbits.blogs.nytimes.com%2F2014%2F02%2F12%2Fidentity-theft-hits-home-the-aftermath%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits%3A+Identity+Theft+Hits+Home%3A+The+Aftermath" 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/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/sc/36/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530489320/u/0/f/640387/c/34625/s/3702cf75/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Store-branded credit cards are not terribly difficult to acquire. That’s bad news when your personal information has been stolen.      </Summary>
<Website>http://bits.blogs.nytimes.com/2014/02/12/identity-theft-hits-home-the-aftermath/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41269/guest@my.umbc.edu/c656cf6e7e94460418f0c9a9241c0067/api/pixel</TrackingUrl>
<Tag>best-buy-company-inc</Tag>
<Tag>best-buy-company-inc-bby-nyse</Tag>
<Tag>consumer-protection</Tag>
<Tag>equifax-inc</Tag>
<Tag>equifax-inc-efx-nyse</Tag>
<Tag>experian-group-ltd</Tag>
<Tag>frauds-and-swindling</Tag>
<Tag>kohls-corporation</Tag>
<Tag>kohls-corporation-kss-nyse</Tag>
<Tag>macys-inc</Tag>
<Tag>macys-inc-m-nyse</Tag>
<Tag>new</Tag>
<Tag>retailing</Tag>
<Tag>security</Tag>
<Tag>shopping-and-retail</Tag>
<Tag>technology</Tag>
<Tag>transunion-llc</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>Wed, 12 Feb 2014 07:00:36 -0500</PostedAt>
<EditAt>Fri, 14 Feb 2014 13:25:33 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41268" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41268">
<Title>How To Build A CLI Tool With Node.js And PhantomJS</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>In this article, we’ll go over the concepts and techniques required to build a command line tool using <a href="http://nodejs.org/" rel="nofollow external" class="bo">Node.js</a> and <a href="http://phantomjs.org/" rel="nofollow external" class="bo">PhantomJS</a>. Building a command line tool enables you to automate a process that would otherwise take a lot longer.</p>
    <p>Command line tools are built in a myriad of languages, but the one we’ll focus on is Node.js.</p>
    <h4>What We’ll Cover</h4>
    <ul>
    <li>Secret sauce</li>
    <li>Installing Node.js and npm</li>
    <li>Process</li>
    <li>Automation</li>
    <li>PhantomJS</li>
    <li>Squirrel</li>
    <li>How it works</li>
    <li>The code</li>
    <li>Packaging</li>
    <li>Publishing</li>
    <li>Conclusion</li>
    </ul>
    <h3>Secret Sauce</h3>
    <p>For those short on time, I’ve condensed the core process into three steps. This is the secret sauce to convert your Node.js script into a fully functioning command line tool. But do stick around to see what else I have to show you.</p>
    <ol>
    <li>In your <code>package.json</code> file, include the following settings:</li>
    </ol>
    <ul>
    <li><code>"preferGlobal": "true"</code></li>
    <li><code>"bin": { "name-of-command": "path-to-script.js" }</code></li>
    </ul>
    <li>Add <code>#!/usr/bin/env node</code> to <code>path-to-script.js</code>.</li>
    <li>To test your new command (<code>name-of-command</code>), use <code>npm link</code>.</li>
    
    <p>The rest of the process is just deciding what functionality to implement.</p>
    <h3>Installing Node.js And npm</h3>
    <p>To install Node.js, you have a few options:</p>
    <ul>
    <li>
    <a href="http://nodejs.org/download/" rel="nofollow external" class="bo">OS-specific installer</a> for Windows, Mac or binary;</li>
    <li>
    <a href="http://brew.sh/" rel="nofollow external" class="bo">Homebrew</a>: <code>brew install node</code>;</li>
    <li>
    <a href="https://github.com/isaacs/nave#nave" rel="nofollow external" class="bo">Nave</a>;</li>
    <li>
    <a href="https://github.com/creationix/nvm#node-version-manager" rel="nofollow external" class="bo">NVM</a>.</li>
    </ul>
    <p>Note that npm is installed as part of Node.js; there is no separate installation.</p>
    <p>To test that Node.js and npm are installed correctly, run the following commands in your terminal:</p>
    <ul>
    <li><code>node --version</code></li>
    <li><code>npm --version</code></li>
    </ul>
    <h3>Process</h3>
    <p>Let’s consider a sample process: generating an <a href="http://www.html5rocks.com/en/tutorials/appcache/beginner/" rel="nofollow external" class="bo">Application Cache</a> manifest file.</p>
    <p>In case you are unfamiliar with AppCache, it <strong>enables you to take your application offline</strong> by specifying pages and resources to cache in the event that the user loses their Internet connection or tries to access your application later offline.</p>
    <p>Typically, you would create an <a href="http://appcachefacts.info/" rel="nofollow external" class="bo">appcache.manifest</a> file, where you would configure the offline settings.</p>
    <p>We won’t go into much detail about AppCache itself because that would distract us from the purpose of this article. Nevertheless, below are the lines for a sample file:</p>
    <pre><code>&#x000A;    CACHE MANIFEST&#x000A;    &#x000A;    CACHE:&#x000A;    foo.jpg&#x000A;    index.html&#x000A;    offline.html&#x000A;    styles.css&#x000A;    behaviours.js&#x000A;    &#x000A;    NETWORK:&#x000A;    *&#x000A;    &#x000A;    FALLBACK:&#x000A;    / /offline.html&#x000A;    </code></pre>
    <p>As you can see, we’ve specified the following:</p>
    <ul>
    <li>a JPG image,</li>
    <li>two HTML files,</li>
    <li>a CSS file,</li>
    <li>a JavaScript file.</li>
    </ul>
    <p>These are the resources that we want to cache in case the user goes offline.</p>
    <p>We’ve also specified that all other items requested by the user should require a network to be accessed.</p>
    <p>Finally, we’ve stated that any file that should be cached but isn’t yet should redirect the user to a file named <code>offline.html</code>.</p>
    <h3>Automation</h3>
    <p>Having to manually look up all of the images, style sheets, scripts and other pages linked from a Web page would be tedious. Thus, we’re trying to automate the process of generating an AppCache manifest file.</p>
    <p>We could do this by writing some Node.js code along with some additional tools, but that wouldn’t be very easy (even for the person writing the script), because we would need to open the code and tell it which Web page to interrogate.</p>
    <p>We also want other people to have the benefit of this tool, without their needing to download a folder full of code, change certain lines of code and run commands to run the scripts.</p>
    <p>This is why a command line tool would help.</p>
    <h3>PhantomJS</h3>
    <p>First, we want to figure out how to solve this problem.</p>
    <p>We’ll use a tool named <a href="http://phantomjs.org/" rel="nofollow external" class="bo">PhantomJS</a>, which is a headless (i.e. chromeless) browser.</p>
    <p>Specifically, it’s a headless <a href="http://www.webkit.org/" rel="nofollow external" class="bo">WebKit</a> browser, which provides a JavaScript API that we can tap into and that lets us do things such as open Web pages and analyze their network requests. (It does many other things, but those are the two fundamental aspects we’re interested in.)</p>
    <p>We can use a Node.js module to load PhantomJS and interact with its API. We can then convert our code into a command line tool with relative ease using Node.js’s package manager, <a href="https://npmjs.org/" rel="nofollow external" class="bo">npm</a>, and a <code>package.json</code> file.</p>
    <h3>Squirrel</h3>
    <p>Luckily, I’ve already done the work for you. It’s an open-source project named <a href="https://github.com/Integralist/Squirrel#squirrel" rel="nofollow external" class="bo">Squirrel</a>.</p>
    <p>To install it, run the command <code>npm install -g squirrel-js</code>.</p>
    <p>Once it’s installed, you can use it by running the command <code>squirrel [url]</code>. For example, <code>squirrel bbc.co.uk/news</code>.</p>
    <p>This would generate (in the current directory) an <code>appcache.manifest</code> file populated with all relevant page resources.</p>
    <h3>How It Works</h3>
    <p>I started Squirrel by first writing the relevant Node.js and PhantomJS code to incorporate the functionality I was after.</p>
    <p>Then, I added a script that bootstraps that code and allows me to take arguments that configure how the code runs.</p>
    <p>I ended up with two scripts:</p>
    <ul>
    <li><a href="https://github.com/Integralist/Squirrel/blob/master/lib/squirrel.js" rel="nofollow external" class="bo">squirrel.js</a></li>
    <li><a href="https://github.com/Integralist/Squirrel/blob/master/lib/appcache.js" rel="nofollow external" class="bo">appcache.js</a></li>
    </ul>
    <p>The first script sets up the work:</p>
    <ul>
    <li>We specify the environment in which we want the script to execute (in this case, Node.js).</li>
    <li>Parse the arguments passed by the user.</li>
    <li>Read an internal (i.e. dummy) <code>appcache.manifest</code> file.</li>
    <li>Open a shell child process, call PhantomJS and pass it the script that we want it to execute (in this case, <code>appcache.js</code>) and the dummy manifest file.</li>
    <li>When the second script finishes its work (collating the Web page data), return to this first script and display some statistical information to the user and generate the manifest file.</li>
    </ul>
    <p>The second script processes the Web page that the user has requested:</p>
    <ul>
    <li>We take in the dummy manifest file.</li>
    <li>Create listeners for the page resources that are requested.</li>
    <li>Set the viewport size.</li>
    <li>Open the Web page and store the resources.</li>
    <li>Get all links from the page (by executing JavaScript code directly in the Web page).</li>
    <li>Convert the contents of the manifest file and inject the resources found, and then return that as a JSON file.</li>
    </ul>
    <h3>The Code</h3>
    <p>Now that you understand what the code does, let’s review it. I’ll show the code in its entirely, and then we’ll go through it piecemeal.</p>
    <h4>squirrel.js</h4>
    <pre><code>&#x000A;    #!/usr/bin/env node&#x000A;    &#x000A;    var userArguments = process.argv.slice(2); // Copies arguments list but removes first two options (script exec type &amp; exec location)&#x000A;    &#x000A;    if (userArguments.length &gt; 1) {&#x000A;        throw new Error('Only one argument may be specified (the URL for which you want to generate the AppCache.)');&#x000A;    }&#x000A;    &#x000A;    var fs               = require('fs');&#x000A;    var shell            = require('child_process').execFile;&#x000A;    var phantomjs        = require('phantomjs').path;&#x000A;    var scriptToExecute  = __dirname + '/appcache.js';&#x000A;    var manifest         = __dirname + '/../appcache.manifest';&#x000A;    var url              = userArguments[0];&#x000A;    var manifestContent;&#x000A;    var data;&#x000A;    &#x000A;    fs.readFile(manifest, bootstrap);&#x000A;    &#x000A;    function bootstrap(err, contentAsBuffer) {&#x000A;        if (err) throw err;&#x000A;    &#x000A;        manifestContent = contentAsBuffer.toString('utf8');&#x000A;    &#x000A;        shell(phantomjs, [scriptToExecute, url, manifestContent], function(err, stdout, stderr) {&#x000A;            if (err) throw err;&#x000A;    &#x000A;            // Sometimes an error in the loaded page's JavaScript doesn't get picked up or thrown,&#x000A;            // but the error comes in via stdout and causes JSON parsing to break&#x000A;            try {&#x000A;                data = JSON.parse(stdout);&#x000A;            } catch(err) {&#x000A;                log('Whoops! It seems there was an error? You\'ll find the stack trace below.');&#x000A;                error(err);&#x000A;            }&#x000A;    &#x000A;            displayStatistics();&#x000A;            createManifestFile();&#x000A;        });&#x000A;    }&#x000A;    &#x000A;    function displayStatistics() {&#x000A;        log(''); // Adds extra line of spacing when displaying the results&#x000A;        log('Links: '      + data.links);&#x000A;        log('Images: '     + data.images);&#x000A;        log('CSS: '        + data.css);&#x000A;        log('JavaScript: ' + data.javascript);&#x000A;    }&#x000A;    &#x000A;    function createManifestFile() {&#x000A;        fs.writeFile(process.cwd() + '/appcache.manifest', data.manifestContent, function(err) {&#x000A;            if (err) throw err;&#x000A;    &#x000A;            log('\nManifest file created');&#x000A;        });&#x000A;    }&#x000A;    &#x000A;    function log(message) {&#x000A;        process.stdout.write(message + '\n');&#x000A;    }&#x000A;    &#x000A;    function error(err) {&#x000A;        process.stderr.write(err);&#x000A;    }&#x000A;    </code></pre>
    <p>The first line, <code>#!/usr/bin/env node</code>, is critical to the script being used in the shell. We have to tell the shell what process should handle the script.</p>
    <p>Next, we have to retrieve the arguments passed to the command. If we run <code>squirrel bbc.co.uk/news</code>, then <code>process.argv</code> would be an array containing the following:</p>
    <ul>
    <li>the script execution type (<code>node</code>);</li>
    <li>the script being executed (<code>squirrel.js</code>);</li>
    <li>any other arguments (in this instance, only one, <code>bbc.co.uk/news</code>).</li>
    </ul>
    <p>Ignore the first two arguments, and store the user-specific arguments so that we can reference them later:</p>
    <pre><code>&#x000A;    var userArguments = process.argv.slice(2);&#x000A;    </code></pre>
    <p>Our script only knows how to handle a single argument (which is the page URL to load). The following line isn’t really needed because we’ll ignore any more than one argument, but it’s useful for the code to have clear intent, so we’ll throw an error if more than one argument is passed.</p>
    <pre><code>&#x000A;    if (userArguments.length &gt; 1) {&#x000A;        throw new Error('Only one argument may be specified (the URL for which you want to generate the AppCache.)');&#x000A;    }&#x000A;    </code></pre>
    <p>Because we’re using PhantomJS, we’ll need to open up a shell and call the <code>phantomjs</code> command:</p>
    <pre><code>&#x000A;    var shell = require('child_process').execFile;&#x000A;    </code></pre>
    <p>We’ll also need to reference the <code>bin</code> directory, where the PhantomJS executable is stored:</p>
    <pre><code>&#x000A;    var phantomjs = require('phantomjs').path;&#x000A;    </code></pre>
    <p>Next, store a reference to the script that we want PhantomJS to execute, as well as the dummy manifest file.</p>
    <pre><code>&#x000A;    var scriptToExecute = __dirname + '/appcache.js';&#x000A;    var manifest        = __dirname + '/../appcache.manifest';&#x000A;    var url             = userArguments[0];&#x000A;    </code></pre>
    <p>Because the PhantomJS script that we’ll be executing needs a reference to the dummy manifest file, we’ll asynchronously read the contents of the file and then pass it on to a <code>bootstrap</code> function:</p>
    <pre><code>&#x000A;    fs.readFile(manifest, bootstrap);&#x000A;    </code></pre>
    <p>Our <code>bootstrap</code> function does exactly what you would expect: start our application (in this case, by opening the shell and calling PhantomJS). You’ll also notice that Node.js passes the contents of the manifest as a buffer, which we need to convert back into a string:</p>
    <pre><code>&#x000A;    function bootstrap(err, contentAsBuffer) {&#x000A;        if (err) throw err;&#x000A;    &#x000A;        manifestContent = contentAsBuffer.toString('utf8');&#x000A;    &#x000A;        shell(phantomjs, [scriptToExecute, url, manifestContent], function(err, stdout, stderr) {&#x000A;            // code...&#x000A;        });&#x000A;    }&#x000A;    </code></pre>
    <p>At this point in the execution of the code, we are in the <code>appcache.js</code> file. Let’s move over there now.</p>
    <h4>appcache.js</h4>
    <p>The purpose of <code>appcache.js</code> is to get information from the user-requested page and pass it back to <code>squirrel.js</code> for processing.</p>
    <p>Again, I’ll show the script in its entirety, and then we’ll break it down. (Don’t worry, we won’t go over each line — only the important parts.)</p>
    <pre><code>&#x000A;    var unique     = require('lodash.uniq');&#x000A;    var system     = require('system');&#x000A;    var fs         = require('fs');&#x000A;    var page       = require('webpage').create();&#x000A;    var args       = system.args;&#x000A;    var manifest   = args[2];&#x000A;    var css        = [];&#x000A;    var images     = [];&#x000A;    var javascript = [];&#x000A;    var links;&#x000A;    var url;&#x000A;    var path;&#x000A;    &#x000A;    bootstrap();&#x000A;    pageSetUp();&#x000A;    openPage();&#x000A;    &#x000A;    function bootstrap() {&#x000A;        if (urlProvided()) {&#x000A;            url = cleanUrl(args[1]);&#x000A;        } else {&#x000A;            var error = new Error('Sorry, a valid URL could not be recognized');&#x000A;                error.additional = 'Valid URL example: bbc.co.uk/news';&#x000A;    &#x000A;            throw error;&#x000A;    &#x000A;            phantom.exit();&#x000A;        }&#x000A;    &#x000A;        if (bbcNews()) {&#x000A;            // We want to serve the responsive code base.&#x000A;            phantom.addCookie({&#x000A;                'name'  : 'ckps_d',&#x000A;                'value' : 'm',&#x000A;                'domain': '.bbc.co.uk'&#x000A;            });&#x000A;        }&#x000A;    }&#x000A;    &#x000A;    function pageSetUp() {&#x000A;        page.onResourceRequested = function(request) {&#x000A;            if (/\.(?:png|jpeg|jpg|gif)$/i.test(request.url)) {&#x000A;                images.push(request.url);&#x000A;            }&#x000A;    &#x000A;            if (/\.(?:js)$/i.test(request.url)) {&#x000A;                javascript.push(request.url);&#x000A;            }&#x000A;    &#x000A;            if (/\.(?:css)$/i.test(request.url)) {&#x000A;                css.push(request.url);&#x000A;            }&#x000A;        };&#x000A;    &#x000A;        page.onError = function(msg, trace) {&#x000A;            console.log('Error :', msg);&#x000A;    &#x000A;            trace.forEach(function(item) {&#x000A;                console.log('Trace:  ', item.file, ':', item.line);&#x000A;            });&#x000A;        }&#x000A;    &#x000A;        page.viewportSize = { width: 1920, height: 800 };&#x000A;    }&#x000A;    &#x000A;    function openPage() {&#x000A;        page.open(url, function(status) {&#x000A;            links      = unique(getLinks());&#x000A;            images     = unique(images);&#x000A;            css        = unique(css);&#x000A;            javascript = unique(javascript);&#x000A;    &#x000A;            populateManifest();&#x000A;    &#x000A;            // Anything written to stdout is actually passed back to our Node script callback&#x000A;            console.log(JSON.stringify({&#x000A;                links           : links.length,&#x000A;                images          : images.length,&#x000A;                css             : css.length,&#x000A;                javascript      : javascript.length,&#x000A;                manifestContent : manifest&#x000A;            }));&#x000A;    &#x000A;            phantom.exit();&#x000A;        });&#x000A;    }&#x000A;    &#x000A;    function urlProvided() {&#x000A;        return args.length &gt; 1 &amp;&amp; /(?:www\.)?[a-z-z1-9]+\./i.test(args[1]);&#x000A;    }&#x000A;    &#x000A;    function cleanUrl(providedUrl) {&#x000A;        // If no http or https found at the start of the URL...&#x000A;        if (/^(?!https?:\/\/)[\w\d]/i.test(providedUrl)) {&#x000A;            return '<a href="http://">http://</a>' + providedUrl + '/';&#x000A;        }&#x000A;    }&#x000A;    &#x000A;    function bbcNews(){&#x000A;        if (/bbc.co.uk\/news/i.test(url)) {&#x000A;            return true;&#x000A;        }&#x000A;    }&#x000A;    &#x000A;    function getLinks() {&#x000A;        var results = page.evaluate(function() {&#x000A;            return Array.prototype.slice.call(document.getElementsByTagName('a')).map(function(item) {&#x000A;                return item.href;&#x000A;            });&#x000A;        });&#x000A;    &#x000A;        return results;&#x000A;    }&#x000A;    &#x000A;    function writeVersion() {&#x000A;        manifest = manifest.replace(/# Timestamp: \d+/i, '# Timestamp: ' + (new Date()).getTime());&#x000A;    }&#x000A;    &#x000A;    function writeListContentFor(str, type) {&#x000A;        manifest = manifest.replace(new RegExp('(# ' + str + ')\\n[\\s\\S]+?\\n\\n', 'igm'), function(match, cg) {&#x000A;            return cg + '\n' + type.join('\n') + '\n\n';&#x000A;        });&#x000A;    }&#x000A;    &#x000A;    function populateManifest() {&#x000A;        writeVersion();&#x000A;    &#x000A;        writeListContentFor('Images', images);&#x000A;        writeListContentFor('Internal HTML documents', links);&#x000A;        writeListContentFor('Style Sheets', css);&#x000A;        writeListContentFor('JavaScript', javascript);&#x000A;    }&#x000A;    </code></pre>
    <p>We begin by using PhantomJS’ API to create a new Web page:</p>
    <pre><code>&#x000A;    var page = require('webpage').create();&#x000A;    </code></pre>
    <p>Next, we’ll check that a URL was provided and, if so, clean it into the format required (for example, by giving it an <code>http</code> protocol). Otherwise, we’ll throw an error and stop PhantomJS:</p>
    <pre><code>&#x000A;    if (urlProvided()) {&#x000A;        url = cleanUrl(args[1]);&#x000A;    } else {&#x000A;        var error = new Error('Sorry, a valid URL could not be recognized');&#x000A;        error.additional = 'Valid URL example: bbc.co.uk/news';&#x000A;    &#x000A;        throw error;&#x000A;        phantom.exit();&#x000A;    }&#x000A;    </code></pre>
    <p>We also put in a check to see whether the URL passed was for <code>bbc.co.uk/news</code> and, if so, use PhantomJS to set a cookie that enables the responsive version of the website to load (the purpose being merely to demonstrate some of PhantomJS’ useful APIs, such as <code>addCookie</code>):</p>
    <pre><code>&#x000A;    if (bbcNews()) {&#x000A;        phantom.addCookie({&#x000A;            'name'  : 'ckps_d',&#x000A;            'value' : 'm',&#x000A;            'domain': '.bbc.co.uk'&#x000A;        });&#x000A;    }&#x000A;    </code></pre>
    <p>For PhantomJS to be able to analyze the network data (so that we can track the style sheets, JavaScript and images being requested by the page), we need to use special PhantomJS handlers to interpret the requests:</p>
    <pre><code>&#x000A;    page.onResourceRequested = function(request) {&#x000A;        if (/\.(?:png|jpeg|jpg|gif)$/i.test(request.url)) {&#x000A;            images.push(request.url);&#x000A;        }&#x000A;    &#x000A;        if (/\.(?:js)$/i.test(request.url)) {&#x000A;            javascript.push(request.url);&#x000A;        }&#x000A;    &#x000A;        if (/\.(?:css)$/i.test(request.url)) {&#x000A;            css.push(request.url);&#x000A;        }&#x000A;    };&#x000A;    </code></pre>
    <p>We’ll also use another PhantomJS API feature that enables us to determine the size of the browser window:</p>
    <pre><code>&#x000A;    page.viewportSize = { width: 1920, height: 800 };&#x000A;    </code></pre>
    <p>We then tell PhantomJS to open the specified Web page. Once the page is open (i.e. the <code>load</code> event has fired), a callback is executed:</p>
    <pre><code>&#x000A;    page.open(url, function(status) {&#x000A;        // code...&#x000A;    });&#x000A;    </code></pre>
    <p>In the callback, we store the resources that were found, and we call a function that replaces the contents of our string (the dummy manifest) with a list of each set of resources:</p>
    <pre><code>&#x000A;    page.open(url, function(status) {&#x000A;        links      = unique(getLinks());&#x000A;        images     = unique(images);&#x000A;        css        = unique(css);&#x000A;        javascript = unique(javascript);&#x000A;    &#x000A;        populateManifest();&#x000A;    &#x000A;        // Remaining code...&#x000A;    });&#x000A;    </code></pre>
    <p>Finally, we create a data object to hold statistics about the resources being requested, convert it to a JSON string, and log it using the <code>console</code> API.</p>
    <p>Once this is done, we tell PhantomJS to <code>exit</code> (otherwise the process would stall):</p>
    <pre><code>&#x000A;    page.open(url, function(status) {&#x000A;        // Previous code...&#x000A;    &#x000A;        console.log(JSON.stringify({&#x000A;            links           : links.length,&#x000A;            images          : images.length,&#x000A;            css             : css.length,&#x000A;            javascript      : javascript.length,&#x000A;            manifestContent : manifest&#x000A;        }));&#x000A;    &#x000A;        phantom.exit();&#x000A;    });&#x000A;    </code></pre>
    <p>Reviewing the code above, you might wonder how we get the data back to our <code>squirrel.js</code> script? Take another look at the <code>console.log</code>. The code has an odd side effect, which is that any code logged by PhantomJS is passed back to our shell callback (originally executed in <code>squirrel.js</code>).</p>
    <p>Let’s revisit our <code>squirrel.js</code> script now.</p>
    <h4>Back to squirrel.js</h4>
    <pre><code>&#x000A;    shell(phantomjs, [scriptToExecute, url, manifestContent], function(err, stdout, stderr) {&#x000A;        if (err) throw err;&#x000A;    &#x000A;        try {&#x000A;            data = JSON.parse(stdout);&#x000A;        } catch(err) {&#x000A;            log('Whoops! It seems there was an error? You\'ll find the stack trace below.');&#x000A;            error(err);&#x000A;        }&#x000A;    &#x000A;        displayStatistics();&#x000A;        createManifestFile();&#x000A;    });&#x000A;    </code></pre>
    <p>The callback function is run when the PhantomJS script finishes executing. It is passed any errors that may have occurred and, if there are, then we throw the error:</p>
    <p><code>if (err) throw err;</code></p>
    <p>The other arguments are the standard output and error arguments provided by the shell. In this case, the standard output would be our JSON string, which we <code>console.log</code>’ed from <code>appcache.js</code>. We parse the JSON string and convert it back into an object so that we can present the data to the user who has run the <code>squirrel</code> command.</p>
    <p>As a side note, we wrap this conversion in a <code>try/catch</code> clause to protect against Web pages that cause a JavaScript error to occur (the error is picked up by <code>stdout</code>, not <code>stderr</code>, thus causing the JSON parsing to break):</p>
    <pre><code>&#x000A;    try {&#x000A;        data = JSON.parse(stdout);&#x000A;    } catch(err) {&#x000A;        error(err);&#x000A;    }&#x000A;    </code></pre>
    <p>Once we have our data, we call <code>displayStatistics</code>, which uses <code>stdout</code> to write a message to the user’s terminal.</p>
    <p>Lastly, we call <code>createManifestFile</code>, which creates an <code>appcache.manifest</code> file in the user’s current directory:</p>
    <pre><code>&#x000A;    fs.writeFile(process.cwd() + '/appcache.manifest', data.manifestContent, function(err) {&#x000A;        if (err) throw err;&#x000A;    &#x000A;        log('\nManifest file created');&#x000A;    });&#x000A;    </code></pre>
    <p>Now that we understand how the script works in its entirety, let’s look at how to allow others to download and install our work.</p>
    <h3>Packaging</h3>
    <p>For other users to be able to install our module, we’ll need to publish it to a public repository. The place to do this is the <a href="https://npmjs.org/" rel="nofollow external" class="bo">npm</a> registry.</p>
    <p>To publish to npm, you’ll need a <code>package.json</code> file.</p>
    <p>The purpose of <code>package.json</code> is to specify the dependencies of the project you’re working on. In this instance, it specifies the dependencies required by Squirrel to do its job.</p>
    <p>Below is Squirrel’s <code>package.json</code> file:</p>
    <pre><code>&#x000A;    {&#x000A;      "name": "squirrel-js",&#x000A;      "version": "0.1.3",&#x000A;      "description": "Node.js-based CLI tool, using PhantomJS to automatically generate an Application Cache manifest file for a specified URL",&#x000A;      "main": "lib/squirrel",&#x000A;      "scripts": {&#x000A;        "test": "echo "Error: no test specified" &amp;&amp; exit 1"&#x000A;      },&#x000A;      "engines": {&#x000A;        "node": "&gt;=0.10"&#x000A;      },&#x000A;      "repository": {&#x000A;        "type": "git",&#x000A;        "url": "<a href="git://github.com/Integralist/Squirrel.git">git://github.com/Integralist/Squirrel.git</a>"&#x000A;      },&#x000A;      "preferGlobal": "true",&#x000A;      "bin": {&#x000A;        "squirrel": "lib/squirrel.js"&#x000A;      },&#x000A;      "dependencies": {&#x000A;        "phantomjs": "~1.9.2-6",&#x000A;        "lodash.uniq": "~2.4.1"&#x000A;      },&#x000A;      "keywords": [&#x000A;        "appcache",&#x000A;        "phantomjs",&#x000A;        "cli"&#x000A;      ],&#x000A;      "author": "Mark McDonnell  (<a href="http://www.integralist.co.uk/">http://www.integralist.co.uk/</a>)",&#x000A;      "license": "MIT",&#x000A;      "bugs": {&#x000A;        "url": "<a href="https://github.com/Integralist/Squirrel/issues">https://github.com/Integralist/Squirrel/issues</a>"&#x000A;      },&#x000A;      "homepage": "<a href="https://github.com/Integralist/Squirrel">https://github.com/Integralist/Squirrel</a>"&#x000A;    }&#x000A;    </code></pre>
    <p>You can read up on all of the properties of <code>package.json</code> in the <a href="https://npmjs.org/doc/json.html" rel="nofollow external" class="bo">npm registry</a>.</p>
    <p>The properties to note are these:</p>
    <ul>
    <li><code>"preferGlobal": "true"</code></li>
    <li><code>"bin": { "squirrel": "lib/squirrel.js" }</code></li>
    </ul>
    <p>The first property indicates when a user has installed a module that you would prefer to be installed globally. In this case, we want it to be installed globally because then the user will be able to run the command anywhere in their system.</p>
    <p>The second property indicates where the command will find the code required to execute the command.</p>
    <p>To test that your command works, you’ll need to run the <code>npm link</code> command, which in this case creates a symlink from the <code>squirrel</code> command to the <code>squirrel.js</code> file.</p>
    <h3>Publishing</h3>
    <p>To publish your code, first <a href="https://npmjs.org/signup" rel="nofollow external" class="bo">register</a> for an npm account.</p>
    <p>You’ll need to verify the account via the command line. To do this, run <code>npm adduser</code>, which will ask you to specify a user name and password.</p>
    <p>Once you’ve verified the account, you can publish your module to the npm registry using <code>npm publish</code>.</p>
    <p>It could take a few minutes for the module to become publicly accessible.</p>
    <p>Be aware that if you update the code and try to run <code>npm publish</code> without updating the <code>package.json</code> file’s <code>version</code> property, then npm will return an error asking you to update the version number.</p>
    <h3>Conclusion</h3>
    <p>This is just one example of the sort of command line tools you can develop with Node.js’ many features.</p>
    <p>The next time you find yourself performing a repetitive task, consider automating the process with a CLI tool.</p>
    <p><em>(al)</em></p>
    <hr>
    <p><small>© Mark McDonnell for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2014.</small></p>
    </div>
]]>
</Body>
<Summary>        In this article, we’ll go over the concepts and techniques required to build a command line tool using Node.js and PhantomJS. Building a command line tool enables you to automate a process...</Summary>
<Website>http://www.smashingmagazine.com/2014/02/12/how-to-build-a-cli-tool-with-node-js-and-phantomjs/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41268/guest@my.umbc.edu/3dd955463cdd7b249cc9f04822b204ad/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>Wed, 12 Feb 2014 05:24:23 -0500</PostedAt>
</NewsItem>

</News>
