<?xml version="1.0"?>
<News hasArchived="true" page="7817" pageCount="10771" pageSize="10" timestamp="Thu, 27 Aug 2026 01:36:29 -0400" url="https://my3.my.umbc.edu/posts.xml?mode=activity&amp;page=7817">
<NewsItem contentIssues="true" id="41325" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41325">
<Title>SOLID: Part 4 - The Dependency Inversion Principle</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>The <a href="http://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle--net-36074" rel="nofollow external" class="bo">Single Responsibility (SRP)</a>, <a href="http://code.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle--net-36600" rel="nofollow external" class="bo">Open/Closed (OCP)</a>, <a href="http://code.tutsplus.com/tutorials/solid-part-3-liskov-substitution-interface-segregation-principles--net-36710" rel="nofollow external" class="bo">Liskov Substitution, Interface Segregation,</a> and <em>Dependency Inversion</em>. Five agile principles that should guide you every time you write code.</p>
    <p></p>
    <p>It would be unjust to tell you that any one of the SOLID principles is more important than another. However, probably none of the others have such an immediate and profound effect on your code than the Dependency Inversion Principle, or DIP in short. If you find the other principles hard to grasp or apply, start with this one and apply the rest on code that already respects DIP.</p>
    <hr>
    <h2>Definition</h2>
    <blockquote><p>A. High-level modules should not depend on low-level modules. Both should depend on abstractions.<br>
    B. Abstractions should not depend upon details. Details should depend upon abstractions.</p></blockquote>
    <p>This principle was defined by <a href="http://www.8thlight.com/our-team/robert-martin" rel="nofollow external" class="bo">Robert C. Martin</a> in his book <a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1378755964&amp;sr=1-1&amp;keywords=robert+c+martin" rel="nofollow external" class="bo">Agile Software Development, Principles, Patterns, and Practices</a> and later republished in the C# version of the book <a href="http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258" rel="nofollow external" class="bo">Agile Principles, Patterns, and Practices in C#</a>, and it is the last of the five SOLID agile principles.<br>
    </p>
    <hr>
    <h2>DIP in the Real World</h2>
    <p>Before we start coding, I would like to tell you a story. At Syneto, we weren't always so careful with our code. A few years ago we knew less and even though we tried to do our best, not all of our projects were so nice. We went through hell and back again and we learned many things by trial and error.</p>
    <p>The SOLID principles and the clean architecture principles of Uncle Bob (Robert C. Martin) became a game changer for us and transformed our way of coding in ways that are hard to describe. I will try to exemplify, in a nutshell, a few key architectural decisions imposed by DIP that had a great impact on our projects.</p>
    <p>Most web projects contain three main technologies: HTML, PHP, and SQL. The particular version of these applications we are talking about or what type of SQL implementations you use is irrelevant. The thing is, that information from an HTML form must end up, in one way or another, in the database. The glue between the two can be provided with PHP.</p>
    <p>What is essential to take away from this, is that how nicely the three technologies represent three different architectural layers: user interface, business logic, and persistence. We will talk about the implications of these layers in a minute. For now, let's focus on some odd but frequently encountered solutions to make the technologies work together.</p>
    <p>Many times I've seen projects that used SQL code in a PHP tag inside an HTML file, or PHP code echoing pages and pages of HTML and interpreting directly the <code>$_GET</code> or <code>$_POST</code> global variables. But why is this bad?</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/html-php-sql-cross-dependencies.png" alt="html-php-sql-cross-dependencies" width="600" height="423" style="max-width: 100%; height: auto;"><br>
    
    <p>The images above represent a raw version of what we described in the previous paragraph. The arrows represent various dependencies, and as we can conclude, basically everything depends on everything. If we need to change a database table, we may end up editing an HTML file. Or if we change a field in HTML, we may end up changing the name of a column in an SQL statement. Or if we look at the second schema, we may very well need to modify our PHP if the HTML changes, or in very bad cases, when we generate all HTML content from inside a PHP file we will surely need to change a PHP file to modify HTML content. So, there is no doubt, the dependencies are zigzagging between the classes and modules. But it doesn't end here. You can store procedures; PHP code in SQL tables.</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/html-php-sql-stored-procedures.png" alt="html-php-sql-stored-procedures" width="600" height="503" style="max-width: 100%; height: auto;"><br>
    
    <p>In the schema above, queries to the SQL database return PHP code generated with data from the tables. These PHP functions or classes are doing other SQL queries which are returning different PHP code, and the cycle continues until finally all the information is obtained and returned... probably to the UI.</p>
    <p>I know this may sound outrageous to many of you, but if you have not yet worked with a project invented and implemented in this manner, you surely will in your future career. Most existing projects, regardless of the programming languages used, were written with old principles in mind, by programmers who did not care or know enough to do better. If you are reading these tutorials, you are most likely a level higher than that. You are ready, or getting ready to respect your profession, to embrace your craft, and to do better.</p>
    <p>The other option is to repeat the mistakes your predecessors made and live with the consequences. At Syneto, after one of our projects reached an almost unmaintainable state because of its old and cross-dependent architecture and we had to basically abandon it forever, we decided to never go back down that road again. Since then, we have striven to have a clean architecture which correctly respects the SOLID principles, and most importantly the Dependency Inversion Principle.</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/HighLevelDesign.png" alt="HighLevelDesign" width="600" height="388" style="max-width: 100%; height: auto;"><br>
    
    <p>What's so amazing about this architecture is how the dependencies are pointing:</p>
    <ul>
    <li>The user interface (in most cases a web MVC framework) or whatever other delivery mechanism there is for your project will depend on the business logic. Business logic is quite abstract. A user interface is very concrete. The UI is just a detail for the project, and it is also very volatile. Nothing should depend on the UI, nothing should depend on your MVC framework.</li>
    <li>The other interesting observation we can make is that the persistence, the database, your MySQL or PostgreSQL, depends on the business logic. Your business logic is database agnostic. This allows exchanging persistence as you wish. If tomorrow you want to change MySQL with PostgreSQL or just plain text files, you can do that. You will, of course, need to implement a specific persistence layer for the new persistence method, but you will not need to modify a single line of code in your business logic. There is a more detailed explanation on the persistence topic in the <a href="http://code.tutsplus.com/tutorials/evolving-toward-a-persistence-layer--net-27138" rel="nofollow external" class="bo">Evolving Toward a Persistence Layer</a> tutorial. </li>
    <li>Finally, on the right of the business logic, outside of it, we have all the classes that are creating business logic classes. These are factories and classes created by the entry point to our application. Many people tend to think these belong to the business logic, but while they are creating business objects, their sole reason is to do this. They are classes just to help us create other classes. The business objects and the logic they provide are independent of these factories. We could use different patterns, like Simple Factory, Abstract Factory, Builder or plain object creation to provide the business logic. It doesn't matter. Once the business objects are created they can do their job.</li>
    </ul>
    <hr>
    <h2>Show Me the Code</h2>
    <p>Applying the Dependency Inversion Principle (DIP) at an architectural level is quite easy if you respect the classic <a href="https://tutsplus.com/course/agile-design-patterns/" rel="nofollow external" class="bo">agile design patterns</a>. Exercising and exemplifying it inside the business logic is quite easy also and can even be fun. We will imagine an e-book reader application.</p>
    <pre>class Test extends PHPUnit_Framework_TestCase {&#x000A;    &#x000A;    	function testItCanReadAPDFBook() {&#x000A;    		$b = new PDFBook();&#x000A;    		$r = new PDFReader($b);&#x000A;    &#x000A;    		$this-&gt;assertRegExp('/pdf book/', $r-&gt;read());&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class PDFReader {&#x000A;    &#x000A;    	private $book;&#x000A;    &#x000A;    	function __construct(PDFBook $book) {&#x000A;    		$this-&gt;book = $book;&#x000A;    	}&#x000A;    &#x000A;    	function read() {&#x000A;    		return $this-&gt;book-&gt;read();&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class PDFBook {&#x000A;    &#x000A;    	function read() {&#x000A;    		return "reading a pdf book.";&#x000A;    	}&#x000A;    }</pre>
    <p>We start developing our e-reader as a PDF reader. So far so good. We have a <code>PDFReader</code> class using a <code>PDFBook</code>. The <code>read()</code> function on the reader delegates to the book's <code>read()</code> method. We just verify this by doing a regex check after a key part of the string returned by <code>PDFBook</code>'s <code>reader()</code> method.</p>
    <p>Please bear in mind that this is just an example. We will not implement the reading logic of PDF files or other file formats. That's why our tests will just simply check for some basic strings. If we were to write the real application, the only difference would be how we test the different file formats. The dependency structure would be very similar to our example.</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/pdfreader-pdfbook.png" alt="pdfreader-pdfbook" width="600" height="89" style="max-width: 100%; height: auto;"><br>
    
    <p>Having a PDF reader using a PDF book may be a sound solution for a limited application. If our scope was to write a PDF reader and nothing more, it would actually be an acceptable solution. But we want to write a generic e-book reader, supporting several formats, amongst which our first implemented version PDF. Let's rename our reader class.</p>
    <pre>class Test extends PHPUnit_Framework_TestCase {&#x000A;    &#x000A;    	function testItCanReadAPDFBook() {&#x000A;    		$b = new PDFBook();&#x000A;    		$r = new EBookReader($b);&#x000A;    &#x000A;    		$this-&gt;assertRegExp('/pdf book/', $r-&gt;read());&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class EBookReader {&#x000A;    &#x000A;    	private $book;&#x000A;    &#x000A;    	function __construct(PDFBook $book) {&#x000A;    		$this-&gt;book = $book;&#x000A;    	}&#x000A;    &#x000A;    	function read() {&#x000A;    		return $this-&gt;book-&gt;read();&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class PDFBook {&#x000A;    &#x000A;    	function read() {&#x000A;    		return "reading a pdf book.";&#x000A;    	}&#x000A;    }</pre>
    <p>Renaming had no functional counter effects. The tests are still passing.</p>
    <p>Testing started at 1:04 PM ...<br>
    PHPUnit 3.7.28 by Sebastian Bergmann.<br>
    Time: 13 ms, Memory: 2.50Mb<br>
    OK (1 test, 1 assertion)<br>
    Process finished with exit code 0</p>
    <p>But it has a serious design effect.</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/ebookreader-pdfbook.png" alt="ebookreader-pdfbook" width="600" height="89" style="max-width: 100%; height: auto;"><br>
    
    <p>Our reader became much more abstract. Much more general. We have a generic <code>EBookReader</code> that uses a very specific book type, <code>PDFBook</code>. An abstraction depends on a detail. The fact that our book is of type PDF should only be a detail, and no one should depend on it.</p>
    <pre>class Test extends PHPUnit_Framework_TestCase {&#x000A;    &#x000A;    	function testItCanReadAPDFBook() {&#x000A;    		$b = new PDFBook();&#x000A;    		$r = new EBookReader($b);&#x000A;    &#x000A;    		$this-&gt;assertRegExp('/pdf book/', $r-&gt;read());&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    interface EBook {&#x000A;    	function read();&#x000A;    }&#x000A;    &#x000A;    class EBookReader {&#x000A;    &#x000A;    	private $book;&#x000A;    &#x000A;    	function __construct(EBook $book) {&#x000A;    		$this-&gt;book = $book;&#x000A;    	}&#x000A;    &#x000A;    	function read() {&#x000A;    		return $this-&gt;book-&gt;read();&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class PDFBook implements EBook{&#x000A;    &#x000A;    	function read() {&#x000A;    		return "reading a pdf book.";&#x000A;    	}&#x000A;    }</pre>
    <p>The most common, and most frequently used solution to invert the dependency is to introduce a more abstract module in our design. "The most abstract element in OOP is an Interface. Thus, any other class can depend on an Interface and still respect DIP".</p>
    <p>We created an interface <em>for our reader</em>. The interface is called <code>EBook</code> and represents the needs of the <code>EBookReader</code>. This is a direct result of respecting the <a href="http://dev.tutsplus.com/tutorials/solid-part-3-liskov-substitution-interface-segregation-principles--net-36710" rel="nofollow external" class="bo">Interface Segregation Principle (ISP)</a> which promotes the idea that interfaces should reflect the needs of the clients. Interfaces belong to the clients, and thus they are named to reflect the types and objects the clients need and they will contain methods the clients wants to use. It is only natural for an <code>EBookReader</code> to use <code>EBooks</code> and have a <code>read()</code> method.</p>
    
    <img src="https://cdn.tutsplus.com/net/uploads/2014/02/ebookreader-ebookinterface-pdfbook.png" alt="ebookreader-ebookinterface-pdfbook" width="600" height="246" style="max-width: 100%; height: auto;"><br>
    
    <p>Instead of a single dependency, we have two dependencies now.</p>
    <ul>
    <li>The first dependency points from <code>EBookReader</code> toward the <code>EBook</code> interface and it is of type usage. <code>EBookReader</code> uses <code>EBooks</code>.</li>
    <li>The second dependency is different. It points from <code>PDFBook</code> toward the same <code>EBook</code> interface but it is of type implementation. A <code>PDFBook</code> is just a particular form of <code>EBook</code>, and thus implements that interface to satisfy the client's needs.</li>
    </ul>
    <p>Unsurprisingly, this solution also allows us to plug in different types of ebooks into our reader. The single condition for all these books is to satisfy the <code>EBook</code> interface and implement it.</p>
    <pre>class Test extends PHPUnit_Framework_TestCase {&#x000A;    &#x000A;    	function testItCanReadAPDFBook() {&#x000A;    		$b = new PDFBook();&#x000A;    		$r = new EBookReader($b);&#x000A;    &#x000A;    		$this-&gt;assertRegExp('/pdf book/', $r-&gt;read());&#x000A;    	}&#x000A;    &#x000A;    	function testItCanReadAMobiBook() {&#x000A;    		$b = new MobiBook();&#x000A;    		$r = new EBookReader($b);&#x000A;    &#x000A;    		$this-&gt;assertRegExp('/mobi book/', $r-&gt;read());&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    interface EBook {&#x000A;    	function read();&#x000A;    }&#x000A;    &#x000A;    class EBookReader {&#x000A;    &#x000A;    	private $book;&#x000A;    &#x000A;    	function __construct(EBook $book) {&#x000A;    		$this-&gt;book = $book;&#x000A;    	}&#x000A;    &#x000A;    	function read() {&#x000A;    		return $this-&gt;book-&gt;read();&#x000A;    	}&#x000A;    &#x000A;    }&#x000A;    &#x000A;    class PDFBook implements EBook {&#x000A;    &#x000A;    	function read() {&#x000A;    		return "reading a pdf book.";&#x000A;    	}&#x000A;    }&#x000A;    &#x000A;    class MobiBook implements EBook {&#x000A;    &#x000A;    	function read() {&#x000A;    		return "reading a mobi book.";&#x000A;    	}&#x000A;    }</pre>
    <p>Which in turn leads us to <a href="http://dev.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle--net-36600" rel="nofollow external" class="bo">The Open/Closed Principle</a>, and the circle is closed.</p>
    <p>The Dependency Inversion Principle is one that leads or helps us respect all the other principles. Respecting DIP will:</p>
    <ul>
    <li>Almost force you into respecting OCP.</li>
    <li>Allow you to separate responsibilities.</li>
    <li>Make you correctly use subtyping.</li>
    <li>Offer you the opportunity to segregate your interfaces.</li>
    </ul>
    <hr>
    <h2>Final Thoughts</h2>
    <p>That's it. We are done. All tutorials about the SOLID principles are complete. For me, personally, discovering these principles and implementing projects with them in mind was a huge change. I completely changed the way I think about design and architecture and I can say since then all the projects I work on are exponentially easier to manage and understand.</p>
    <p>I consider the SOLID principles one of the most essential concepts of object-oriented design. These concepts that must guide us in making our code better and our life as programmers much much easier. Well-designed code is easier for programmers to understand. Computers are smart, they can understand code regardless of its complexity. Human beings on the other hand have a limited number of things they can keep in their active, focused mind. More specifically, the number of such things is <a href="http://www.musanim.com/miller1956/" rel="nofollow external" class="bo">The Magical Number Seven, Plus or Minus Two</a>.</p>
    <p>We should strive to have our code structured around these numbers and there are several techniques that help us do so. Functions with a maximum of four lines in length (five with the definition line included) so that they can all fit at once within our mind. Indentations not passing five levels deep. Classes with no more than nine methods. Design patterns that usually use a number of five to nine classes. Our high level design in the schemas above uses four to five concepts. There are five SOLID principles, each requiring five to nine sub-concepts/modules/classes to be exemplified. The ideal size of a programming team is between five and nine. The ideal number of teams in a company is between five and nine.</p>
    <p>As you can see, the magical number seven, plus or minus two is all around us, so why should your code be different?</p>
    </div>
]]>
</Body>
<Summary>The Single Responsibility (SRP), Open/Closed (OCP), Liskov Substitution, Interface Segregation, and Dependency Inversion. Five agile principles that should guide you every time you write code....</Summary>
<Website>http://code.tutsplus.com/tutorials/solid-part-4-the-dependency-inversion-principle--net-36872</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41325/guest@my.umbc.edu/8d81c9bf480dfdf547384499c60628c6/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>wed</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>Thu, 13 Feb 2014 09:00:17 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 09:00:17 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41323" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41323">
<Title>DealBook: In Matter of Weeks, Meeting of Minds on Cable Giants&#8217; Deal</Title>
<Body>
<![CDATA[
    <div class="html-content">Comcast was not intensely engaged with Time Warner Cable until about 10 days or so prior to the announcement of the $45 billion acquisition, according to Comcast’s chief.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F02%2F13%2Ftime-warner-cable-and-comcast-strike-45-2-billion-deal%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+In+Matter+of+Weeks%2C+Meeting+of+Minds+on+Cable+Giants%E2%80%99+Deal" 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%2F2014%2F02%2F13%2Ftime-warner-cable-and-comcast-strike-45-2-billion-deal%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+In+Matter+of+Weeks%2C+Meeting+of+Minds+on+Cable+Giants%E2%80%99+Deal" 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%2F2014%2F02%2F13%2Ftime-warner-cable-and-comcast-strike-45-2-billion-deal%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+In+Matter+of+Weeks%2C+Meeting+of+Minds+on+Cable+Giants%E2%80%99+Deal" 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%2F2014%2F02%2F13%2Ftime-warner-cable-and-comcast-strike-45-2-billion-deal%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+In+Matter+of+Weeks%2C+Meeting+of+Minds+on+Cable+Giants%E2%80%99+Deal" 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%2F2014%2F02%2F13%2Ftime-warner-cable-and-comcast-strike-45-2-billion-deal%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+In+Matter+of+Weeks%2C+Meeting+of+Minds+on+Cable+Giants%E2%80%99+Deal" 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/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/sc/2/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478454/u/0/f/640387/c/34625/s/370ecb04/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Comcast was not intensely engaged with Time Warner Cable until about 10 days or so prior to the announcement of the $45 billion acquisition, according to Comcast’s chief.      </Summary>
<Website>http://dealbook.nytimes.com/2014/02/13/time-warner-cable-and-comcast-strike-45-2-billion-deal/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41323/guest@my.umbc.edu/e8efdb8d06133bebed8cd142015eee40/api/pixel</TrackingUrl>
<Tag>comcast-corporation</Tag>
<Tag>comcast-corporation-cmcsa-nasdaq</Tag>
<Tag>mergers-acquisitions-and-divestitures</Tag>
<Tag>mergers-and-acquisitions</Tag>
<Tag>new</Tag>
<Tag>technology</Tag>
<Tag>telecommunications</Tag>
<Tag>time-warner-cable-inc</Tag>
<Tag>time-warner-cable-inc-twc-nyse</Tag>
<Tag>top-headline-1</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>Thu, 13 Feb 2014 07:57:02 -0500</PostedAt>
<EditAt>Fri, 14 Feb 2014 06:12:47 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41324" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41324">
<Title>Bits Blog: The Number Cisco Left Out</Title>
<Body>
<![CDATA[
    <div class="html-content">Cisco just reported a tough quarter, the latest sign of an incumbent struggling to adapt to a world of cloud computing, mobility, sensors and lots of cheap competition.<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%2Fthe-number-cisco-left-out%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+The+Number+Cisco+Left+Out" 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%2Fthe-number-cisco-left-out%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+The+Number+Cisco+Left+Out" 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%2Fthe-number-cisco-left-out%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+The+Number+Cisco+Left+Out" 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%2Fthe-number-cisco-left-out%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+The+Number+Cisco+Left+Out" 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%2Fthe-number-cisco-left-out%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+The+Number+Cisco+Left+Out" 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/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/sc/15/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530478263/u/0/f/640387/c/34625/s/370ec95f/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Cisco just reported a tough quarter, the latest sign of an incumbent struggling to adapt to a world of cloud computing, mobility, sensors and lots of cheap competition.      </Summary>
<Website>http://bits.blogs.nytimes.com/2014/02/12/the-number-cisco-left-out/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41324/guest@my.umbc.edu/a0a67844229f888fe80e15364e570679/api/pixel</TrackingUrl>
<Tag>chambers-john-t</Tag>
<Tag>cisco-systems-inc</Tag>
<Tag>cisco-systems-inc-csco-nasdaq</Tag>
<Tag>cloud-computing</Tag>
<Tag>enterprise-computing</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>Thu, 13 Feb 2014 07:27:14 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 13:07:36 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="41322" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41322">
<Title>The Shadowy World of Wikipedia's Editing Bots</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Much of the editing work on Wikipedia is too mind-numbingly repetitive for humans, so automated bots do it instead. But keeping track of automated editing has always been hard … until now.</p>
    <p><br>In a little over a decade, Wikipedia has evolved from an Internet experiment into a global crowdsourcing phenomenon. Today, this online encyclopedia provides free access to more than 30 million articles in 287 languages.</p>
    </div>
]]>
</Body>
<Summary>Much of the editing work on Wikipedia is too mind-numbingly repetitive for humans, so automated bots do it instead. But keeping track of automated editing has always been hard … until now.   In a...</Summary>
<Website>http://www.technologyreview.com/view/524751/the-shadowy-world-of-wikipedias-editing-bots/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41322/guest@my.umbc.edu/50dcfef0f30810c2ed6d8a280fb3cb3b/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>Thu, 13 Feb 2014 06:30:53 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 06:30:53 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="41320" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41320">
<Title>Daytime Columbia location classes are cancelled today due to inclement weather....</Title>
<Body>
<![CDATA[
    <div class="html-content">Daytime Columbia location classes are cancelled today due to inclement weather. Please call our main line with any questions.</div>
]]>
</Body>
<Summary>Daytime Columbia location classes are cancelled today due to inclement weather. Please call our main line with any questions.</Summary>
<Website>http://www.facebook.com/umbctraining/posts/10151856741781076</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41320/guest@my.umbc.edu/934b5f2e02a2db62f07c5404ab3e5968/api/pixel</TrackingUrl>
<Tag>ccna</Tag>
<Tag>ceh</Tag>
<Tag>centers</Tag>
<Tag>cisco</Tag>
<Tag>cyber</Tag>
<Tag>cybersecurity</Tag>
<Tag>information</Tag>
<Tag>it</Tag>
<Tag>leadership</Tag>
<Tag>management</Tag>
<Tag>microsoft</Tag>
<Tag>project</Tag>
<Tag>security</Tag>
<Tag>technology</Tag>
<Tag>training</Tag>
<Tag>umbc</Tag>
<Group token="retired-575">UMBC Training Centers</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-575</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/xsmall.png?1361981335</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/original.jpg?1361981335</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/xxlarge.png?1361981335</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/xlarge.png?1361981335</AvatarUrl>
<AvatarUrl size="large">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/large.png?1361981335</AvatarUrl>
<AvatarUrl size="medium">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/medium.png?1361981335</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/small.png?1361981335</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/xsmall.png?1361981335</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/575/83756b985266168d0d29c6c9a146db50/xxsmall.png?1361981335</AvatarUrl>
<Sponsor>UMBC Training Centers</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Thu, 13 Feb 2014 06:13:15 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 06:13:15 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41321" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41321">
<Title>Creating A Client-Side Shopping Cart</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>Session storage is a new feature introduced by the W3C’s “<a href="http://www.w3.org/TR/webstorage/" rel="nofollow external" class="bo">Web Storage</a>” specification. It’s supported in Internet Explorer 8+, Firefox, Chrome, Safari and Opera Desktop (for a complete list, please consult “<a href="http://caniuse.com/#feat=namevalue-storage" rel="nofollow external" class="bo">Can I Use</a>”). In this series of articles, we’ll cover in depth a practical implementation of session storage by creating a complete e-commerce shopping cart with the <code>sessionStorage</code> object and jQuery.</p>
    <p>Bear in mind that, in these articles, I’m not going to propose a new technique to replace existing server-side techniques, but rather just a proof of concept of session storage.</p>
    <h3>Session Storage: A Quick Reminder</h3>
    <p>We use sessions to store data and share such data across several pages. Usually, a user would pick a product, and we’d save the product’s name along with the chosen quantity and price.</p>
    <p>Then, the user would fill out a form with their personal information, and we’d save it in the current session before the end of the process, which is typically the checkout page and the subsequent redirection to the payment gateway (for example, PayPal).</p>
    <p><strong>How are shopping carts built?</strong> PHP, for instance, makes frequent use of associative arrays to create the basic structure of a shopping cart. Associative arrays enable PHP Web developers to keep session data structured and organized.</p>
    <p>JavaScript sessions work differently. Generally, a session expires when the user closes their browser (but bear in mind that the concept of “closing a browser” is not clear on mobile devices). When a session expires, all data stored in the session storage of a Web browser is removed. There’s no need to explicitly initialize a session because in JavaScript a session takes the form of the global <code>sessionStorage</code> object and is always present. It’s up to us to write data into the current session.</p>
    <p>Session data comes in the form of key-value pairs, and the value of each key may contain only strings. To write data, we can use the <code>sessionStorage.setItem( name, value )</code> method:</p>
    <pre><code>&#x000A;    sessionStorage.setItem( "total", 120 );&#x000A;    </code></pre>
    <p>In this case, the key named <code>total</code> now contains the value <code>120</code> as a string, although we’ve used an integer in our call to the <code>.setItem()</code> method. This value will be available until the session expires, unless we use <code>sessionStorage.removeItem( "total" )</code> to remove the named key or we call <code>sessionStorage.clear()</code> to entirely remove all keys and values from the session storage.</p>
    <p><strong>Note</strong> that when a key doesn’t exist in session storage, its value is always <code>null</code>. Then, when we remove a key from session storage and try again to get its value, we’d simply get <code>null</code>.</p>
    <p>As you may have guessed, our key now is always available, even as the user navigates the pages of our website. To get its value, we simply write the following:</p>
    <pre><code>&#x000A;    var total = sessionStorage.getItem( "total" );&#x000A;    console.log( total ); // '120', a string&#x000A;    </code></pre>
    <p>We can also update its value by using <code>sessionStorage.setItem()</code> again with a new value:</p>
    <pre><code>&#x000A;    var total = parseInt( sessionStorage.getItem( "total" ) );&#x000A;    var quantity = 2;&#x000A;    var updatedTotal = total * quantity;&#x000A;    sessionStorage.setItem( "total", updatedTotal ); // '240', a string&#x000A;    </code></pre>
    <p>Now, the key named <code>total</code> has a value of <code>240</code> with our last update. Why did we call <code>parseInt()</code>? This is a simple technique to convert a numerical string into a true number, ensuring that our calculation will be consistent. Remember that all values in session storage are strings, and our calculations must be between only numbers.</p>
    <p><strong>But wait! What about objects?</strong> Objects may be stored in session storage by first turning them into JSON strings (with <code>JSON.stringify()</code>) and then back into JavaScript objects (with <code>JSON.parse()</code>):</p>
    <pre><code>&#x000A;    var cart = {&#x000A;    	item: "Product 1",&#x000A;    	price: 35.50,&#x000A;    	qty: 2&#x000A;    };&#x000A;    var jsonStr = JSON.stringify( cart );&#x000A;    sessionStorage.setItem( "cart", jsonStr );&#x000A;    // now the cart is {"item":"Product 1","price":35.50,"qty":2}&#x000A;    var cartValue = sessionStorage.getItem( "cart" );&#x000A;    var cartObj = JSON.parse( cartValue );&#x000A;    // original object&#x000A;    </code></pre>
    <p>To update our object, we simply extend it and then repeat the procedure above.</p>
    <h3>Security Considerations</h3>
    <p>Security is important. If we read the <a href="http://www.w3.org/TR/webstorage/#security-storage" rel="nofollow external" class="bo">security notes</a> of the W3C’s specification, then we’d be aware of the security risks of even a client-side technology such as Web storage.</p>
    <p>The US Computer Emergency Readiness Team’s <a href="http://www.us-cert.gov/sites/default/files/publications/TIP-12-298-01-Website-Security.pdf" rel="nofollow external" class="bo">technical paper on website security</a> (PDF) clearly states:</p>
    <blockquote>
    <p>“Every community organization, corporation, business, or government agency relies on an outward-facing website to provide information about themselves, announce an event, or sell a product or service. Consequently, public-facing websites are often the most targeted attack vectors for malicious activity.”</p>
    </blockquote>
    <p>Even if a browser session ends when the browser itself is closed, malicious attacks can still take place, especially if the browser has been compromised by certain exploits. Moreover, compromised websites can often be used to spread malware that targets particular browsers.</p>
    <p>For this reason, <strong>make sure your website is safe</strong> before relying on any technique to store data in the browser. Keeping a website safe is beyond the scope of this article, but by simply following security best practices, you should be able to benefit from Web storage without worrying too much about its security implications.</p>
    <h3>Our Sample Project: Winery</h3>
    <p>Our sample project is an online store that sells wine. It’s a simple e-commerce website whose only complication is in how its shipping charges are calculated.</p>
    <p>In short, wines are sold in packages of six bottles. This means that the total quantity of bottles sold must always be in multiples of six. Shipping charges are calculated, then, according to the total quantity of bottles sold.</p>
    <p>Our store will rely on PayPal, so we’ll have to create a Business account in <a href="https://www.sandbox.paypal.com/" rel="nofollow external" class="bo">PayPal Sandbox</a> to test our code.</p>
    <p>The user may add and remove products from their shopping cart, update the cart, change the quantity of each product, and empty the cart. They have to fill a form with their contact information, specifying whether their billing address is the same as their shipping address.</p>
    <p>Before being redirected to PayPal, the user will see a summary page with their personal data, their cart, and the cart’s total price plus shipping charges.</p>
    <p>After completing their purchase, the user should be redirected back to our website. This is <strong>the only step of the process that we can’t handle only with JavaScript</strong>. PayPal will send back various data over an HTTP request that has to be processed with a server-side language (such as PHP). If you need more information to get started with this kind of processing, please consult <a href="https://developer.paypal.com/docs/classic/ipn/gs_IPN/" rel="nofollow external" class="bo">PayPal’s tutorial</a>.</p>
    <h3>HTML Structure</h3>
    <p>Our project is made up of the following sections:</p>
    <ul>
    <li>
    <code>index.html</code><br>
    This contains the list from which users may add products to their shopping cart, specifying the quantity for each product.</li>
    <li>
    <code>cart.html</code><br>
    This is the shopping cart page where users may update or empty their cart. Alternatively, they can go back to the main page to continue shopping or proceed to the checkout page.</li>
    <li>
    <code>checkout.html</code><br>
    On this page, users fill out a form with their personal information — specifically, their billing and shipping addresses.</li>
    <li>
    <code>order.html</code><br>
    This page contains a brief summary of the user’s order plus the PayPal form. Once a user submits the form, they will be redirected to PayPal’s landing page.</li>
    </ul>
    <p>We’ll go over the markup for this project in the following sections.</p>
    <h4>index.html</h4>
    <p>The main components of this page are the forms that enable the user to add products to their shopping cart.</p>
    <pre><code>&#x000A;    &lt;div class="product-description" data-name="Wine #1" data-price="5"&gt;&#x000A;    	&lt;h3 class="product-name"&gt;Wine #1&lt;/h3&gt;&#x000A;    		&lt;p class="product-price"&gt;&amp;euro; 5&lt;/p&gt;&#x000A;    		&lt;form class="add-to-cart" action="cart.html" method="post"&gt;&#x000A;    			&lt;div&gt;&#x000A;    				&lt;label for="qty-1"&gt;Quantity&lt;/label&gt;&#x000A;    				&lt;input type="text" name="qty-1" id="qty-1" class="qty" value="1" /&gt;&#x000A;    			&lt;/div&gt;&#x000A;    			&lt;p&gt;&lt;input type="submit" value="Add to cart" class="btn" /&gt;&lt;/p&gt;&#x000A;    		&lt;/form&gt;&#x000A;    &lt;/div&gt;&#x000A;    </code></pre>
    <p>The data attributes used here for storing product names and prices can be accessed via jQuery using the <a href="http://api.jquery.com/data/" rel="nofollow external" class="bo">.data()</a> and <a href="http://api.jquery.com/jquery.data/" rel="nofollow external" class="bo">$.data()</a> methods.</p>
    <h4>cart.html</h4>
    <p>Our shopping cart page is made up of three components: a table with the product’s information, an element that displays the subtotal, and a list<br>
    of cart actions.</p>
    <pre><code>&#x000A;    &lt;form id="shopping-cart" action="cart.html" method="post"&gt;&#x000A;    	&lt;table class="shopping-cart"&gt;&#x000A;    		&lt;thead&gt;&#x000A;    			&lt;tr&gt;&#x000A;    				&lt;th scope="col"&gt;Item&lt;/th&gt;&#x000A;    				&lt;th scope="col"&gt;Qty&lt;/th&gt;&#x000A;    				&lt;th scope="col"&gt;Price&lt;/th&gt;&#x000A;    			&lt;/tr&gt;&#x000A;    		&lt;/thead&gt;&#x000A;    		&lt;tbody&gt;&lt;/tbody&gt;&#x000A;    	&lt;/table&gt;&#x000A;    	&lt;p id="sub-total"&gt;&#x000A;    		&lt;strong&gt;Sub Total&lt;/strong&gt;: &lt;span id="stotal"&gt;&lt;/span&gt;&#x000A;    	&lt;/p&gt;&#x000A;    	&lt;ul id="shopping-cart-actions"&gt;&#x000A;    		&lt;li&gt;&#x000A;    			&lt;input type="submit" name="update" id="update-cart" class="btn" value="Update Cart" /&gt;&#x000A;    		&lt;/li&gt;&#x000A;    		&lt;li&gt;&#x000A;    			&lt;input type="submit" name="delete" id="empty-cart" class="btn" value="Empty Cart" /&gt;&#x000A;    		&lt;/li&gt;&#x000A;    		&lt;li&gt;&#x000A;    			&lt;a href="index.html" class="btn"&gt;Continue Shopping&lt;/a&gt;&#x000A;    		&lt;/li&gt;&#x000A;    		&lt;li&gt;&#x000A;    			&lt;a href="checkout.html" class="btn"&gt;Go To Checkout&lt;/a&gt;&#x000A;    		&lt;/li&gt;&#x000A;    	&lt;/ul&gt;&#x000A;    &lt;/form&gt;&#x000A;    </code></pre>
    <p>The table contained in this page is empty, and we’ll fill it with data via JavaScript. The element that displays the subtotal works just as a placeholder for JavaScript. The first two actions, “Update Cart” and “Empty Cart,” will be handled by JavaScript, while the latter two actions are just plain links to the product’s list page and the checkout page, respectively.</p>
    <h4>checkout.html</h4>
    <p>This page has four components:
    </p>
    <ul>
    <li>a table that shows the ordered items (the same table shown earlier in the shopping cart section), plus the final price and shipping charges;</li>
    <li>a form in which the user must fill in their billing details;</li>
    <li>a form with shipping information;</li>
    <li>a checkbox to enable the user to specify that their billing details are the same as their shipping details.</li>
    </ul>
    <pre><code>&#x000A;    &lt;table id="checkout-cart" class="shopping-cart"&gt;&#x000A;    	&lt;thead&gt;&#x000A;    		&lt;tr&gt;&#x000A;    			&lt;th scope="col"&gt;Item&lt;/th&gt;&#x000A;    			&lt;th scope="col"&gt;Qty&lt;/th&gt;&#x000A;    			&lt;th scope="col"&gt;Price&lt;/th&gt;&#x000A;    		&lt;/tr&gt;&#x000A;    	&lt;/thead&gt;&#x000A;    	&lt;tbody&gt;&#x000A;    &#x000A;    	&lt;/tbody&gt;&#x000A;    &lt;/table&gt;&#x000A;    &#x000A;    &lt;div id="pricing"&gt;&#x000A;    	&lt;p id="shipping"&gt;&#x000A;    		&lt;strong&gt;Shipping&lt;/strong&gt;: &lt;span id="sshipping"&gt;&lt;/span&gt;&#x000A;    	&lt;/p&gt;&#x000A;    			&#x000A;    	&lt;p id="sub-total"&gt;&#x000A;    		&lt;strong&gt;Total&lt;/strong&gt;: &lt;span id="stotal"&gt;&lt;/span&gt;&#x000A;    	&lt;/p&gt;&#x000A;    &lt;/div&gt;&#x000A;    		 &#x000A;    &lt;form action="order.html" method="post" id="checkout-order-form"&gt;&#x000A;    	&lt;h2&gt;Your Details&lt;/h2&gt;&#x000A;    		&lt;fieldset id="fieldset-billing"&gt;&#x000A;    			&lt;legend&gt;Billing&lt;/legend&gt;&#x000A;    				&lt;!-- Name, Email, City, Address, ZIP Code, Country (select box) --&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="name"&gt;Name&lt;/label&gt;&#x000A;    	&lt;input type="text" name="name" id="name" data-type="string" data-message="This field may not be empty" /&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="email"&gt;Email&lt;/label&gt;&#x000A;    	&lt;input type="text" name="email" id="email" data-type="expression" data-message="Not a valid email address" /&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="city"&gt;City&lt;/label&gt;&#x000A;    	&lt;input type="text" name="city" id="city" data-type="string" data-message="This field may not be empty" /&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="address"&gt;Address&lt;/label&gt;&#x000A;    		&lt;input type="text" name="address" id="address" data-type="string" data-message="This field may not be empty" /&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="zip"&gt;ZIP Code&lt;/label&gt;&#x000A;    	&lt;input type="text" name="zip" id="zip" data-type="string" data-message="This field may not be empty" /&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div&gt;&#x000A;    	&lt;label for="country"&gt;Country&lt;/label&gt;&#x000A;    		&lt;select name="country" id="country" data-type="string" data-message="This field may not be empty"&gt;&#x000A;    			&lt;option value=""&gt;Select&lt;/option&gt;&#x000A;    			&lt;option value="US"&gt;USA&lt;/option&gt;&#x000A;    			&lt;option value="IT"&gt;Italy&lt;/option&gt;&#x000A;    		&lt;/select&gt;&#x000A;    &lt;/div&gt;&#x000A;    &lt;/fieldset&gt;&#x000A;    &#x000A;    &lt;div id="shipping-same"&gt;Same as Billing &lt;input type="checkbox" id="same-as-billing" value=""/&gt;&lt;/div&gt;&#x000A;    &#x000A;    &lt;fieldset id="fieldset-shipping"&gt;&#x000A;    &lt;legend&gt;Shipping&lt;/legend&gt;&#x000A;    	&lt;!-- Same fields as billing --&gt;&#x000A;    &lt;/fieldset&gt;&#x000A;    &#x000A;    &lt;p&gt;&lt;input type="submit" id="submit-order" value="Submit" class="btn" /&gt;&lt;/p&gt;&#x000A;    &#x000A;    &lt;/form&gt;&#x000A;    </code></pre>
    <p>Data attributes are used here for validation. The <code>data-type</code> attribute specifies the type of data we’re validating, and <code>data-message</code> contains the error message to be shown in case of failure.</p>
    <p>I didn’t use the email validation built into Web browsers just for the sake of simplicity, but you could use it if you want.</p>
    <h4>order.html</h4>
    <p>This final page contains a brief recap of the user’s order, their details and the PayPal form.</p>
    <pre><code>&#x000A;    &lt;h1&gt;Your Order&lt;/h1&gt;&#x000A;    &#x000A;    &lt;table id="checkout-cart" class="shopping-cart"&gt;&#x000A;    	&lt;thead&gt;&#x000A;    		&lt;tr&gt;&#x000A;    			&lt;th scope="col"&gt;Item&lt;/th&gt;&#x000A;    			&lt;th scope="col"&gt;Qty&lt;/th&gt;&#x000A;    			&lt;th scope="col"&gt;Price&lt;/th&gt;&#x000A;    		&lt;/tr&gt;&#x000A;    	&lt;/thead&gt;&#x000A;    	&lt;tbody&gt;&#x000A;    	&lt;/tbody&gt;&#x000A;    &lt;/table&gt;&#x000A;    &#x000A;    &lt;div id="pricing"&gt;&#x000A;    	&lt;p id="shipping"&gt;&#x000A;    		&lt;strong&gt;Shipping&lt;/strong&gt;: &lt;span id="sshipping"&gt;&lt;/span&gt;&#x000A;    	&lt;/p&gt;&#x000A;    &#x000A;    	&lt;p id="sub-total"&gt;&#x000A;    		&lt;strong&gt;Total&lt;/strong&gt;: &lt;span id="stotal"&gt;&lt;/span&gt;&#x000A;    	&lt;/p&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    &lt;div id="user-details"&gt;&#x000A;    	&lt;h2&gt;Your Data&lt;/h2&gt;&#x000A;    		&lt;div id="user-details-content"&gt;&lt;/div&gt;&#x000A;    &lt;/div&gt;&#x000A;    &#x000A;    		 &#x000A;    &lt;form id="paypal-form" action="" method="post"&gt;&#x000A;    	&lt;input type="hidden" name="cmd" value="_cart" /&gt;&#x000A;    	&lt;input type="hidden" name="upload" value="1" /&gt;&#x000A;    	&lt;input type="hidden" name="business" value="" /&gt;&#x000A;    &#x000A;    	&lt;input type="hidden" name="currency_code" value="" /&gt;&#x000A;    	&lt;input type="submit" id="paypal-btn" class="btn" value="Pay with PayPal" /&gt;&#x000A;    &lt;/form&gt;&#x000A;    </code></pre>
    <p>The PayPal form and other elements of this page are initially empty, except for those fields that don’t need to be generated dynamically.</p>
    <h3>JavaScript Code</h3>
    <p>The CSS layout of this project will have no actual influence on the goal we want to achieve. Even if we disabled CSS entirely, the project would continue to function, thanks to the strong relationship between the HTML’s structure and the JavaScript’s behavior.</p>
    <p>We’ll use an <strong>object-oriented approach</strong> because of the complexity of our goals. Our object will be based on a simple constructional pattern and will use both private and public methods.</p>
    <h4>Object Structure</h4>
    <p>Our object has a very simple structure. The constructor function both initializes the top-level element that wraps our DOM’s entire structure and invokes the initialization method.</p>
    <pre><code>&#x000A;    (function( $ ) {&#x000A;    	$.Shop = function( element ) {&#x000A;    		this.$element = $( element ); // top-level element&#x000A;    		this.init();&#x000A;    	};&#x000A;    &#x000A;    	$.Shop.prototype = {&#x000A;    		init: function() {&#x000A;    			// initializes properties and methods&#x000A;    		}&#x000A;    	};&#x000A;    &#x000A;    	$(function() {&#x000A;    		var shop = new $.Shop( "#site" ); // object's instance&#x000A;    	});&#x000A;    &#x000A;    })( jQuery );&#x000A;    </code></pre>
    <p>The object’s instance is created when the DOM is ready. We can test that everything has worked fine as follows:</p>
    <pre><code>&#x000A;    $(function() {&#x000A;    	var shop = new $.Shop( "#site" );&#x000A;    	console.log( shop.$element );&#x000A;    });&#x000A;    </code></pre>
    <p>This outputs the following:</p>
    <pre><code>&#x000A;    x.fn.x.init[1]&#x000A;    	0: div#site&#x000A;    	context: document&#x000A;    	length: 1&#x000A;    	selector: "#site"&#x000A;    </code></pre>
    <p>Now that we know our object has been instantiated correctly, we can define its properties.</p>
    <h4>Object Properties</h4>
    <p>The properties of our object break down into two categories: first, the properties for handling calculations, forms and validation, and secondly, the references to HTML elements.</p>
    <pre><code>&#x000A;    $.Shop.prototype = {&#x000A;    	init: function() {&#x000A;    		// Properties&#x000A;    &#x000A;    			this.cartPrefix = "winery-"; // prefix string to be prepended to the cart's name in session storage&#x000A;    			this.cartName = this.cartPrefix + "cart"; // cart's name in session storage&#x000A;    			this.shippingRates = this.cartPrefix + "shipping-rates"; // shipping rates key in session storage&#x000A;    			this.total = this.cartPrefix + "total"; // total key in the session storage&#x000A;    			this.storage = sessionStorage; // shortcut to sessionStorage object&#x000A;    &#x000A;    &#x000A;    			this.$formAddToCart = this.$element.find( "form.add-to-cart" ); // forms for adding items to the cart&#x000A;    			this.$formCart = this.$element.find( "#shopping-cart" ); // Shopping cart form&#x000A;    			this.$checkoutCart = this.$element.find( "#checkout-cart" ); // checkout form cart&#x000A;    			this.$checkoutOrderForm = this.$element.find( "#checkout-order-form" ); // checkout user details form&#x000A;    			this.$shipping = this.$element.find( "#sshipping" ); // element that displays the shipping rates&#x000A;    			this.$subTotal = this.$element.find( "#stotal" ); // element that displays the subtotal charges&#x000A;    			this.$shoppingCartActions = this.$element.find( "#shopping-cart-actions" ); // cart actions links&#x000A;    			this.$updateCartBtn = this.$shoppingCartActions.find( "#update-cart" ); // update cart button&#x000A;    			this.$emptyCartBtn = this.$shoppingCartActions.find( "#empty-cart" ); // empty cart button&#x000A;    			this.$userDetails = this.$element.find( "#user-details-content" ); // element that displays the user's information&#x000A;    			this.$paypalForm = this.$element.find( "#paypal-form" ); // PayPal form&#x000A;    &#x000A;    &#x000A;    			this.currency = "&amp;euro;"; // HTML entity of the currency to be displayed in layout&#x000A;    			this.currencyString = "€"; // currency symbol as text string&#x000A;    			this.paypalCurrency = "EUR"; // PayPal's currency code&#x000A;    			this.paypalBusinessEmail = "<a href="mailto:yourbusiness@email.com">yourbusiness@email.com</a>"; // your PayPal Business account email address&#x000A;    			this.paypalURL = "<a href="https://www.sandbox.paypal.com/cgi-bin/webscr">https://www.sandbox.paypal.com/cgi-bin/webscr</a>"; // URL of the PayPal form&#x000A;    &#x000A;    			// object containing patterns for form validation&#x000A;    			this.requiredFields = {&#x000A;    				expression: {&#x000A;    					value: /^([\w-\.]+)@((?:[\w]+\.)+)([a-z]){2,4}$/&#x000A;    				},&#x000A;    &#x000A;    				str: {&#x000A;    					value: ""&#x000A;    				}&#x000A;    &#x000A;    			};&#x000A;    &#x000A;    			// public methods invocation&#x000A;    	}&#x000A;    };&#x000A;    </code></pre>
    <p>Let’s go over these properties one by one.</p>
    <p><strong>Storage and other properties:</strong></p>
    <ul>
    <li>
    <code>cartPrefix</code><br>
    A prefix to be prepended to the cart’s name key in session storage</li>
    <li>
    <code>cartName</code><br>
    The cart’s name key in session storage (combines the <code>cartPrefix</code> string with the <code>cart</code> string)</li>
    <li>
    <code>shippingRates</code><br>
    The shipping rate key in session storage</li>
    <li>
    <code>total</code><br>
    The total’s key in session storage</li>
    <li>
    <code>storage</code><br>
    Shortcut to the <code>sessionStorage</code> object.</li>
    <li>
    <code>currency</code><br>
    An HTML entity used to display the current currency in the layout</li>
    <li>
    <code>currencyString</code><br>
    The current currency symbol used in the element’s text</li>
    <li>
    <code>paypalCurrency</code><br>
    PayPal’s currency text code</li>
    <li>
    <code>paypalBusinessEmail</code><br>
    The email address of your PayPal Business account</li>
    <li>
    <code>paypalURL</code><br>
    The URL of PayPal’s form (defaults to the URL of PayPal Sandbox)</li>
    <li>
    <code>requiredFields</code><br>
    An object containing the patterns and rules for form validation</li>
    </ul>
    <p><strong>References to elements:</strong></p>
    <ul>
    <li>
    <code>$formAddToCart</code><br>
    The forms for adding products to the shopping cart</li>
    <li>
    <code>$formCart</code><br>
    The shopping cart form</li>
    <li>
    <code>$checkoutCart</code><br>
    The checkout’s shopping cart form</li>
    <li>
    <code>$checkoutOrderForm</code><br>
    The checkout’s form where users input their personal information</li>
    <li>
    <code>$shipping</code><br>
    The element that contains and displays shipping rates</li>
    <li>
    <code>$subTotal</code><br>
    The element that contains and displays the total charges</li>
    <li>
    <code>$shoppingCartActions</code><br>
    The elements that contain the actions related to the shopping cart</li>
    <li>
    <code>$updateCartBtn</code><br>
    The button to update the shopping cart</li>
    <li>
    <code>$emptyCartBtn</code><br>
    The button for emptying the cart</li>
    <li>
    <code>$userDetails</code><br>
    The element that contains and displays the information entered by the user</li>
    <li>
    <code>$paypalForm</code><br>
    PayPal’s form</li>
    </ul>
    <p>All of the elements are prefixed with the <code>$</code> sign, meaning that they’re jQuery objects. But <strong>not all of these elements are available on all pages</strong>. To check whether a jQuery element exists, simply test its <code>length</code> property:</p>
    <pre><code>&#x000A;    if( $element.length ) {&#x000A;    	// the element exists&#x000A;    }&#x000A;    </code></pre>
    <p>Another approach, not used in our project, is to add a particular ID or class to the <code>body</code> element and perform actions conditionally:</p>
    <pre><code>&#x000A;    var $body = $( "body" ),&#x000A;    	page = $body.attr( "id" );&#x000A;    &#x000A;    	switch( page ) {&#x000A;    		case "product-list":&#x000A;    			// actions for handling products&#x000A;    			break;&#x000A;    		case "shopping-cart":&#x000A;    			// actions for handling the shopping cart&#x000A;    			break;&#x000A;    		case "checkout":&#x000A;    			// actions for handling the checkout's page&#x000A;    			break;&#x000A;    		default:&#x000A;    			break;&#x000A;    	}&#x000A;    </code></pre>
    <h4>Object Methods</h4>
    <p>The actions of our code take place in our object’s methods, which, in turn, can be divided into public and private methods. Private methods operate in the background, so to speak, and help the public methods perform their tasks. These methods are prefixed with an underscore and are never used directly.</p>
    <p>Public methods, meanwhile, operate directly on page elements and data, and they’re unprefixed. We’ve already seen the <code>init()</code> method, which simply initializes properties and other public methods in the object’s constructor function. The other methods will be explained below.</p>
    <h4>Private Methods (Helpers)</h4>
    <p>The first private method, <code>_emptyCart()</code>, simply empties the current session storage in the browser:</p>
    <pre><code>&#x000A;    $.Shop.prototype = {&#x000A;    	// empties session storage&#x000A;    &#x000A;    	_emptyCart: function() {&#x000A;    		this.storage.clear();&#x000A;    	}&#x000A;    };&#x000A;    </code></pre>
    <p>To format a number by a set number of decimal places, we implement the <code>_formatNumber()</code> method:</p>
    <pre><code>&#x000A;    /* Format a number by decimal places&#x000A;     * @param num Number the number to be formatted&#x000A;     * @param places Number the decimal places&#x000A;     * @returns n Number the formatted number&#x000A;    */&#x000A;    &#x000A;    &#x000A;    _formatNumber: function( num, places ) {&#x000A;    	var n = num.toFixed( places );&#x000A;    	return n;&#x000A;    }&#x000A;    </code></pre>
    <p>This method makes use of JavaScript’s <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed" rel="nofollow external" class="bo">toFixed()</a> method of the <code>Number</code> object. Its role in our project is to properly format prices.</p>
    <p>Because <strong>not all of the prices in our pages are contained in data attributes</strong>, we need a specialized method to extract the numeric portion of a string from text nodes. This method is named <code>_extractPrice()</code>:</p>
    <pre><code>&#x000A;    /* Extract the numeric portion from a string&#x000A;     * @param element Object the jQuery element that contains the relevant string&#x000A;     * @returns price String the numeric string&#x000A;     */&#x000A;    &#x000A;    &#x000A;    _extractPrice: function( element ) {&#x000A;    	var self = this;&#x000A;    	var text = element.text();&#x000A;    	var price = text.replace( self.currencyString, "" ).replace( " ", "" );&#x000A;    	return price;&#x000A;    }&#x000A;    </code></pre>
    <p>Above, <code>self</code> is a reference to the <code>$.Shop</code> object, and we’ll need it every time we want to access a property or a method of our object without worrying much about scope.</p>
    <p>You can bulletproof this method by adding a further routine that strips out all trailing white space:</p>
    <pre><code>&#x000A;    var text = $.trim( element.text() );&#x000A;    </code></pre>
    <p>Bear in mind that jQuery’s <a href="https://api.jquery.com/jQuery.trim/" rel="nofollow external" class="bo">$.trim()</a> method removes all new lines, spaces (including non-breaking spaces) and tabs from the beginning and end of a string. If these white space characters occur in the middle of a string, they are preserved.</p>
    <p>Then, <strong>we need two methods to convert strings into numbers and numbers into strings</strong>. This is necessary to perform calculations and to display the results on our pages.</p>
    <pre><code>&#x000A;    /* Converts a numeric string into a number&#x000A;     * @param numStr String the numeric string to be converted&#x000A;     * @returns num Number the number, or false if the string cannot be converted&#x000A;     */&#x000A;    &#x000A;    _convertString: function( numStr ) {&#x000A;    	var num;&#x000A;    	if( /^[-+]?[0-9]+\.[0-9]+$/.test( numStr ) ) {&#x000A;    		num = parseFloat( numStr );&#x000A;    	} else if( /^\d+$/.test( numStr ) ) {&#x000A;    		num = parseInt( numStr );&#x000A;    	} else {&#x000A;    		num = Number( numStr );&#x000A;    	}&#x000A;    &#x000A;    	if( !isNaN( num ) ) {&#x000A;    		return num;&#x000A;    	} else {&#x000A;    		console.warn( numStr + " cannot be converted into a number" );&#x000A;    		return false;&#x000A;    	}&#x000A;    },&#x000A;    &#x000A;    /* Converts a number to a string&#x000A;     * @param n Number the number to be converted&#x000A;     * @returns str String the string returned&#x000A;     */&#x000A;    &#x000A;    _convertNumber: function( n ) {&#x000A;    	var str = n.toString();&#x000A;    	return str;&#x000A;    }&#x000A;    </code></pre>
    <p>Above, <code>_convertString()</code> runs the following tests:</p>
    <ol>
    <li>Does the string have a decimal format? If so, it uses the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat" rel="nofollow external" class="bo">parseFloat()</a> function.</li>
    <li>Does the string have an integer format? If so, it uses the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt" rel="nofollow external" class="bo">parseInt()</a> function.</li>
    <li>If the format of the string cannot be detected, it uses the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number" rel="nofollow external" class="bo">Number()</a> constructor.</li>
    <li>If the result is a number (tested with the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN" rel="nofollow external" class="bo">isNaN()</a> function), it returns the number. Otherwise, it outputs a warning to the JavaScript console and returns <code>false</code>.</li>
    </ol>
    <p>By contrast, <code>_convertNumber()</code> simply invokes the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString" rel="nofollow external" class="bo">toString()</a> method to convert a number into a string.</p>
    <p>The next step is to define two methods to <strong>convert a JavaScript object into a JSON string</strong> and a JSON string back into a JavaScript object:</p>
    <pre><code>&#x000A;    /* Converts a JSON string to a JavaScript object&#x000A;     * @param str String the JSON string&#x000A;     * @returns obj Object the JavaScript object&#x000A;     */&#x000A;    &#x000A;    _toJSONObject: function( str ) {&#x000A;    	var obj = JSON.parse( str );&#x000A;    	return obj;&#x000A;    },&#x000A;    &#x000A;    /* Converts a JavaScript object to a JSON string&#x000A;     * @param obj Object the JavaScript object&#x000A;     * @returns str String the JSON string&#x000A;     */&#x000A;    &#x000A;    &#x000A;    _toJSONString: function( obj ) {&#x000A;    	var str = JSON.stringify( obj );&#x000A;    	return str;&#x000A;    }&#x000A;    </code></pre>
    <p>The first method makes use of the <code>JSON.parse()</code> method, while the latter invokes the <code>JSON.stringify()</code> method (see Mozilla Developer Network’s article on “<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON" rel="nofollow external" class="bo">Using Native JSON</a>”).</p>
    <p>Why do we need these methods? Because our cart will also store the information related to each product using the following data format (spaces added for legibility):</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td><code>{ "items": [ { "product": "Wine #1", "qty": 5, "price": 5 } ] }</code></td>
    </tr>
    </tbody>
    </table>
    <p>The <code>winery-cart</code> key contains a JSON string that represents an array of objects (i.e. <code>items</code>) in which each object shows the relevant information about a product added by the user — namely, the product’s name, the quantity and the price.</p>
    <p>It’s pretty obvious that we also now need a specialized method to add items to this particular key in session storage:</p>
    <pre><code>&#x000A;    /* Add an object to the cart as a JSON string&#x000A;     * @param values Object the object to be added to the cart&#x000A;     * @returns void&#x000A;     */&#x000A;    &#x000A;    &#x000A;    _addToCart: function( values ) {&#x000A;    	var cart = this.storage.getItem( this.cartName );&#x000A;    	var cartObject = this._toJSONObject( cart );&#x000A;    	var cartCopy = cartObject;&#x000A;    	var items = cartCopy.items;&#x000A;    	items.push( values );&#x000A;    &#x000A;    	this.storage.setItem( this.cartName, this._toJSONString( cartCopy ) );&#x000A;    }&#x000A;    </code></pre>
    <p>This method gets the cart’s key from session storage, converts it to a JavaScript object and adds a new object as a JSON string to the cart’s array. The newly added object has the following format:</p>
    <pre><code>&#x000A;    this._addToCart({&#x000A;    	product: "Test",&#x000A;    	qty: 1,&#x000A;    	price: 2&#x000A;    });&#x000A;    </code></pre>
    <p>Now, our cart key will look like this:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td><code>{ "items": [ { "product": "Wine #1", "qty": 5, "price": 5 }, { "product": "Test", "qty": 1, "price": 2 } ] }</code></td>
    </tr>
    </tbody>
    </table>
    <p>Shipping is calculated according to the overall number of products added to the cart, not the quantity of each individual product:</p>
    <pre><code>&#x000A;    /* Custom shipping rates calculated based on total quantity of items in cart&#x000A;     * @param qty Number the total quantity of items&#x000A;     * @returns shipping Number the shipping rates&#x000A;     */&#x000A;    &#x000A;    _calculateShipping: function( qty ) {&#x000A;    	var shipping = 0;&#x000A;    	if( qty &gt;= 6 ) {&#x000A;    		shipping = 10;&#x000A;    	}&#x000A;    	if( qty &gt;= 12 &amp;&amp; qty &lt;= 30 ) {&#x000A;    		shipping = 20;	&#x000A;    	}&#x000A;    &#x000A;    	if( qty &gt;= 30 &amp;&amp; qty &lt;= 60 ) {&#x000A;    		shipping = 30;	&#x000A;    	}&#x000A;    &#x000A;    	if( qty &gt; 60 ) {&#x000A;    		shipping = 0;&#x000A;    	}&#x000A;    &#x000A;    	return shipping;&#x000A;    &#x000A;    }&#x000A;    </code></pre>
    <p>You can replace this method’s routines with your own. In this case, shipping charges are calculated based on specific amounts.</p>
    <p><strong>We also need to validate the checkout form</strong> where users insert their personal information. The following method takes into account the special visibility toggle by which the user may specify that their billing information is the same as their shipping information.</p>
    <pre><code>&#x000A;    /* Validates the checkout form&#x000A;     * @param form Object the jQuery element of the checkout form&#x000A;     * @returns valid Boolean true for success, false for failure&#x000A;     */&#x000A;    &#x000A;    &#x000A;    _validateForm: function( form ) {&#x000A;    		var self = this;&#x000A;    		var fields = self.requiredFields;&#x000A;    		var $visibleSet = form.find( "fieldset:visible" );&#x000A;    		var valid = true;&#x000A;    &#x000A;    		form.find( ".message" ).remove();&#x000A;    			&#x000A;    	$visibleSet.each(function() {&#x000A;    &#x000A;    		$( this ).find( ":input" ).each(function() {&#x000A;    		var $input = $( this );&#x000A;    		var type = $input.data( "type" );&#x000A;    		var msg = $input.data( "message" );&#x000A;    				&#x000A;    		if( type == "string" ) {&#x000A;    			if( $input.val() == fields.str.value ) {&#x000A;    				$( "&lt;span class='message'/&gt;" ).text( msg ).&#x000A;    				insertBefore( $input );&#x000A;    &#x000A;    				valid = false;&#x000A;    			}&#x000A;    		} else {&#x000A;    			if( !fields.expression.value.test( $input.val() ) ) {&#x000A;    				$( "&lt;span class='message'/&gt;" ).text( msg ).&#x000A;    				insertBefore( $input );&#x000A;    &#x000A;    				valid = false;&#x000A;    			}&#x000A;    		}&#x000A;    &#x000A;    	});&#x000A;    	});&#x000A;    &#x000A;    	return valid;&#x000A;    }&#x000A;    </code></pre>
    <p>When validation messages are added upon the form being submitted, we need to clear these messages before going any further. In this case, we take into account only the fields contained in a <code>fieldset</code> element that is still visible after the user has checked the visibility toggle.</p>
    <p>Validation takes place by checking whether the current field requires a simple string comparison (<code>data-type="string"</code>) or a regular expression test (<code>data-type="expression"</code>). Our tests are based on the <code>requiredFields</code> property. If there’s an error, we’ll show a message by using the <code>data-message</code> attribute of each field.</p>
    <p>Note that the validation routines used above have been inserted just for demonstration purposes, and they have several flaws. For better validation, I recommend a dedicated jQuery plugin, such as <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" rel="nofollow external" class="bo">jQuery Validation</a>.</p>
    <p>Last but not least is <strong>registering the information that the user has entered</strong> in the checkout form:</p>
    <pre><code>&#x000A;    /* Save the data entered by the user in the checkout form&#x000A;     * @param form Object the jQuery element of the checkout form&#x000A;     * @returns void&#x000A;     */&#x000A;    &#x000A;    &#x000A;    _saveFormData: function( form ) {&#x000A;    	var self = this;&#x000A;    	var $visibleSet = form.find( "fieldset:visible" );&#x000A;    			&#x000A;    	$visibleSet.each(function() {&#x000A;    		var $set = $( this );&#x000A;    		if( $set.is( "#fieldset-billing" ) ) {&#x000A;    			var name = $( "#name", $set ).val();&#x000A;    			var email = $( "#email", $set ).val();&#x000A;    			var city = $( "#city", $set ).val();&#x000A;    			var address = $( "#address", $set ).val();&#x000A;    			var zip = $( "#zip", $set ).val();&#x000A;    			var country = $( "#country", $set ).val();&#x000A;    &#x000A;    			self.storage.setItem( "billing-name", name );&#x000A;    			self.storage.setItem( "billing-email", email );&#x000A;    			self.storage.setItem( "billing-city", city );&#x000A;    			self.storage.setItem( "billing-address", address );&#x000A;    			self.storage.setItem( "billing-zip", zip );&#x000A;    			self.storage.setItem( "billing-country", country );&#x000A;    		} else {&#x000A;    			var sName = $( "#sname", $set ).val();&#x000A;    			var sEmail = $( "#semail", $set ).val();&#x000A;    			var sCity = $( "#scity", $set ).val();&#x000A;    			var sAddress = $( "#saddress", $set ).val();&#x000A;    			var sZip = $( "#szip", $set ).val();&#x000A;    			var sCountry = $( "#scountry", $set ).val();&#x000A;    &#x000A;    			self.storage.setItem( "shipping-name", sName );&#x000A;    			self.storage.setItem( "shipping-email", sEmail );&#x000A;    			self.storage.setItem( "shipping-city", sCity );&#x000A;    			self.storage.setItem( "shipping-address", sAddress );&#x000A;    			self.storage.setItem( "shipping-zip", sZip );&#x000A;    			self.storage.setItem( "shipping-country", sCountry );&#x000A;    &#x000A;    		}&#x000A;    	});&#x000A;    }&#x000A;    </code></pre>
    <p>Again, this method takes into account the visibility of the fields based on the user’s choice. Once the form has been submitted, our session storage may have the following details added to it:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>billing-name</code></td>
    <td>John Doe</td>
    </tr>
    <tr>
    <td><code>billing-email</code></td>
    <td>jdoe@localhost</td>
    </tr>
    <tr>
    <td><code>billing-city</code></td>
    <td>New York</td>
    </tr>
    <tr>
    <td><code>billing-address</code></td>
    <td>Street 1</td>
    </tr>
    <tr>
    <td><code>billing-zip</code></td>
    <td>1234</td>
    </tr>
    <tr>
    <td><code>billing-country</code></td>
    <td>USA</td>
    </tr>
    </tbody>
    </table>
    <h4>Public Methods</h4>
    <p>Our public methods are invoked in the initialization method (<code>init()</code>). The first thing to do is create the initial keys and values in session storage.</p>
    <pre><code>&#x000A;    // Creates the cart keys in session storage&#x000A;    &#x000A;    createCart: function() {&#x000A;    	if( this.storage.getItem( this.cartName ) == null ) {&#x000A;    &#x000A;    		var cart = {};&#x000A;    		cart.items = [];&#x000A;    			&#x000A;    		this.storage.setItem( this.cartName, this._toJSONString( cart ) );&#x000A;    		this.storage.setItem( this.shippingRates, "0" );&#x000A;    		this.storage.setItem( this.total, "0" );&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>The first check tests whether our values have already been added to session storage. We need this test because we could actually overwrite our values if we run this method every time a document has finished loading.</p>
    <p>Now, our session storage looks like this:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>0</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>0</td>
    </tr>
    </tbody>
    </table>
    <p>Now, we need to <strong>handle the forms where the user may add products</strong> to their shopping cart:</p>
    <pre><code>&#x000A;    // Adds items to shopping cart&#x000A;    &#x000A;    handleAddToCartForm: function() {&#x000A;    	var self = this;&#x000A;    	self.$formAddToCart.each(function() {&#x000A;    		var $form = $( this );&#x000A;    		var $product = $form.parent();&#x000A;    		var price = self._convertString( $product.data( "price" ) );&#x000A;    		var name =  $product.data( "name" );&#x000A;    &#x000A;    		$form.on( "submit", function() {&#x000A;    			var qty = self._convertString( $form.find( ".qty" ).val() );&#x000A;    			var subTotal = qty * price;&#x000A;    			var total = self._convertString( self.storage.getItem( self.total ) );&#x000A;    			var sTotal = total + subTotal;&#x000A;    			self.storage.setItem( self.total, sTotal );&#x000A;    			self._addToCart({&#x000A;    				product: name,&#x000A;    				price: price,&#x000A;    				qty: qty&#x000A;    			});&#x000A;    			var shipping = self._convertString( self.storage.getItem( self.shippingRates ) );&#x000A;    			var shippingRates = self._calculateShipping( qty );&#x000A;    			var totalShipping = shipping + shippingRates;&#x000A;    &#x000A;    			self.storage.setItem( self.shippingRates, totalShipping );&#x000A;    		});&#x000A;    	});&#x000A;    }&#x000A;    </code></pre>
    <p>Every time a user submits one of these forms, we have to read the product quantity specified by the user and multiply it by the unit price. Then, we need to read the total’s key contained in session storage and update its value accordingly. Having done this, we call the <code>_addToCart()</code> method to store the product’s details in storage. The quantity specified will also be used to <strong>calculate the shipping rate</strong> by comparing its value to the value already stored.</p>
    <p>Suppose that a user chooses the first product, Wine #1, whose price is €5.00, and specifies a quantity of 5. The session storage would look like this once the form has been submitted:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[{"product":"Wine #1","price":5,"qty":5}]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>0</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>25</td>
    </tr>
    </tbody>
    </table>
    <p>Suppose the same user goes back to the product list and chooses Wine #2, whose price is €8.00, and specifies a quantity of 2:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[{"product":"Wine #1","price":5,"qty":5},{"product":"Wine #2","price":8,"qty":2}]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>0</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>41</td>
    </tr>
    </tbody>
    </table>
    <p>Finally, our eager user returns again to the product list, chooses Wine #3, whose price is €11.00, and specifies a quantity of 6:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[{"product":"Wine #1","price":5,"qty":5},{"product":"Wine #2","price":8,"qty":2},{"product":"Wine #3","price":11,"qty":6}]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>10</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>107</td>
    </tr>
    </tbody>
    </table>
    <p>At this point, we need to <strong>accurately display the cart</strong> when the user goes to the shopping cart page or checkout page:</p>
    <pre><code>&#x000A;    // Displays the shopping cart&#x000A;    &#x000A;    displayCart: function() {&#x000A;    	if( this.$formCart.length ) {&#x000A;    		var cart = this._toJSONObject( this.storage.getItem( this.cartName ) );&#x000A;    		var items = cart.items;&#x000A;    		var $tableCart = this.$formCart.find( ".shopping-cart" );&#x000A;    		var $tableCartBody = $tableCart.find( "tbody" );&#x000A;    &#x000A;    &#x000A;    		for( var i = 0; i &lt; items.length; ++i ) {&#x000A;    			var item = items[i];&#x000A;    			var product = item.product;&#x000A;    			var price = this.currency + " " + item.price;&#x000A;    			var qty = item.qty;&#x000A;    			var html = "&lt;tr&gt;&lt;td class='pname'&gt;" + product + "&lt;/td&gt;" + "&lt;td class='pqty'&gt;&lt;input type='text' value='" + qty + "' class='qty'/&gt;&lt;/td&gt;" + "&lt;td class='pprice'&gt;" + price + "&lt;/td&gt;&lt;/tr&gt;";&#x000A;    &#x000A;    			$tableCartBody.html( $tableCartBody.html() + html );&#x000A;    		}&#x000A;    &#x000A;    		var total = this.storage.getItem( this.total );&#x000A;    		this.$subTotal[0].innerHTML = this.currency + " " + total;&#x000A;    	} else if( this.$checkoutCart.length ) {&#x000A;    		var checkoutCart = this._toJSONObject( this.storage.getItem( this.cartName ) );&#x000A;    		var cartItems = checkoutCart.items;&#x000A;    		var $cartBody = this.$checkoutCart.find( "tbody" );&#x000A;    &#x000A;    		for( var j = 0; j &lt; cartItems.length; ++j ) {&#x000A;    			var cartItem = cartItems[j];&#x000A;    			var cartProduct = cartItem.product;&#x000A;    			var cartPrice = this.currency + " " + cartItem.price;&#x000A;    			var cartQty = cartItem.qty;&#x000A;    			var cartHTML = "&lt;tr&gt;&lt;td class='pname'&gt;" + cartProduct + "&lt;/td&gt;" + "&lt;td class='pqty'&gt;" + cartQty + "&lt;/td&gt;" + "&lt;td class='pprice'&gt;" + cartPrice + "&lt;/td&gt;&lt;/tr&gt;";&#x000A;    &#x000A;    			$cartBody.html( $cartBody.html() + cartHTML );&#x000A;    		}&#x000A;    &#x000A;    		var cartTotal = this.storage.getItem( this.total );&#x000A;    		var cartShipping = this.storage.getItem( this.shippingRates );&#x000A;    		var subTot = this._convertString( cartTotal ) + this._convertString( cartShipping );&#x000A;    &#x000A;    		this.$subTotal[0].innerHTML = this.currency + " " + this._convertNumber( subTot );&#x000A;    		this.$shipping[0].innerHTML = this.currency + " " + cartShipping;&#x000A;    			&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>If the cart’s table is on the shopping cart page, then this method iterates over the array of objects contained in the <code>winery-cart</code> key and populates the table by adding a text field to allow users to modify the quantity of each product. For the sake of simplicity, I didn’t include an action to remove an item from the cart, but that procedure is pretty simple:</p>
    <ol>
    <li>Get the <code>items</code> array, contained in session storage.</li>
    <li>Get the product’s name, contained in the <code>td</code> element with the <code>pname</code> class.</li>
    <li>Create a new array by filtering out the item with the product’s name, obtained in step 2 (you can use <a href="https://api.jquery.com/jQuery.grep/" rel="nofollow external" class="bo">$.grep()</a>).</li>
    <li>Save the new array in the <code>winery-cart</code> key.</li>
    <li>Update the total and shipping charge values.</li>
    </ol>
    <pre><code>&#x000A;    var items = [&#x000A;    	{&#x000A;    		product: "Test",&#x000A;    		qty: 1,&#x000A;    		price: 5&#x000A;    	},&#x000A;    	{&#x000A;    		product: "Foo",&#x000A;    		qty: 5,&#x000A;    		price: 10&#x000A;    	},&#x000A;    	{&#x000A;    		product: "Bar",&#x000A;    		qty: 2,&#x000A;    		price: 8&#x000A;    	}&#x000A;    ];&#x000A;    &#x000A;    &#x000A;    items = $.grep( items, function( item ) {&#x000A;    	return item.product !== "Test";&#x000A;    &#x000A;    });&#x000A;    &#x000A;    console.log( items ); &#x000A;    &#x000A;    /*&#x000A;    	Array[2]&#x000A;    		0: Object&#x000A;    			price: 10&#x000A;    			product: "Foo"&#x000A;    			qty: 5&#x000A;    		1: Object&#x000A;    			price: 8&#x000A;    			product: "Bar"&#x000A;    			qty: 2&#x000A;    */&#x000A;    </code></pre>
    <p>Then, we need a method that updates the cart with a new quantity value for each product:</p>
    <pre><code>&#x000A;    // Updates the cart&#x000A;    &#x000A;    updateCart: function() {&#x000A;    		var self = this;&#x000A;    	if( self.$updateCartBtn.length ) {&#x000A;    		self.$updateCartBtn.on( "click", function() {&#x000A;    			var $rows = self.$formCart.find( "tbody tr" );&#x000A;    			var cart = self.storage.getItem( self.cartName );&#x000A;    			var shippingRates = self.storage.getItem( self.shippingRates );&#x000A;    			var total = self.storage.getItem( self.total );&#x000A;    &#x000A;    			var updatedTotal = 0;&#x000A;    			var totalQty = 0;&#x000A;    			var updatedCart = {};&#x000A;    			updatedCart.items = [];&#x000A;    &#x000A;    			$rows.each(function() {&#x000A;    				var $row = $( this );&#x000A;    				var pname = $.trim( $row.find( ".pname" ).text() );&#x000A;    				var pqty = self._convertString( $row.find( ".pqty &gt; .qty" ).val() );&#x000A;    				var pprice = self._convertString( self._extractPrice( $row.find( ".pprice" ) ) );&#x000A;    &#x000A;    				var cartObj = {&#x000A;    					product: pname,&#x000A;    					price: pprice,&#x000A;    					qty: pqty&#x000A;    				};&#x000A;    &#x000A;    				updatedCart.items.push( cartObj );&#x000A;    &#x000A;    				var subTotal = pqty * pprice;&#x000A;    				updatedTotal += subTotal;&#x000A;    				totalQty += pqty;&#x000A;    			});&#x000A;    				&#x000A;    			self.storage.setItem( self.total, self._convertNumber( updatedTotal ) );&#x000A;    			self.storage.setItem( self.shippingRates, self._convertNumber( self._calculateShipping( totalQty ) ) );&#x000A;    			self.storage.setItem( self.cartName, self._toJSONString( updatedCart ) );&#x000A;    &#x000A;    		});&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>Our method loops through all of the relevant table cells of the cart and builds a new object to be inserted in the <code>winery-cart</code> key. It also recalculates the total price and shipping charge by taking into account the newly inserted values of the quantity fields.</p>
    <p>Suppose that a user changes the quantity of Wine #2 from 2 to 6:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[{"product":"Wine #1","price":5,"qty":5},{"product":"Wine #2","price":8,"qty":6},{"product":"Wine #3","price":11,"qty":6}]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>20</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>139</td>
    </tr>
    </tbody>
    </table>
    <p>If the user wants to empty their cart and start over, we simply have to add the following action:</p>
    <pre><code>&#x000A;    // Empties the cart by calling the _emptyCart() method&#x000A;    // @see $.Shop._emptyCart()&#x000A;    &#x000A;    emptyCart: function() {&#x000A;    	var self = this;&#x000A;    	if( self.$emptyCartBtn.length ) {&#x000A;    		self.$emptyCartBtn.on( "click", function() {&#x000A;    			self._emptyCart();&#x000A;    		});&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>Now, session storage has been emptied entirely, and <strong>the user may start making purchases again</strong>. However, if they decide to finalize their order instead, then we need to handle the checkout form when they insert their personal information.</p>
    <pre><code>&#x000A;    // Handles the checkout form by adding a validation routine and saving user’s info in session storage&#x000A;    &#x000A;    handleCheckoutOrderForm: function() {&#x000A;    	var self = this;&#x000A;    	if( self.$checkoutOrderForm.length ) {&#x000A;    		var $sameAsBilling = $( "#same-as-billing" );&#x000A;    		$sameAsBilling.on( "change", function() {&#x000A;    			var $check = $( this );&#x000A;    			if( $check.prop( "checked" ) ) {&#x000A;    				$( "#fieldset-shipping" ).slideUp( "normal" );&#x000A;    			} else {&#x000A;    				$( "#fieldset-shipping" ).slideDown( "normal" );&#x000A;    			}&#x000A;    		});&#x000A;    &#x000A;    		self.$checkoutOrderForm.on( "submit", function() {&#x000A;    			var $form = $( this );&#x000A;    			var valid = self._validateForm( $form );&#x000A;    	&#x000A;    			if( !valid ) {&#x000A;    				return valid;&#x000A;    			} else {&#x000A;    				self._saveFormData( $form );&#x000A;    			}&#x000A;    		});&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>The first thing we need to do is <strong>hide the shipping fields</strong> if the user checks the toggle that specifies that their billing information is the same as their shipping information. We use the <code>change</code> event, combined with jQuery’s <a href="http://api.jquery.com/prop/" rel="nofollow external" class="bo">.prop()</a> method. (If you’re curious about the difference between <code>.prop()</code> and <code>.attr()</code>, <a href="http://stackoverflow.com/questions/5874652/prop-vs-attr" rel="nofollow external" class="bo">StackOverflow has a good discussion</a> of it.)</p>
    <p>Then, we validate the form by returning a <code>false</code> value in case of errors, thus preventing the form from being submitted. If validation succeeds, we save the user’s data in storage. For example:</p>
    <table>
    <tbody>
    <tr>
    <td><strong>Key</strong></td>
    <td><strong>Value</strong></td>
    </tr>
    <tr>
    <td><code>winery-cart</code></td>
    <td>{“items”:[{"product":"Wine #1","price":5,"qty":5},{"product":"Wine #2","price":8,"qty":6},{"product":"Wine #3","price":11,"qty":6}]}</td>
    </tr>
    <tr>
    <td><code>winery-shipping-rates</code></td>
    <td>20</td>
    </tr>
    <tr>
    <td><code>winery-total</code></td>
    <td>139</td>
    </tr>
    <tr>
    <td><code>billing-name</code></td>
    <td>John Doe</td>
    </tr>
    <tr>
    <td><code>billing-email</code></td>
    <td>jdoe@localhost</td>
    </tr>
    <tr>
    <td><code>billing-city</code></td>
    <td>New York</td>
    </tr>
    <tr>
    <td><code>billing-address</code></td>
    <td>Street 1</td>
    </tr>
    <tr>
    <td><code>billing-zip</code></td>
    <td>1234</td>
    </tr>
    <tr>
    <td><code>billing-country</code></td>
    <td>USA</td>
    </tr>
    </tbody>
    </table>
    <p><strong>The final step is the page with the PayPal form.</strong> First, we need to display the user’s information gathered on the checkout page:</p>
    <pre><code>&#x000A;    // Displays the user's information&#x000A;    &#x000A;    displayUserDetails: function() {&#x000A;    	if( this.$userDetails.length ) {&#x000A;    		if( this.storage.getItem( "shipping-name" ) == null ) {&#x000A;    			var name = this.storage.getItem( "billing-name" );&#x000A;    			var email = this.storage.getItem( "billing-email" );&#x000A;    			var city = this.storage.getItem( "billing-city" );&#x000A;    			var address = this.storage.getItem( "billing-address" );&#x000A;    			var zip = this.storage.getItem( "billing-zip" );&#x000A;    			var country = this.storage.getItem( "billing-country" );&#x000A;    &#x000A;    			var html = "&lt;div class='detail'&gt;";&#x000A;    				html += "&lt;h2&gt;Billing and Shipping&lt;/h2&gt;";&#x000A;    				html += "&lt;ul&gt;";&#x000A;    				html += "&lt;li&gt;" + name + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + email + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + city + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + address + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + zip + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + country + "&lt;/li&gt;";&#x000A;    				html += "&lt;/ul&gt;&lt;/div&gt;";&#x000A;    &#x000A;    			this.$userDetails[0].innerHTML = html;&#x000A;    		} else {&#x000A;    			var name = this.storage.getItem( "billing-name" );&#x000A;    			var email = this.storage.getItem( "billing-email" );&#x000A;    			var city = this.storage.getItem( "billing-city" );&#x000A;    			var address = this.storage.getItem( "billing-address" );&#x000A;    			var zip = this.storage.getItem( "billing-zip" );&#x000A;    			var country = this.storage.getItem( "billing-country" );&#x000A;    &#x000A;    			var sName = this.storage.getItem( "shipping-name" );&#x000A;    			var sEmail = this.storage.getItem( "shipping-email" );&#x000A;    			var sCity = this.storage.getItem( "shipping-city" );&#x000A;    			var sAddress = this.storage.getItem( "shipping-address" );&#x000A;    			var sZip = this.storage.getItem( "shipping-zip" );&#x000A;    			var sCountry = this.storage.getItem( "shipping-country" );&#x000A;    &#x000A;    			var html = "&lt;div class='detail'&gt;";&#x000A;    				html += "&lt;h2&gt;Billing&lt;/h2&gt;";&#x000A;    				html += "&lt;ul&gt;";&#x000A;    				html += "&lt;li&gt;" + name + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + email + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + city + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + address + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + zip + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + country + "&lt;/li&gt;";&#x000A;    				html += "&lt;/ul&gt;&lt;/div&gt;";&#x000A;    &#x000A;    				html += "&lt;div class='detail right'&gt;";&#x000A;    				html += "&lt;h2&gt;Shipping&lt;/h2&gt;";&#x000A;    				html += "&lt;ul&gt;";&#x000A;    				html += "&lt;li&gt;" + sName + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + sEmail + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + sCity + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + sAddress + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + sZip + "&lt;/li&gt;";&#x000A;    				html += "&lt;li&gt;" + sCountry + "&lt;/li&gt;";&#x000A;    				html += "&lt;/ul&gt;&lt;/div&gt;";&#x000A;    &#x000A;    			this.$userDetails[0].innerHTML = html;	&#x000A;    &#x000A;    		}&#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>Our method first <strong>checks whether the user has inputted either billing or shipping information or both</strong>. Then, it simply builds an HTML fragment by getting the user’s data from session storage.</p>
    <p>Finally, the user may buy the products by submitting the PayPal form. The form redirects them to PayPal, but the fields need to be filled in properly before the form can be submitted.</p>
    <pre><code>&#x000A;    // Appends the required hidden values to PayPal's form before submitting&#x000A;    &#x000A;    populatePayPalForm: function() {&#x000A;    	var self = this;&#x000A;    	if( self.$paypalForm.length ) {&#x000A;    		var $form = self.$paypalForm;&#x000A;    		var cart = self._toJSONObject( self.storage.getItem( self.cartName ) );&#x000A;    		var shipping = self.storage.getItem( self.shippingRates );&#x000A;    		var numShipping = self._convertString( shipping );&#x000A;    		var cartItems = cart.items; &#x000A;    		var singShipping = Math.floor( numShipping / cartItems.length );&#x000A;    &#x000A;    		$form.attr( "action", self.paypalURL );&#x000A;    		$form.find( "input[name='business']" ).val( self.paypalBusinessEmail );&#x000A;    		$form.find( "input[name='currency_code']" ).val( self.paypalCurrency );&#x000A;    &#x000A;    		for( var i = 0; i &lt; cartItems.length; ++i ) {&#x000A;    			var cartItem = cartItems[i];&#x000A;    			var n = i + 1;&#x000A;    			var name = cartItem.product;&#x000A;    			var price = cartItem.price;&#x000A;    			var qty = cartItem.qty;&#x000A;    &#x000A;    			$( "&lt;div/&gt;" ).html( "&lt;input type='hidden' name='quantity_" + n + "' value='" + qty + "'/&gt;" ).&#x000A;    			insertBefore( "#paypal-btn" );&#x000A;    			$( "&lt;div/&gt;" ).html( "&lt;input type='hidden' name='item_name_" + n + "' value='" + name + "'/&gt;" ).&#x000A;    			insertBefore( "#paypal-btn" );&#x000A;    			$( "&lt;div/&gt;" ).html( "&lt;input type='hidden' name='item_number_" + n + "' value='SKU " + name + "'/&gt;" ).&#x000A;    			insertBefore( "#paypal-btn" );&#x000A;    			$( "&lt;div/&gt;" ).html( "&lt;input type='hidden' name='amount_" + n + "' value='" + self._formatNumber( price, 2 ) + "'/&gt;" ).&#x000A;    			insertBefore( "#paypal-btn" );&#x000A;    			$( "&lt;div/&gt;" ).html( "&lt;input type='hidden' name='shipping_" + n + "' value='" + self._formatNumber( singShipping, 2 ) + "'/&gt;" ).&#x000A;    			insertBefore( "#paypal-btn" );&#x000A;    &#x000A;    		}&#x000A;    &#x000A;    &#x000A;    &#x000A;    	}&#x000A;    }&#x000A;    </code></pre>
    <p>First, we get some important information from session storage — namely, the shipping rate and the total number of items in the cart. We divide the total shipping amount by the number of items to get the shipping rate for each item.</p>
    <p>Then, we set the URL for the <code>action</code> attribute of the form, together with our business email and currency code (taken from the <code>paypalBusinessEmail</code> and <code>paypalCurrency</code> properties, respectively).</p>
    <p>Finally, we loop through the items of our cart, and we append to the form several hidden input elements containing the quantities, the names of the products, the number of items for each product, the prices (amounts), and the unit shipping rates.</p>
    <p>The monetary values are formatted as <code>00,00</code>. Explaining all of the possible values of a PayPal form and the various types of PayPal forms goes well beyond the scope of this article, If you want to go deeper, I recommend the following reading:</p>
    <ul>
    <li>“<a href="https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/formbasics/" rel="nofollow external" class="bo">HTML Form Basics for PayPal Payments Standard</a>,” PayPal Developer</li>
    <li>“<a href="https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/" rel="nofollow external" class="bo">HTML Variables for PayPal Payments Standard</a>,” PayPal Developer</li>
    </ul>
    <h3>Preview And Source Code</h3>
    <p>The following video shows the result. I’ve omitted PayPal’s landing page to protect my account’s data, but you can <a href="https://raw2.github.com/gabrieleromanato/jQuery-sessionStorage-shopping-cart/master/images/paypal-shopping-cart.jpg" rel="nofollow external" class="bo">see it as a screenshot</a>.</p>
    <p></p>
    <div class="embed-container"><iframe src="http://player.vimeo.com/video/81308642?title=0&amp;amp;byline=0&amp;amp;portrait=0" frameborder="0" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowFullScreen">[Video]</iframe></div>
    <p>Get the code from the <a href="https://github.com/gabrieleromanato/jQuery-sessionStorage-shopping-cart" rel="nofollow external" class="bo">GitHub repository</a>. Just change the <code>paypalBusinessEmail</code> property of the <code>$.Shop</code> object to your PayPal Sandbox email account.</p>
    <h4>Other Resources</h4>
    <ul>
    <li>“<a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage" rel="nofollow external" class="bo">DOM Storage Guide</a>,” Mozilla Developer Network</li>
    <li>“<a href="http://www.nczonline.net/blog/2009/07/21/introduction-to-sessionstorage/" rel="nofollow external" class="bo">Introduction to Session Storage</a>,” Nicholas C. Zakas</li>
    <li>“<a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes" rel="nofollow external" class="bo">Using data-* Attributes</a>,” Mozilla Developer Network</li>
    </ul>
    <p><em>(al, ea)</em></p>
    <hr>
    <p><small>© Gabriele Romanato for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2014.</small></p>
    </div>
]]>
</Body>
<Summary>        Session storage is a new feature introduced by the W3C’s “Web Storage” specification. It’s supported in Internet Explorer 8+, Firefox, Chrome, Safari and Opera Desktop (for a complete...</Summary>
<Website>http://www.smashingmagazine.com/2014/02/13/creating-a-client-side-shopping-cart/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41321/guest@my.umbc.edu/7e24f70bd56a2a5d37c00e7c530bb618/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>Thu, 13 Feb 2014 06:12:56 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="41318" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41318">
<Title>35+ inspiring quotes for designers</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><img alt="thumbnail" src="http://netdna.webdesignerdepot.com/uploads/2014/02/thumbnail12.jpg" width="200" height="160" style="max-width: 100%; height: auto;">When it’s going well, design is a pleasure. But we all know what it’s like to experience a bad day: nothing works the way it should, colors clash, type mumbles, the message is lost altogether.</p> <p>It’s worth remembering that everyone has their bad days. Here are some of the most inspirational quotes we’ve found online to help you through the rough patch and come out smiling on the other side.</p> <p>Each and every one of these pearls of wisdom came from bitter experience, when work was hard-going, and things didn’t click the way the person wanted them to. So take a look at the world from a different perspective, you might be surprised at what you find.</p> <p><a href="http://www.behance.net/gallery/Oscar-Wilde/9330545" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/001.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Think-More/12046231" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/002.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Lettering-Project-1-ver1-typography/11804917" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/003.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Evolve/2498441" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/004.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Picassos-Quote/10886511" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/005.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Leonardos-quote/11343977" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/006.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Everything-is-a-Work-in-Progress/10341425" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/007.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/The-Beauty-of-Dreams/10966685" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/008.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Directions-Wallpaper-Freebie/10967337" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/009.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Typography-Poster-Set-No2-by-Matt-Edson/11136049" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/010.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Inspyre-Series/11713373" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/011.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Typographic-Poster/12006877" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/012.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Every-Artist-was-First-an-Amateur/2086512" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/013.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Ideas-Are-Bulletproof/3424703" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/014.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Saul-Bass-Poster/5623933" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/015.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Type-Posters-Inspirational-Quotes/5391679" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/016.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/52-Weeks-of-Hand-Lettering-Week-3/7766809" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/017.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Letterpress-Quote-Poster/10015899" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/018.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Do-what-you-can/10092743" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/019.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Colin-wright-quote-poster-design/10321421" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/020.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Typography-Quote-Posters/11851235" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/021.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/What-I-dont-Know/10474405" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/022.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Uni-Project-Typeset-First-Semester/10510949" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/023.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Interesting-Questions/10562075" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/024.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Iron-Man/10736129" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/025.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Blackboard-Typography/11047481" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/026.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Cesar-Cruz/11486891" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/027.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/I-LOVE-TYPOGRAPHY/2741459" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/028.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Never-Finished/10052595" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/029.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Quote-Experimentation/1031973" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/030.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/We-the-Willing-T-Shirt-and-Poster/1857793" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/031.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/Churchill/1957019" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/032.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/The-core-of-mans-spirit/2101430" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/033.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/The-Quote-Illustration-Project/7683851" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/034.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://mustbeprinted.com/post/44286245282/be-yourself-everyone-else-is-already-taken" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/035.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://oneskillwonder.deviantart.com/art/Practice-Safe-Design-165694242?q=boost" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/036.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p><a href="http://www.behance.net/gallery/The-Quote-Illustration-Project/7683851" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/02/037.jpg" width="650" alt="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"></a></p> <p> </p> <p><em><strong>Which of these quotes inspires you the most? Have we missed a quote you like to refer to? Let us know in the comments.</strong></em></p> <p><br><br> </p>
    <table width="100%"> <tbody>
    <tr> <td> <a href="http://www.mightydeals.com/deal/beautune.html?ref=inwidget" rel="nofollow external" class="bo"><strong>Create Picture-Perfect Portraits With Beautune – only $14!</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="35+ inspiring quotes for designers" style="max-width: 100%; height: auto;"><br> </a> </td> </tr> </tbody>
    </table> <p><br> </p> <a href="http://www.webdesignerdepot.com/2014/02/35-inspiring-quotes-for-designers/" 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%2F2014%2F02%2F35-inspiring-quotes-for-designers%2F&amp;t=35%2B+inspiring+quotes+for+designers" 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%2F2014%2F02%2F35-inspiring-quotes-for-designers%2F&amp;t=35%2B+inspiring+quotes+for+designers" 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%2F2014%2F02%2F35-inspiring-quotes-for-designers%2F&amp;t=35%2B+inspiring+quotes+for+designers" 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%2F2014%2F02%2F35-inspiring-quotes-for-designers%2F&amp;t=35%2B+inspiring+quotes+for+designers" 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%2F2014%2F02%2F35-inspiring-quotes-for-designers%2F&amp;t=35%2B+inspiring+quotes+for+designers" 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/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/sc/4/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530523614/u/49/f/661066/c/35285/s/370c2171/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>When it’s going well, design is a pleasure. But we all know what it’s like to experience a bad day: nothing works the way it should, colors clash, type mumbles, the message is lost altogether....</Summary>
<Website>http://rss.feedsportal.com/c/35285/f/661066/s/370c2171/sc/4/l/0L0Swebdesignerdepot0N0C20A140C0A20C350Einspiring0Equotes0Efor0Edesigners0C/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41318/guest@my.umbc.edu/1756620bdce535ec140a0106c80943db/api/pixel</TrackingUrl>
<Tag>art</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>design-quotes</Tag>
<Tag>designer-posters</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>html5</Tag>
<Tag>illustrator</Tag>
<Tag>inspiration</Tag>
<Tag>inspirational-quotes</Tag>
<Tag>inspirational-web-design-quotations</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>oracle</Tag>
<Tag>photoshop</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web-design-quotes</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>Thu, 13 Feb 2014 03:15:22 -0500</PostedAt>
<EditAt>Thu, 13 Feb 2014 03:15:22 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41317" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41317">
<Title>Apple Says War Zones Don&#8217;t Ship Its Supplies</Title>
<Body>
<![CDATA[
    <div class="html-content">Apple said that it had confirmed that its suppliers did not use tantalum, a type of metal commonly used in electronics, containing minerals from areas engaged in warfare.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.nytimes.com%2F2014%2F02%2F14%2Ftechnology%2Fapple-says-supplies-dont-come-from-war-zones.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Says+War+Zones+Don%E2%80%99t+Ship+Its+Supplies" 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.nytimes.com%2F2014%2F02%2F14%2Ftechnology%2Fapple-says-supplies-dont-come-from-war-zones.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Says+War+Zones+Don%E2%80%99t+Ship+Its+Supplies" 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.nytimes.com%2F2014%2F02%2F14%2Ftechnology%2Fapple-says-supplies-dont-come-from-war-zones.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Says+War+Zones+Don%E2%80%99t+Ship+Its+Supplies" 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.nytimes.com%2F2014%2F02%2F14%2Ftechnology%2Fapple-says-supplies-dont-come-from-war-zones.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Says+War+Zones+Don%E2%80%99t+Ship+Its+Supplies" 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.nytimes.com%2F2014%2F02%2F14%2Ftechnology%2Fapple-says-supplies-dont-come-from-war-zones.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Apple+Says+War+Zones+Don%E2%80%99t+Ship+Its+Supplies" 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/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/sc/4/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/186530582571/u/0/f/640387/c/34625/s/370b53e4/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Apple said that it had confirmed that its suppliers did not use tantalum, a type of metal commonly used in electronics, containing minerals from areas engaged in warfare.      </Summary>
<Website>http://www.nytimes.com/2014/02/14/technology/apple-says-supplies-dont-come-from-war-zones.html?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41317/guest@my.umbc.edu/9d1279ee82fc1c446a834fe894beecbc/api/pixel</TrackingUrl>
<Tag>apple-inc</Tag>
<Tag>congo-democratic-republic-of-congo-kinshasa</Tag>
<Tag>electronics</Tag>
<Tag>new</Tag>
<Tag>tantalum</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>Thu, 13 Feb 2014 02:02:13 -0500</PostedAt>
<EditAt>Fri, 14 Feb 2014 15:11:07 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41316" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41316">
<Title>Internship: MD State Archives Summer Program</Title>
<Tagline>Deadline: Monday, March 31</Tagline>
<Body>
<![CDATA[
    <div class="html-content">There are position openings in history, information technology/computer science, women's studies, and records management. <br><br>[Click on the link for more information.]<br>
    </div>
]]>
</Body>
<Summary>There are position openings in history, information technology/computer science, women's studies, and records management.   [Click on the link for more information.]</Summary>
<Website>http://msa.maryland.gov/msa/intromsa/employ/html/employ.html</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41316/guest@my.umbc.edu/ec31fc03458530e73feca9f91042718f/api/pixel</TrackingUrl>
<Group token="amst">American Studies Department</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/amst</GroupUrl>
<AvatarUrl>https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/xsmall.png?1700059172</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/original.png?1700059172</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/xxlarge.png?1700059172</AvatarUrl>
<AvatarUrl size="xlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/xlarge.png?1700059172</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/large.png?1700059172</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/medium.png?1700059172</AvatarUrl>
<AvatarUrl size="small">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/small.png?1700059172</AvatarUrl>
<AvatarUrl size="xsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/xsmall.png?1700059172</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/571/f1a862c4a5a31b363f857fee1e038fea/xxsmall.png?1700059172</AvatarUrl>
<Sponsor>Maryland State Archives</Sponsor>
<ThumbnailUrl size="xxlarge">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/xxlarge.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/xlarge.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="large">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/large.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="medium">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/medium.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="small">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/small.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="xsmall">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/xsmall.jpg?1392268592</ThumbnailUrl>
<ThumbnailUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/041/316/95e00030b8bd03e7c44548a60263ee6d/xxsmall.jpg?1392268592</ThumbnailUrl>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>false</CommentsAllowed>
<PostedAt>Thu, 13 Feb 2014 00:16:56 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="41315" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41315">
<Title>Facebook Deal on Privacy Is Under Attack</Title>
<Body>
<![CDATA[
    <div class="html-content">A class-action settlement intended to ensure that Facebook obtained consent before using people’s images or other data in ads is about to receive another legal challenge.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fwww.nytimes.com%2F2014%2F02%2F13%2Ftechnology%2Ffacebook-deal-on-privacy-is-under-attack.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Facebook+Deal+on+Privacy+Is+Under+Attack" 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.nytimes.com%2F2014%2F02%2F13%2Ftechnology%2Ffacebook-deal-on-privacy-is-under-attack.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Facebook+Deal+on+Privacy+Is+Under+Attack" 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.nytimes.com%2F2014%2F02%2F13%2Ftechnology%2Ffacebook-deal-on-privacy-is-under-attack.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Facebook+Deal+on+Privacy+Is+Under+Attack" 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.nytimes.com%2F2014%2F02%2F13%2Ftechnology%2Ffacebook-deal-on-privacy-is-under-attack.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Facebook+Deal+on+Privacy+Is+Under+Attack" 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.nytimes.com%2F2014%2F02%2F13%2Ftechnology%2Ffacebook-deal-on-privacy-is-under-attack.html%3Fpartner%3Drss%26emc%3Drss&amp;t=Facebook+Deal+on+Privacy+Is+Under+Attack" 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/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/sc/1/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557731953/u/0/f/640387/c/34625/s/370a8b77/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>A class-action settlement intended to ensure that Facebook obtained consent before using people’s images or other data in ads is about to receive another legal challenge.      </Summary>
<Website>http://www.nytimes.com/2014/02/13/technology/facebook-deal-on-privacy-is-under-attack.html?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41315/guest@my.umbc.edu/6caff9172bde54b82b3061b080648fac/api/pixel</TrackingUrl>
<Tag>children-and-childhood</Tag>
<Tag>facebook-inc-fb-nasdaq</Tag>
<Tag>google-inc-goog-nasdaq</Tag>
<Tag>new</Tag>
<Tag>nonprofit-organizations</Tag>
<Tag>online-advertising</Tag>
<Tag>suits-and-litigation-civil</Tag>
<Tag>technology</Tag>
<Tag>walt-disney-company-dis-nyse</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>Thu, 13 Feb 2014 00:08:11 -0500</PostedAt>
</NewsItem>

</News>
