<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>pixelhandler</title>
  <link href="http://pixelhandler.com/atom.xml" rel="self"/>
  <link href="http://pixelhandler.com/"/>
  <updated>2012-02-29T01:05:33-08:00</updated>
  <id>http://pixelhandler.com/</id>
  <author>
    <name>Bill Heaton</name>
    
      <email>bill@pixelhandler.com</email>
    
  </author>

  
  <entry>
    <title>Backbone.js Models, Views and Collections to Present API Data</title>
    <link href="http://pixelhandler.com/blog/2012/02/29/backbone-js-models-views-collections-to-present-api-data/"/>
    <updated>2012-02-29T12:15:00-08:00</updated>
    <id>http://pixelhandler.com/blog/2012/02/29/backbone-js-models-views-collections-to-present-api-data</id>
    <content type="html">&lt;p&gt;This tutorial explores coding with &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; title=&quot;Backbone.js&quot;&gt;Backbone.js&lt;/a&gt; using data stored in an API. The code developed will interact with an API as described in the earlier post : &lt;a href=&quot;http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/&quot; title=&quot;Develop a RESTful API Using Node.js With Express and Mongoose&quot;&gt;Develop a RESTful API Using Node.js With Express and Mongoose&lt;/a&gt;. This article is the second tutorial in a series on the topic building an online store using &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_state_transfer&quot; title=&quot;Representational state transfer&quot;&gt;REST&lt;/a&gt;. Previously, I explored creating an API with &lt;a href=&quot;http://nodejs.org/&quot; title=&quot;Node.js&quot;&gt;Node.js&lt;/a&gt;, &lt;a href=&quot;http://expressjs.com/&quot; title=&quot;High performance, high class Web development for Node.js&quot;&gt;Express&lt;/a&gt;, &lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;MongoDB (from 'humongous') - Document-oriented storage&quot;&gt;MongoDB&lt;/a&gt;, and &lt;a href=&quot;http://mongoosejs.com/&quot; title=&quot;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&quot;&gt;Mongoose&lt;/a&gt;. In this article I demonstrate an overview of coding a front-end interface for a data-driven application using Backbone.&lt;/p&gt;

&lt;p&gt;Backbone organizes code objects for &lt;a href=&quot;http://documentcloud.github.com/backbone/#Model&quot; title=&quot;Backbone.Model&quot;&gt;Models&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/backbone/#Collection&quot; title=&quot;Backbone.Collection&quot;&gt;Collections&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/backbone/#View&quot; title=&quot;Backbone.View&quot;&gt;Views&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/backbone/#Router&quot; title=&quot;Backbone.Router&quot;&gt;Routers&lt;/a&gt; and uses a &lt;a href=&quot;http://documentcloud.github.com/backbone/#Sync&quot; title=&quot;Backbone.sync&quot;&gt;sync&lt;/a&gt; object to interact with an API. I will use these constructors to build a list of projects from objects stored as documents in a database (&lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;MongoDB (from 'humongous') - Document-oriented storage&quot;&gt;MongoDB&lt;/a&gt;) . The API built in the previous tutorial facilitates development with an actual &lt;a href=&quot;http://ecomapi.herokuapp.com/&quot; title=&quot;Web Service&quot;&gt;web service&lt;/a&gt; rather than mocking JSON data in a flat file.&lt;/p&gt;

&lt;p&gt;For the purpose of getting to know Backbone, the use case that I will focus on is listing products consumed via &lt;a href=&quot;http://www.json.org/&quot; title=&quot;JSON&quot;&gt;JSON&lt;/a&gt; data from a web service. Each product in the list represents data found in a &lt;em&gt;model&lt;/em&gt;. The product list represents a &lt;em&gt;collection&lt;/em&gt; of (product) models. The HTML is generated using a &lt;em&gt;view&lt;/em&gt; which renders data - blending the model's JSON data with a template. Finally a &lt;em&gt;route&lt;/em&gt; triggers the asynchronous process of fetching data and rendering the product list by listening for a &lt;a href=&quot;http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-hashchange&quot; title=&quot;hashchange&quot;&gt;hashchange&lt;/a&gt; or using &lt;a href=&quot;https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history&quot; title=&quot;Manipulating the browser history&quot;&gt;pushState&lt;/a&gt;. These are the core components that Backbone provides.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;I will start with the end in mind. I'll need a router to &lt;strong&gt;list&lt;/strong&gt; the products, a &lt;strong&gt;collection&lt;/strong&gt; of data, a &lt;strong&gt;view&lt;/strong&gt; to render the list, and a &lt;strong&gt;model&lt;/strong&gt; for each data object. (The code examples are found in a &lt;a href=&quot;https://gist.github.com/1912291&quot; title=&quot;Product API example using Backbone.js Models, Views and Collections&quot;&gt;gist&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;The Product's Router&lt;/h2&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product_router.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;PX = window.PX || {};
// application
PX.App = Backbone.Router.extend({
    routes: {
        &amp;quot;/&amp;quot;: &amp;quot;listProducts&amp;quot;,
        &amp;quot;list&amp;quot;: &amp;quot;listProducts&amp;quot;,
        &amp;quot;products/:id&amp;quot;: &amp;quot;showProductDetails&amp;quot;
    },
    //initialize: function (options) {},
    listProducts: function () {
        var productsList = new PX.ProductListView({
            &amp;quot;container&amp;quot;: $('#container'),
            &amp;quot;collection&amp;quot;: PX.products
        });
        PX.products.deferred.done(function () {
            productsList.render();
        });
    },
    showProductDetails: function () {
        var productDetails = new PX.ProductDetailsView();
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;In the code above I am using a object named 'PX' as a namespace, adding the code for the Backbone objects to the PX object to minimize adding a bunch global variables to the window obejct. For the purpose of this tutorial I am only adding one global object, 'PX'.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PX = window.PX || {};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The object literal &lt;code&gt;{ ... }&lt;/code&gt; is an argument to &lt;code&gt;Backbone.Router.extend&lt;/code&gt; which is the &lt;strong&gt;prototype&lt;/strong&gt; for the router object that I will use to render the products' list. &lt;code&gt;PX.App&lt;/code&gt; is a constructor with a prototype that extends the &lt;code&gt;Backbone.Router&lt;/code&gt; function. The prototype (object literal) has to properties: &lt;em&gt;routes&lt;/em&gt; and &lt;em&gt;listProducts&lt;/em&gt;. The routes property has an object literal with two named routes - the root directory &quot;/&quot; and &quot;list&quot;. Both routes are assigned a string which is the name of the function that handles the routes. See the &lt;a href=&quot;http://documentcloud.github.com/backbone/#Router&quot; title=&quot;Backbone.Router&quot;&gt;Backbone.Router documentation&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;In the routes' handler method (&lt;code&gt;listProducts&lt;/code&gt;) I create a new &lt;code&gt;Backbone.View&lt;/code&gt; object using the new operator with &lt;code&gt;PX.ProductListView&lt;/code&gt; and passing some options as an object literal. Included in the options argument are properties for a &lt;code&gt;container&lt;/code&gt; and also a &lt;code&gt;collection&lt;/code&gt;. The container is the jQuery object where I will render the products list or &lt;em&gt;view&lt;/em&gt;. The collection is a list of products or a collection of product models. Typically with an application that has some output from a server-side script a collection's data would be written into a script element (or bootstrapped) as JSON data so that an AJAX request is not necessary. In this case, I am not using any server-side scripting; so, I will need to fetch a collection (array) of products from an API. Also, I am using a &lt;a href=&quot;http://api.jquery.com/category/deferred-object/&quot; title=&quot;utility object that can register multiple callbacks into callback queues&quot;&gt;jQuery Deferred object&lt;/a&gt; to indicate when the collection is ready. The function &lt;code&gt;PX.products.deferred.done&lt;/code&gt; accepts functions as arguments which can be executed when the deferred object is resolved. In this example the render method is called when a list of products (collection instance) is populated with models (data).&lt;/p&gt;

&lt;p&gt;I have not created a view or a collection yet; to use this router I will need both.&lt;/p&gt;

&lt;h2&gt;The Products' View(s)&lt;/h2&gt;

&lt;p&gt;I will need two types of view objects one to render the list and one for each item in the list. A Backbone view has a model instance as data; and uses a &lt;code&gt;render&lt;/code&gt; method to parse the JSON data into HTML with using a template, e.g. the &lt;a href=&quot;https://github.com/janl/mustache.js/&quot; title=&quot;Minimal templating with  in JavaScript&quot;&gt;Mustache library&lt;/a&gt; provides a sweet logic-less utility to render JSON using an HTML template (see a &lt;a href=&quot;http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/&quot; title=&quot;Tutorial: HTML Templates with Mustache.js&quot;&gt;Mustache tutorial&lt;/a&gt; with &lt;a href=&quot;http://coenraets.org/tutorials/mustache/&quot; title=&quot;example code using Mustache&quot;&gt;examples&lt;/a&gt;).&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product_list_view.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;PX.ProductListView = Backbone.View.extend({
    tagName: &amp;quot;ul&amp;quot;,
    className: &amp;quot;products&amp;quot;,
    render: function () {
        for (var i = 0; i &amp;lt; this.collection.length; i++) {
            this.renderItem(this.collection.models[i]);
        };
        $(this.container).find(this.className).remove();
        this.$el.appendTo(this.options.container);
        return this;
    },
    renderItem: function (model) {
        var item = new PX.ProductListItemView({
            &amp;quot;model&amp;quot;: model
        });
        item.render().$el.appendTo(this.$el);
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;The constructor for the &lt;em&gt;product list view&lt;/em&gt; above uses an (unordered list) &lt;code&gt;ul&lt;/code&gt; tag and will be responsible for rendering a list of products. The render method uses an iteration over the object's &lt;code&gt;collection&lt;/code&gt; to build the list of products. The render method depends on the list view object having a &lt;code&gt;collection&lt;/code&gt; property. (I should have added a check during initialization and also thrown an error if the constructor is called without an option for the collection.)&lt;/p&gt;

&lt;p&gt;When rendering a list, the &lt;code&gt;render&lt;/code&gt; method calls a &lt;code&gt;renderItem&lt;/code&gt; method which renders each list item. In the method to render each &lt;code&gt;li&lt;/code&gt; a variable named &lt;code&gt;item&lt;/code&gt; is assigned a new &lt;code&gt;PX.ProductListItemView&lt;/code&gt; instance. This &lt;em&gt;item&lt;/em&gt; is constructed with a model from the products' collection. The item object is a view instance for each product in the list. Notice the reference to &lt;code&gt;this.$el&lt;/code&gt;, every Backbone view object has an &lt;code&gt;el&lt;/code&gt; property and also a jQuery/Zepto object &lt;code&gt;$el&lt;/code&gt;. Also in the render method, the return value is &lt;code&gt;this&lt;/code&gt;, which refers to the view object itself. So, when a view is rendered the element can be accessed like so &lt;code&gt;viewInstance.render().$el&lt;/code&gt;. When this code is executed: &lt;code&gt;item.render().$el.appendTo(this.$el);&lt;/code&gt; from within the &lt;code&gt;renderItem&lt;/code&gt; method, the result of rendering the product (item) is appended to the &lt;code&gt;ul&lt;/code&gt; (this.$el) element with belongs to the product list view instance object.&lt;/p&gt;

&lt;p&gt;I will need to create a view to render each item...&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product_list_item_view.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;PX.ProductListItemView = Backbone.View.extend({
    tagName: &amp;quot;li&amp;quot;,
    className: &amp;quot;product&amp;quot;,
    events: {
        &amp;quot;click&amp;quot;: &amp;quot;showProductDetails&amp;quot;
    },
    initialize: function (options) {
        this.template = $('#product-template').html();
    },
    render: function () {
        var markup = Mustache.to_html(this.template, this.model.toJSON());
        this.$el.html(markup).attr('id',this.model.get('_id'));
        return this;
    },
    showProductDetails: function(event) {
        var targ = $(event.target), pid = targ.attr(id), dest;
        event.preventDefault();
        dest = &amp;quot;products/&amp;quot; + ( (pid) ? pid : targ.closest('li').attr('id') );
        console.log(&amp;quot;Show product details: &amp;quot; + pid);
        PX.app.navigate(dest);
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;The &lt;em&gt;product list items'&lt;/em&gt; view constructor uses a (list item) &lt;code&gt;li&lt;/code&gt; tag and during initialization selects some HTML to use as an HTML template. This template will be used to render the JSON data for each product. The template HTML is found on the document within a script element, see below.&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product-template.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&amp;quot;text/template&amp;quot; id=&amp;quot;product-template&amp;quot;&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;products/{{_id}}&amp;quot;&amp;gt;{{title}}&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;{{description}}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;ID: {{_id}}&amp;lt;/p&amp;gt;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;The HTML template will be used to render the markup; see the code in the render method &lt;code&gt;Mustache.to_html(this.template, this.model.toJSON())&lt;/code&gt;. To learn more about using Mustache, see: &lt;a href=&quot;https://github.com/janl/mustache.js/&quot; title=&quot;Minimal templating with  in JavaScript&quot;&gt;mustache.js&lt;/a&gt;. The &lt;a href=&quot;http://documentcloud.github.com/underscore/&quot; title=&quot;Underscore is a utility-belt library for JavaScript&quot;&gt;Underscore&lt;/a&gt; library has a template rendering utility as well, I happen to like the &lt;em&gt;logic-less&lt;/em&gt; library and syntax that Mustache.js provides. This demonstrates the flexibility of Backbone, I can use whatever methods I choose to render HTML. The template HTML could have been loaded using AJAX and stored as an object, in this example I used a script element. In the template there are placeholders for the JSON object's properties: &lt;code&gt;,&lt;/code&gt; and ``. The job of the template utility is blending JSON data found in a Backbone model object with a HTML template string.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;$el&lt;/code&gt; property of the view instance object for the list item is an &lt;code&gt;li&lt;/code&gt; element, which receives the &lt;code&gt;markup&lt;/code&gt; as it's HTML content when the code &lt;code&gt;this.$el.html(markup)&lt;/code&gt; in the render method executes. Using &lt;code&gt;this.$el&lt;/code&gt; allows for chaining. So, I added an &lt;code&gt;id&lt;/code&gt; property to the &lt;code&gt;li&lt;/code&gt; element as well.&lt;/p&gt;

&lt;p&gt;To learn more about &lt;a href=&quot;http://documentcloud.github.com/backbone/#View&quot; title=&quot;Backbone.View&quot;&gt;Backbone.View objects&lt;/a&gt; see the documentation.&lt;/p&gt;

&lt;p&gt;There would be no list of products to render without a collection...&lt;/p&gt;

&lt;h2&gt;The Products' Collection&lt;/h2&gt;

&lt;p&gt;The product data exists in an (example) API and is available using a &lt;a href=&quot;http://ecomapi.herokuapp.com/&quot; title=&quot;Web Service&quot;&gt;Web service&lt;/a&gt;; the url to fetch an array of products is '/api/products'. &lt;a href=&quot;http://documentcloud.github.com/backbone/#Collection&quot; title=&quot;Backbone.Collection&quot;&gt;Backbone collections&lt;/a&gt; can fetch this array, then generate models to add as members of the products' collection. Below is a constructor to generate a collection of product data using an API for the data source.&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product_collection.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// collection
(function () {
    var ProductList;

    ProductList = Backbone.Collection.extend({
        model: PX.Product,
        url: '/api/products',
        initialize: function () {
            this.fetch({
                success: this.fetchSuccess,
                error: this.fetchError
            });
            this.deferred = new $.Deferred();
        },
        deferred: Function.constructor.prototype,
        fetchSuccess: function (collection, response) {
            collection.deferred.resolve();
        },
        fetchError: function (collection, response) {
            throw new Error(&amp;quot;Products fetch did get collection from API&amp;quot;);
        }
    });

    PX.products = new ProductList();
    ProductList = null;
}());&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;In the &lt;code&gt;PX.ProductList&lt;/code&gt; prototype there are properties for &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt;. The model property has a constructor object used to generate models as members of the products collection. The url property is the web service that &lt;a href=&quot;http://documentcloud.github.com/backbone/#Sync&quot; title=&quot;Backbone.sync&quot;&gt;Backbone.sync&lt;/a&gt; will call to fetch the data. During initialization the product data is fetched and a &lt;code&gt;deferred&lt;/code&gt; property is initialized which will be resolved during execution of the fetch success handler function.&lt;/p&gt;

&lt;p&gt;Backbone wraps the AJAX success and error handlers and calls the handlers sent following the fetch call. When Backbone calls either handler, two arguments are passed &lt;code&gt;collection&lt;/code&gt; and &lt;code&gt;response&lt;/code&gt;. In this example, the &lt;code&gt;fetchSuccess&lt;/code&gt; method resolves the collection's deferred object and the &lt;code&gt;fetchError&lt;/code&gt; method throws an error.&lt;/p&gt;

&lt;p&gt;When the router fires the method to &lt;code&gt;listProducts&lt;/code&gt; the collections' deferred object is used to render the list when the deferred is done (resolved). See the router code &lt;code&gt;PX.products.deferred.done&lt;/code&gt;; which takes an anonymous function to call the list view's render method, &lt;code&gt;productsList.render();&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The collection cannot generate a list of products without a model constructor...&lt;/p&gt;

&lt;h2&gt;The Product Model&lt;/h2&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=product_model.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// model
PX.Product = Backbone.Model.extend({
    defaults: {
        title: null,
        description: null
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;This &lt;a href=&quot;http://documentcloud.github.com/backbone/#Model&quot; title=&quot;Backbone.Model&quot;&gt;Backbone.Model&lt;/a&gt; is very simple, it has some defaults defined on it's prototype object: &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;. The API has a much more data in each product document. However, the purpose of this tutorial is to demonstrate generating a list of products; these two properties do for now. Each model that the collection adds will have all the data provided by the Web service. The List view instance also uses the model instance to get JSON data when rendering each list item. The model object has a method to get the data as an object &lt;code&gt;.toJSON()&lt;/code&gt; which is not stringified but rather a JavaScript object. The model's data is stored on a property of the model instance named &lt;code&gt;attributes&lt;/code&gt;. To learn more about &lt;a href=&quot;http://documentcloud.github.com/backbone/#Model&quot; title=&quot;Backbone.Model&quot;&gt;Backbone.Model&lt;/a&gt; see the documentation.&lt;/p&gt;

&lt;p&gt;All these objects work together to provide a representation of the API data in the format specified using the template and the view instance objects to present HTML within the browser. The server is only providing data as JSON objects. All the HTML rendering is done on the client-side.&lt;/p&gt;

&lt;p&gt;So to kick off the application we need to create an instance of the router and start Backbone.history ...&lt;/p&gt;

&lt;h2&gt;Bootstrap the Application&lt;/h2&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1912291.js?file=bootstrap.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// bootstrap
PX.app = new PX.App();
Backbone.history.start();&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;new PX.App()&lt;/code&gt; returns the instance of the router and &lt;code&gt;Backbone.history.start()&lt;/code&gt; handles monitoring of the hashchange or HTML5 pushState. When a route is matched in the URL e.g. /#list the assigned function is called to handler the route's behavior. For a demo, see the example API page at &lt;a href=&quot;http://ecomapi.herokuapp.com/#list&quot; title=&quot;Backbone List of Products generated with API data&quot;&gt;http://ecomapi.herokuapp.com/#list&lt;/a&gt; (look under the heading 'Product List' you can reset the data with the button 'Add product fixtures').&lt;/p&gt;

&lt;p&gt;See the &lt;a href=&quot;http://documentcloud.github.com/backbone/#History&quot; title=&quot;Backbone History&quot;&gt;Backbone.history documentation&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;Post Hoc&lt;/h2&gt;

&lt;p&gt;This tutorial walks through development using the core components that Backbone provides; as stated in the Backbone documentation, giving &lt;em&gt;structure&lt;/em&gt; to a web application. There are more than a few ways to do this same job of rendering a list of products with JSON data. Perhaps event a single AJAX call using a success handler and some DOM manipulation with jQuery. However, without structure in a web application, the task of managing code as the application's life matures and grows (well into a beast) can become a fairly difficult. Backbone provides simple structure and still allows the developer to decide how to organize code, and which utilities to add. I like to use jQuery, Mustache and RequireJS as well, Backbone does not get in the way. See a &lt;a href=&quot;https://github.com/pixelhandler/app-boilerplate&quot; title=&quot;Example application structure with RequireJS and Backbone.js&quot;&gt;sample application&lt;/a&gt; using these libraries. I used this sample application to test the file structure and build process when planning development for a fairly complex application.&lt;/p&gt;

&lt;p&gt;Perhaps you can continue building upon this tutorial and generate a route to view product details. Also, if you have not already read the first article in this series, you can build your own development API as well - &lt;a href=&quot;http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/&quot; title=&quot;Develop a RESTful API Using Node.js With Express and Mongoose&quot;&gt;Develop a RESTful API Using Node.js With Express and Mongoose&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next post I plan to take a second look at this same code; but instead, walk though the process of using &lt;a href=&quot;http://pivotal.github.com/jasmine/&quot; title=&quot;Jasmine is a behavior-driven development framework&quot;&gt;Jasmine&lt;/a&gt;, a behavior-driven development framework, to discover the implementation. This tutorial is structured in the same way I would approach writing tests, sort of a top-down approach beginning with the router instance.&lt;/p&gt;

&lt;h2&gt;Reference&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Gist: &lt;a href=&quot;https://gist.github.com/1912291&quot; title=&quot;Product API example using Backbone.js Models, Views and Collections&quot;&gt;Product API example using Backbone.js Models, Views and Collections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;API tutorial: &lt;a href=&quot;http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/&quot; title=&quot;Develop a RESTful API Using Node.js With Express and Mongoose&quot;&gt;Develop a RESTful API Using Node.js With Express and Mongoose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ecomapi.herokuapp.com/#list&quot; title=&quot;Backbone List of Products generated with API data&quot;&gt;Sample API with list generated using code in this tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; title=&quot;Backbone.js&quot;&gt;Backbone documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://documentcloud.github.com/underscore/&quot; title=&quot;Underscore is a utility-belt library for JavaScript&quot;&gt;Underscore documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Framework for API: &lt;a href=&quot;http://expressjs.com/&quot; title=&quot;High performance, high class Web development for Node.js&quot;&gt;Express, a node package for developing node.js apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-hashchange&quot; title=&quot;hashchange&quot;&gt;hashchange&lt;/a&gt; | HTML5 &lt;a href=&quot;https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history&quot; title=&quot;Manipulating the browser history&quot;&gt;pushState&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://coenraets.org/tutorials/mustache/&quot; title=&quot;example code using Mustache&quot;&gt;Mustache examples&lt;/a&gt; | &lt;a href=&quot;http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/&quot; title=&quot;Tutorial: HTML Templates with Mustache.js&quot;&gt;Mustache tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pixelhandler/app-boilerplate&quot; title=&quot;Example application structure with RequireJS and Backbone.js&quot;&gt;Example application structure with RequireJS and Backbone.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Develop a RESTful API Using Node.js With Express and Mongoose</title>
    <link href="http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/"/>
    <updated>2012-02-09T18:02:00-08:00</updated>
    <id>http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose</id>
    <content type="html">&lt;p&gt;For the past couple months I've been developing with &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; title=&quot;Backbone.js&quot;&gt;Backbone.js&lt;/a&gt; and mocking data for an application. I've worked in the ecommerce industry for a few years and thought it would be a good idea to create a serious of posts on the topic of developing with Backbone using an example with some complexity, perhaps more than a '&lt;em&gt;todos&lt;/em&gt;' or '&lt;em&gt;blog&lt;/em&gt;' application, so the example will utilize a familiar Web application, an online store. To program a data-driven asynchronous application using a language I already know, JavaScript, the best way to learn is to write some code. So, I researched a few example applications using &lt;a href=&quot;http://nodejs.org/&quot; title=&quot;Node.js&quot;&gt;Node.js&lt;/a&gt; with a &lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;MongoDB (from 'humongous') - Document-oriented storage&quot;&gt;MongoDB database&lt;/a&gt;. This article is intended to be the first in a series on the topic building an online store using &lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_state_transfer&quot; title=&quot;Representational state transfer&quot;&gt;REST&lt;/a&gt; and Backbone.js to structure the code. This tutorial is not intended for production code, but rather an exploration of developing interactions with a RESTful API. This first post lays down a foundation for developing with a local API, then I can get into using the application with Backbone; but let's get into the server-side for a bit first.&lt;/p&gt;

&lt;h2&gt;API Design for Mock Ecommerce Application&lt;/h2&gt;

&lt;p&gt;Goals for the Web service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple API design and pragmatic REST Web service, with only 2 base URLs per resource&lt;/li&gt;
&lt;li&gt;Keep verbs out of your base URLs&lt;/li&gt;
&lt;li&gt;Our HTTP verbs are POST, GET, PUT, and DELETE (&lt;a href=&quot;http://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot; title=&quot;Create, read, update and delete&quot;&gt;Create, Read, Update, Delete&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Concrete names are better than abstract&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;em&gt;Example&lt;/em&gt; : two (2) resources (&lt;code&gt;/products&lt;/code&gt; and &lt;code&gt;/products/XX&lt;/code&gt;) and the four (4) HTTP verbs&lt;/p&gt;

&lt;table class=&quot;cols5&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;&lt;strong&gt;Resource&lt;/strong&gt;&lt;/th&gt;
        &lt;th&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;br&gt;(create)&lt;/th&gt;
        &lt;th&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;br&gt;(read)&lt;/th&gt;
        &lt;th&gt;&lt;strong&gt;PUT&lt;/strong&gt;&lt;br&gt;(update)&lt;/th&gt;
        &lt;th&gt;&lt;strong&gt;DELETE&lt;/strong&gt;&lt;br&gt;(delete)&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;/products&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;create a new product&lt;/td&gt;
        &lt;td&gt;list products&lt;/td&gt;
        &lt;td&gt;bulk update products&lt;/td&gt;
        &lt;td&gt;delete all products&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;/products/1234&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;error&lt;/td&gt;
        &lt;td&gt;show 1234&lt;/td&gt;
        &lt;td&gt;if exists update 1234, else error&lt;/td&gt;
        &lt;td&gt;delete 1234&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;




&lt;!-- more --&gt;


&lt;h3&gt;Nouns&lt;/h3&gt;

&lt;h4&gt;Products&lt;/h4&gt;

&lt;p&gt;There a many configurations for setting up a product to sell online, some with no options, with multiple configurable options, or groups of products. For this example I will use one of my favorite things, a &lt;em&gt;t-shirt&lt;/em&gt;. This type of product can be configured with size and color options, e.g. Black - Large, or Red - Medium; specific material variations would be represented as separate products, like long- vs. short-sleeves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product&lt;/strong&gt; attributes include:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Id,  
Title,  
Description,  
Images: [ { Kind, URL } ],  
Categories: [ { Name } ],  
Style: Number,  
Varients: [  
  {  
    Color,  
    Images: [  
      { Kind, URL }  
    ],  
    Sizes: [  
      { Size, Available, SKU, Price }  
    ],  
  }  
]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.json.org/&quot; title=&quot;JSON (JavaScript Object Notation)&quot;&gt;JSON&lt;/a&gt;&lt;/strong&gt; data may be represented like so:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Product JSON.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;span class='line'&gt;36&lt;/span&gt;
&lt;span class='line'&gt;37&lt;/span&gt;
&lt;span class='line'&gt;38&lt;/span&gt;
&lt;span class='line'&gt;39&lt;/span&gt;
&lt;span class='line'&gt;40&lt;/span&gt;
&lt;span class='line'&gt;41&lt;/span&gt;
&lt;span class='line'&gt;42&lt;/span&gt;
&lt;span class='line'&gt;43&lt;/span&gt;
&lt;span class='line'&gt;44&lt;/span&gt;
&lt;span class='line'&gt;45&lt;/span&gt;
&lt;span class='line'&gt;46&lt;/span&gt;
&lt;span class='line'&gt;47&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Awesome T-shirt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;All about the details. Of course it&amp;#39;s black.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/main.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;categories&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Clothes&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Shirts&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;style&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1234&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;variants&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;color&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Black&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/thumbnail.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;catalog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/black.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;S&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;available&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;sku&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CAT-1234-Blk-S&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;price&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;99.99&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;M&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;available&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;sku&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CAT-1234-Blk-M&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;price&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;109.99&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;catalogs&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Apparel&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;The above object has a variety of types composing a document that should bring up some challenges in learning how to store and update the document in a &lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;MongoDB (from 'humongous') - Document-oriented storage&quot;&gt;MongoDB&lt;/a&gt; database. The first thing I needed to do was install MongoDB (see the &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Quickstart&quot; title=&quot;MongoDB Quickstart&quot;&gt;quickstart guide&lt;/a&gt;). To get to know the database I &lt;a href=&quot;http://try.mongodb.org/&quot; title=&quot;MongoDB browser shell&quot;&gt;tried out using Mongo in the console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll need to define the &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_service&quot; title=&quot;Web service&quot;&gt;Web service&lt;/a&gt; urls to interact with the data via REST like so...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/products &lt;em&gt;- list&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;/products/:id &lt;em&gt;- single&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Data: MongoDB using &lt;a href=&quot;http://mongoosejs.com/&quot; title=&quot;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&quot;&gt;Mongoose&lt;/a&gt; with &lt;a href=&quot;http://expressjs.com/&quot; title=&quot;High performance, high class Web development for Node.js&quot;&gt;Express framework&lt;/a&gt; running on Node.js&lt;/h3&gt;

&lt;p&gt;For installation of Node.js, NPM, and Express see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joyent/node/wiki/Installation&quot; title=&quot;Building and Installing Node.js&quot;&gt;Installing Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://npmjs.org/&quot; title=&quot;npm is a package manager for node.&quot;&gt;npm is a package manager for node.&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://expressjs.com/guide.html&quot; title=&quot;npm install express&quot;&gt;npm install express&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Also there are plenty of links at the end of the article to learn about this stack.&lt;/p&gt;

&lt;p&gt;Working with data using the Mongoose package in node, I will need to research storing JSON documents. The Mongoose documentation outlines the use of &lt;a href=&quot;http://mongoosejs.com/docs/schematypes.html&quot; title=&quot;SchemaTypes take care of validation, casting, defaults, and other general options in our models&quot;&gt;schema types&lt;/a&gt; and &lt;a href=&quot;http://mongoosejs.com/docs/embedded-documents.html&quot; title=&quot;Embedded documents are documents with schemas of their own that are part of other documents&quot;&gt;embedded documents&lt;/a&gt;; so these can be integrated into a product &lt;a href=&quot;http://mongoosejs.com/docs/model-definition.html&quot; title=&quot;Models are defined by passing a Schema instance to mongoose.model&quot;&gt;model&lt;/a&gt; to store the product JSON above. Models are defined by passing a Schema instance to &lt;a href=&quot;http://mongoosejs.com/docs/model-definition.html&quot; title=&quot;Models are defined by passing a Schema instance to mongoose.model&quot;&gt;mongoose.model&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;A Node App Running Express to Access Data using a RESTful Web Service&lt;/h4&gt;

&lt;p&gt;I found that a section of '&lt;a href=&quot;https://github.com/addyosmani/backbone-fundamentals#restful&quot; title=&quot;Using Node.js, Express, Mongoose and MongoDB&quot;&gt;Backbone Fundamentals&lt;/a&gt;' has an example application which is built using this same stack : Node.js, Express, Mongoose and MongoDB. I reviewed the example methods to GET, POST, PUT and DELETE. Then I got started with an instance of the &lt;code&gt;express.HTTPServer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I created a file &lt;code&gt;app.js&lt;/code&gt; and added the following JavaScript code:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;application_root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;express&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;mongoose&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mongoose&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Database&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;mongoose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mongodb://localhost/ecomm_database&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Config&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bodyParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;methodOverride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;application_root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;public&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;errorHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dumpExceptions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Ecomm API is running&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Launch server&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4242&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;In the above code, the line beginning with &lt;code&gt;var&lt;/code&gt; loads the modules needed for the API, and &lt;code&gt;app = express.createServer()&lt;/code&gt; creates the Web server. The Web server can also serve static files in a &lt;code&gt;public&lt;/code&gt; directory, the line in the configure block &lt;code&gt;app.use(express.static(path.join(application_root, &quot;public&quot;)));&lt;/code&gt; sets up the public directory to use static files. The code,  &lt;code&gt;mongoose.connect('mongodb://localhost/ecomm_database');&lt;/code&gt;, hooks up the database. All I needed to do is name the database, in this example I used the name: 'ecomm_database'. With MongoDB is setup and running, the actual database is automatically generated. To run &lt;code&gt;mongod&lt;/code&gt;, on the command line I needed to execute the command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mongod run --config /usr/local/Cellar/mongodb/2.0.1-x86_64/mongod.conf  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since I installed MongoGB on OSX Lion, the above command was printed out following the installation on my MacBook.&lt;/p&gt;

&lt;p&gt;The code &lt;code&gt;app.listen(4242);&lt;/code&gt; sets up the server to respond to the URL: &lt;em&gt;http://localhost:4242&lt;/em&gt;. Once &lt;em&gt;mongod&lt;/em&gt; is running, to start up the server genereated with the app.js file... I executed &lt;code&gt;node app.js&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;Now, I have a folder named 'ecomapi' and inside this directory is the 'app.js' file and a directory named 'public' which has an 'index.html' file. With the static index.html file I can load the data using jQuery which I am linking to on a CDN. Later I will be able to try out AJAX calls to create products using my browser's JavaScript console.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ecomapi
|-- app.js  
`-- public  
    `-- index.html  
&lt;/code&gt;&lt;/pre&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt; (index.html)&lt;/span&gt; &lt;a href='http://pixelhandler.com/downloads/code/node/ecomapi/index.html'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;div class='line'&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;API index&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Nouns...&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        /products&lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        /products/:id
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;In my browser I can load http://localhost:4242 and see that the static index.html file loads and also hitting http://localhost:4242/api spits out some text 'Ecomm API is running', which is the result of the get response:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app.get('/api', function (req, res) {  
  res.send('Ecomm API is running');  
});  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Up to this point we have a simple server with a single get response, next I can add in the data models and REST services.&lt;/p&gt;

&lt;h4&gt;Setup a Simple Model Using CRUD (create, read, update, delete)&lt;/h4&gt;

&lt;p&gt;Following the &lt;code&gt;app.configure&lt;/code&gt; code block, in the &lt;em&gt;app.js&lt;/em&gt;, I added a Schema and a Product Model:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var Schema = mongoose.Schema;  

var Product = new Schema({  
    title: { type: String, required: true },  
    description: { type: String, required: true },  
    style: { type: String, unique: true },  
    modified: { type: Date, default: Date.now }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since I still needed to learn how to use the &lt;a href=&quot;http://mongoosejs.com/docs/schematypes.html&quot; title=&quot;SchemaTypes take care of validation, casting, defaults, and other general options in our models&quot;&gt;schema types&lt;/a&gt; and &lt;a href=&quot;http://mongoosejs.com/docs/embedded-documents.html&quot; title=&quot;Embedded documents are documents with schemas of their own that are part of other documents&quot;&gt;embedded documents&lt;/a&gt; that come with &lt;a href=&quot;http://mongoosejs.com/&quot; title=&quot;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&quot;&gt;mongoose&lt;/a&gt;, I didn't add the price yet which should be set on a combination of color and size.&lt;/p&gt;

&lt;p&gt;To use the model I created a variable &lt;code&gt;ProductModel&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var ProductModel = mongoose.model('Product', Product);  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I can add the CRUD methods:&lt;/p&gt;

&lt;h5&gt;READ a List of Products&lt;/h5&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;added to app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;h5&gt;CREATE a Single Product&lt;/h5&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;added to app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;POST: &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;created&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;h5&gt;READ a Single Product by ID&lt;/h5&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;added to app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products/:id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;h5&gt;UPDATE a Single Product by ID&lt;/h5&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;added to app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products/:id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;updated&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;h5&gt;DELETE a Single Product by ID&lt;/h5&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;added to app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products/:id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;removed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;&lt;em&gt;NOTE: To exit your running app.js job, press &lt;code&gt;control-c&lt;/code&gt; then re-start your updated app.js using the same command as before: node app.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the new &lt;strong&gt;product model&lt;/strong&gt; and &lt;strong&gt;CRUD methods&lt;/strong&gt; serving up a RESTful service at &lt;em&gt;http://localhost:4242/api&lt;/em&gt; I can utilize the index.html (with jQuery)... and in my browser's console I can fiddle with my new Web service using jQuery's AJAX methods. Specifically, by loading http://localhost:4242/ and executing commands in the JavaScript console I can using ($.ajax) POST to create a new product.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;post.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Awesome T-shirt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;All about the details. Of course it&amp;#39;s black.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;style&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;12345&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Post resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;The post response is something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;_id: &quot;4f34d8e7f05ebf212b000004&quot;  
description: &quot;All about the details. Of course it's black.&quot;  
modified: &quot;2012-02-10T08:44:23.372Z&quot;  
style: &quot;12345&quot;  
title: &quot;My Awesome T-shirt&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;_id&lt;/code&gt; property was added automatically, this value can be used to UPDATE, READ, or DELETE the record. Notice all the &lt;code&gt;console.log()&lt;/code&gt; and &lt;code&gt;console.dir()&lt;/code&gt; calls I added within the anonymous functions' '&lt;em&gt;success&lt;/em&gt;' callbacks. With the logging in place, I can inspect the server's response in the console or by viewing the responses on in network tab of my browser's developer tools.&lt;/p&gt;

&lt;p&gt;To READ the product data I just created, I execute the following code in my browser's JavaScript console:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;get.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Get resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;The above GET request reads &lt;em&gt;all products&lt;/em&gt;; to read a specific product add the ID to the URL like so:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;get.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products/4f34d8e7f05ebf212b000004&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Get resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;To test the UPDATE request use PUT:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;update.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products/4f34d8e7f05ebf212b000004&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;PUT&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Awesome T-shirt in Black&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;All about the details. Of course it&amp;#39;s black, and long sleeve&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;style&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;12345&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Post resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;The above code is about the same as the the previous code I used to create the product document and store in MongoDB. However, I appended the product's description with the text: 'black, and long sleeve'.&lt;/p&gt;

&lt;p&gt;Now, when I get the product by ID, I see the updated text added to the product description:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;jQuery.get(&quot;/api/products/4f34d8e7f05ebf212b000004&quot;);  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or I can visit : http://localhost:4242/api/products/4f34d8e7f05ebf212b000004 to see the text response only.&lt;/p&gt;

&lt;p&gt;I can also DELETE the product:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;jQuery.ajax({
    url: &quot;/api/products/4f34d8e7f05ebf212b000004&quot;, 
    type: &quot;DELETE&quot;,
    success: function (data, textStatus, jqXHR) { 
        console.log(&quot;Post resposne:&quot;); 
        console.dir(data); 
        console.log(textStatus); 
        console.dir(jqXHR); 
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when I load http://localhost:4242/api/products/4f34d8e7f05ebf212b000004 the server response with a &lt;code&gt;null&lt;/code&gt; response&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TIP: I am using a log of console.log() and console.dir() calls within the success (anonymous) functions to view the responses from the server.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;Embedded Documents for the Remaining Product Attributes&lt;/h4&gt;

&lt;p&gt;I am now adding a few items to the product model: &lt;em&gt;images, categories, catalogs, variants&lt;/em&gt;. A t-shirt product may have many variants with size and color options; the pricing should be configured by the combination of: the selected size option which belongs to a selected color option. The product may belong one or more product catalogs, and also should have one or more associated categories.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;model.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Product Model&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;categories&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;catalogs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Catalogs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;variants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Variants&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;The &lt;a href=&quot;http://mongoosejs.com/docs/embedded-documents.html&quot; title=&quot;Embedded documents are documents with schemas of their own that are part of other documents&quot;&gt;embedded documents&lt;/a&gt; are in square brackets (above) in the product model. I referenced the &lt;a href=&quot;http://mongoosejs.com/&quot; title=&quot;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&quot;&gt;Mongoose&lt;/a&gt; documentation to learn how to assemble this model with embedded documents.&lt;/p&gt;

&lt;p&gt;Below are the schema assignments that together assemble the product document to store in MongoDB. My strategy is adding one embedded document at time and updating each the CREATE and UPDATE methods, stopping and restarting the application (&lt;code&gt;control-c&lt;/code&gt; then &lt;code&gt;node app.js&lt;/code&gt;) with each iteration. And working out the additional code by fiddling with the same jQuery &lt;code&gt;$.ajax&lt;/code&gt; requests, but also adding the single attribute(s) added to the &lt;code&gt;post&lt;/code&gt; data to create a new product document in the db.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;schemas.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Schemas&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Sizes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;available&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;sku&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/[a-zA-Z0-9]/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Product sku should only have letters and numbers&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;thumbnail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;catalog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;detail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;zoom&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Variants&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Categories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Catalogs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;For example, I first added the &lt;code&gt;[Images]&lt;/code&gt; embedded docuemnt to my product model and tested out the application by updated the AJAX post which creates the product using the same post as before but with an array of objects with the image attributes for &lt;code&gt;kind&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt;, see below:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;model.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Schema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;I also updated the CREATE &lt;em&gt;(POST)&lt;/em&gt; and UPDATE &lt;em&gt;(PUT)&lt;/em&gt; methods, adding the references to the images attribute (an embedded document) of the product model.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;create.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// CREATE a product&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;POST: &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;created&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;




&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;update.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// UPDATE a single product&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products/:id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;updated&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;Then I worked out the adding the image(s) data to my post that creates a product in the database; addming the images data array with an object like so:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;post.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Awesome T-shirt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;All about the details. Of course it&amp;#39;s black.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;style&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1234&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/main.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Post resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;On my first of attempt of adding multiple documents to the product model, I did get errors and the server's create action failed. However, my terminal (shell) does report the errors - the app.js file uses the code &lt;code&gt;app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));&lt;/code&gt; to setup the display of errors on the command line. Also, I added some console.log calls in the post action to log the request pluse notes on the execution of saving the document. On both the browser and on the command line, all the logging indicates whether I am building the product model (using Mongoose) properly. This attempt to add the images did not save. I am not sure why, but I switched over to adding a [Categories] embedded docuemnt, then worked my way toward a completed product model with an API to CREATE, UPDATE and DELETE a single product at a time and to READ a single product or list of products in an array.&lt;/p&gt;

&lt;p&gt;After debugging the embedded documents I added for the product models attribtues... now I can create the complete product in a post:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;post.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;span class='line'&gt;36&lt;/span&gt;
&lt;span class='line'&gt;37&lt;/span&gt;
&lt;span class='line'&gt;38&lt;/span&gt;
&lt;span class='line'&gt;39&lt;/span&gt;
&lt;span class='line'&gt;40&lt;/span&gt;
&lt;span class='line'&gt;41&lt;/span&gt;
&lt;span class='line'&gt;42&lt;/span&gt;
&lt;span class='line'&gt;43&lt;/span&gt;
&lt;span class='line'&gt;44&lt;/span&gt;
&lt;span class='line'&gt;45&lt;/span&gt;
&lt;span class='line'&gt;46&lt;/span&gt;
&lt;span class='line'&gt;47&lt;/span&gt;
&lt;span class='line'&gt;48&lt;/span&gt;
&lt;span class='line'&gt;49&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/api/products&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;title&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Awesome T-shirt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;All about the details. Of course it&amp;#39;s black.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/main.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;categories&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Clothes&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Shirts&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;style&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1234&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;variants&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;color&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Black&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;thumbnail&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/thumbnail.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;kind&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;catalog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;images/products/1234/black.jpg&amp;quot;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;s2&quot;&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;S&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;available&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;sku&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CAT-1234-Blk-S&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;price&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;99.99&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;M&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;available&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;sku&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CAT-1234-Blk-M&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;          &lt;span class=&quot;s2&quot;&gt;&amp;quot;price&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;109.99&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;catalogs&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Apparel&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Post resposne:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jqXHR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;And from the node console (shell) I get this output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;POST:  
{ title: 'My Awesome T-shirt',  
  description: 'All about the details. Of course it\'s black.',  
  images: [ { kind: 'thumbnail', url: 'images/products/1234/main.jpg' } ],  
  categories: [ { name: 'Clothes' }, { name: 'Shirts' } ],  
  style: '1234',  
  varients: [ { color: 'Black', images: [Object], sizes: [Object] } ],  
  catalogs: [ { name: 'Apparel' } ] }  
validate style  
1234  
validate description  
All about the details. Of course it's black.  
validate title  
My Awesome T-shirt  
created  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In my browser this looks like these two screenshot:&lt;/p&gt;

&lt;p&gt;Ready to post using the console...&lt;/p&gt;

&lt;p&gt;&lt;img class='' src='http://pixelhandler.com/images/products-post.png' width='' height='' alt=''jQuery Post using console' 'jQUery post in console'' title=''jQuery Post using console' 'jQUery post in console''&gt;&lt;/p&gt;

&lt;p&gt;Server response in the network tab...&lt;/p&gt;

&lt;p&gt;&lt;img class='' src='http://pixelhandler.com/images/server-response.png' width='' height='' alt=''Server response' 'network tab in browser'' title=''Server response' 'network tab in browser''&gt;&lt;/p&gt;

&lt;h4&gt;Bulk Actions for UPDATE and DELETE&lt;/h4&gt;

&lt;p&gt;Finally to finish up the actions needed in the design for the products web service I added the &lt;strong&gt;bulk&lt;/strong&gt; actions to remove all products at once and also to update many products in a PUT request.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;bulk delete app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;removed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;      &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;




&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;bulk update app.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;is Array req.body.products&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PUT: (products)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;UPDATE product by id:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;            &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;nx&quot;&gt;ProductModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;numAffected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;                &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Error on update&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;                &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;                &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;updated num: &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;numAffected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;See the &lt;a href=&quot;https://gist.github.com/1791080&quot; title=&quot;Develop a RESTful API Using Node.js With Express and Mongoose&quot;&gt;Gist&lt;/a&gt; links that follow for sample scripts to create many products (fixtures) and also the bulk update with single AJAX PUT request.&lt;/p&gt;

&lt;h3&gt;The app.js, index.html and jQuery AJAX snippets developed in this tutorial&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Source Code for This Tutorial is on GitHub as a Gist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/1791080&quot; title=&quot;Develop a RESTful API Using Node.js With Express and Mongoose&quot;&gt;Develop a RESTful API Using Node.js With Express and Mongoose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/1791080#file_fixtures.js&quot; title=&quot;Fixtures - example AJAX posts to create products&quot;&gt;Fixtures - example AJAX posts to create products&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/1791080#file_bulk_updates.js&quot; title=&quot;Sample script for bulk update of products&quot;&gt;Sample script for bulk update of products&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The application file:&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1791080.js?file=app.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;var application_root = __dirname,
    express = require(&amp;quot;express&amp;quot;),
    path = require(&amp;quot;path&amp;quot;),
    mongoose = require('mongoose');

var app = express.createServer();

// database

mongoose.connect('mongodb://localhost/ecomm_database');

// config

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(application_root, &amp;quot;public&amp;quot;)));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

var Schema = mongoose.Schema; //Schema.ObjectId

// Schemas

var Sizes = new Schema({
    size: { type: String, required: true },
    available: { type: Number, required: true, min: 0, max: 1000 },
    sku: { 
        type: String, 
        required: true, 
        validate: [/[a-zA-Z0-9]/, 'Product sku should only have letters and numbers']
    },
    price: { type: Number, required: true, min: 0 }
});

var Images = new Schema({
    kind: { 
        type: String, 
        enum: ['thumbnail', 'catalog', 'detail', 'zoom'],
        required: true
    },
    url: { type: String, required: true }
});

var Variants = new Schema({
    color: String,
    images: [Images],
    sizes: [Sizes]
});

var Categories = new Schema({
    name: String
});

var Catalogs = new Schema({
    name: String
});

// Product Model

var Product = new Schema({
    title: { type: String, required: true },
    description: { type: String, required: true },
    style: { type: String, unique: true },
    images: [Images],
    categories: [Categories],
    catalogs: [Catalogs],
    variants: [Variants],
    modified: { type: Date, default: Date.now }
});

// validation

Product.path('title').validate(function (v) {
    console.log(&amp;quot;validate title&amp;quot;);
    console.log(v);
    return v.length &amp;gt; 10 &amp;amp;&amp;amp; v.length &amp;lt; 70;
});

Product.path('style').validate(function (v) {
    console.log(&amp;quot;validate style&amp;quot;);
    console.log(v);
    return v.length &amp;lt; 40;
}, 'Product style attribute is should be less than 40 characters');

Product.path('description').validate(function (v) {
    console.log(&amp;quot;validate description&amp;quot;);
    console.log(v);
    return v.length &amp;gt; 10;
}, 'Product description should be more than 10 characters');

var ProductModel = mongoose.model('Product', Product);

/* Product Document 
[
{  
  &amp;quot;title&amp;quot;: &amp;quot;My Awesome T-shirt&amp;quot;,  
  &amp;quot;description&amp;quot;: &amp;quot;All about the details. Of course it's black.&amp;quot;,  
  &amp;quot;images&amp;quot;: [  
    {  
      &amp;quot;kind&amp;quot;: &amp;quot;thumbnail&amp;quot;,  
      &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/main.jpg&amp;quot;  
    }  
  ],  
  &amp;quot;categories&amp;quot;: [  
      { &amp;quot;name&amp;quot;: &amp;quot;Clothes&amp;quot; },  
      { &amp;quot;name&amp;quot;: &amp;quot;Shirts&amp;quot; }  
  ],  
  &amp;quot;style&amp;quot;: &amp;quot;1234&amp;quot;,  
  &amp;quot;variants&amp;quot;: [  
    {  
      &amp;quot;color&amp;quot;: &amp;quot;Black&amp;quot;,  
      &amp;quot;images&amp;quot;: [  
        {  
          &amp;quot;kind&amp;quot;: &amp;quot;thumbnail&amp;quot;,  
          &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/thumbnail.jpg&amp;quot;  
        },  
        {  
          &amp;quot;kind&amp;quot;: &amp;quot;catalog&amp;quot;,  
          &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/black.jpg&amp;quot;  
        }  
      ],  
      &amp;quot;sizes&amp;quot;: [  
        {  
          &amp;quot;size&amp;quot;: &amp;quot;S&amp;quot;,  
          &amp;quot;available&amp;quot;: 10,  
          &amp;quot;sku&amp;quot;: &amp;quot;CAT-1234-Blk-S&amp;quot;,  
          &amp;quot;price&amp;quot;: 99.99  
        },  
        {  
          &amp;quot;size&amp;quot;: &amp;quot;M&amp;quot;,  
          &amp;quot;available&amp;quot;: 7,  
          &amp;quot;sku&amp;quot;: &amp;quot;CAT-1234-Blk-M&amp;quot;,  
          &amp;quot;price&amp;quot;: 109.99  
        }  
      ]  
    }  
  ],  
  &amp;quot;catalogs&amp;quot;: [  
      { &amp;quot;name&amp;quot;: &amp;quot;Apparel&amp;quot; }  
  ]  
}
]
*/


// REST api

app.get('/api', function (req, res) {
  res.send('Ecomm API is running');
});

// POST to CREATE
app.post('/api/products', function (req, res) {
  var product;
  console.log(&amp;quot;POST: &amp;quot;);
  console.log(req.body);
  product = new ProductModel({
    title: req.body.title,
    description: req.body.description,
    style: req.body.style,
    images: req.body.images,
    categories: req.body.categories,
    catalogs: req.body.catalogs,
    variants: req.body.variants
  });
  product.save(function (err) {
    if (!err) {
      return console.log(&amp;quot;created&amp;quot;);
    } else {
      return console.log(err);
    }
  });
  return res.send(product);
});

// PUT to UPDATE
app.put('/api/products/:id', function (req, res) {
  return ProductModel.findById(req.params.id, function (err, product) {
    product.title = req.body.title;
    product.description = req.body.description;
    product.style = req.body.style;
    product.images = req.body.images;
    product.categories = req.body.categories;
    product.catalogs = req.body.catalogs;
    product.variants = req.body.variants;
    return product.save(function (err) {
      if (!err) {
        console.log(&amp;quot;updated&amp;quot;);
      } else {
        console.log(err);
      }
      return res.send(product);
    });
  });
});

// GET to READ
app.get('/api/products', function (req, res) {
  return ProductModel.find(function (err, products) {
    if (!err) {
      return res.send(products);
    } else {
      return console.log(err);
    }
  });
});

app.get('/api/products/:id', function (req, res) {
  return ProductModel.findById(req.params.id, function (err, product) {
    if (!err) {
      return res.send(product);
    } else {
      return console.log(err);
    }
  });
});

// DELETE to DESTROY
app.delete('/api/products/:id', function (req, res) {
  return ProductModel.findById(req.params.id, function (err, product) {
    return product.remove(function (err) {
      if (!err) {
        console.log(&amp;quot;removed&amp;quot;);
        return res.send('');
      } else {
        console.log(err);
      }
    });
  });
});


// launch server

app.listen(4242);
&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;Also in the app.js gist (above), I added code to validate the product model using Mongoose.&lt;/p&gt;

&lt;p&gt;The index file (inside /public directory):&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1791080.js?file=index.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;API index&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;section&amp;gt;
      &amp;lt;h1&amp;gt;Nouns...&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;
        /products&amp;lt;br&amp;gt;
        /products/:id
      &amp;lt;/p&amp;gt;
    &amp;lt;/section&amp;gt;
    &amp;lt;script src=&amp;quot;http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;Some jQuery AJAX snippets to fiddle with the API:&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1791080.js?file=snippets.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// jQuery snippets used in the console to use the REST api created with app.js

// CREATE

jQuery.post(&amp;quot;/api/products&amp;quot;, {
  &amp;quot;title&amp;quot;: &amp;quot;My Awesome T-shirt&amp;quot;,  
  &amp;quot;description&amp;quot;: &amp;quot;All about the details. Of course it's black.&amp;quot;,  
  &amp;quot;images&amp;quot;: [  
    {  
      &amp;quot;kind&amp;quot;: &amp;quot;thumbnail&amp;quot;,  
      &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/main.jpg&amp;quot;  
    }  
  ],  
  &amp;quot;categories&amp;quot;: [  
      { &amp;quot;name&amp;quot;: &amp;quot;Clothes&amp;quot; },
      { &amp;quot;name&amp;quot;: &amp;quot;Shirts&amp;quot; } 
  ],  
  &amp;quot;style&amp;quot;: &amp;quot;1234&amp;quot;,  
  &amp;quot;variants&amp;quot;: [  
    {  
      &amp;quot;color&amp;quot;: &amp;quot;Black&amp;quot;,  
      &amp;quot;images&amp;quot;: [  
        {  
          &amp;quot;kind&amp;quot;: &amp;quot;thumbnail&amp;quot;,  
          &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/thumbnail.jpg&amp;quot;  
        },
        {  
          &amp;quot;kind&amp;quot;: &amp;quot;catalog&amp;quot;,  
          &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/black.jpg&amp;quot;  
        }  
      ],  
      &amp;quot;sizes&amp;quot;: [  
        {  
          &amp;quot;size&amp;quot;: &amp;quot;S&amp;quot;,  
          &amp;quot;available&amp;quot;: 10,  
          &amp;quot;sku&amp;quot;: &amp;quot;CAT-1234-Blk-S&amp;quot;,  
          &amp;quot;price&amp;quot;: 99.99  
        },
        {
          &amp;quot;size&amp;quot;: &amp;quot;M&amp;quot;,  
          &amp;quot;available&amp;quot;: 7,  
          &amp;quot;sku&amp;quot;: &amp;quot;CAT-1234-Blk-M&amp;quot;,  
          &amp;quot;price&amp;quot;: 109.99  
        }  
      ]  
    }  
  ],
  &amp;quot;catalogs&amp;quot;: [
      { &amp;quot;name&amp;quot;: &amp;quot;Apparel&amp;quot; }
  ]  
}, function(data, textStatus, jqXHR) { 
    console.log(&amp;quot;Post resposne:&amp;quot;); console.dir(data); console.log(textStatus); console.dir(jqXHR); 
});

// generated a product document with automatically assigned ID, e.g. 4f34734d21289c1c28000007 


// READ

jQuery.get(&amp;quot;/api/products/&amp;quot;, function(data, textStatus, jqXHR) { 
    console.log(&amp;quot;Post resposne:&amp;quot;); 
    console.dir(data); 
    console.log(textStatus); 
    console.dir(jqXHR); 
});

jQuery.get(&amp;quot;/api/products/4f34734d21289c1c28000007&amp;quot;, function(data, textStatus, jqXHR) { 
    console.log(&amp;quot;Post resposne:&amp;quot;); 
    console.dir(data); 
    console.log(textStatus); 
    console.dir(jqXHR); 
});

// UPDATE

jQuery.ajax({
    url: &amp;quot;/api/products/4f34734d21289c1c28000007&amp;quot;, 
    type: &amp;quot;PUT&amp;quot;,
    data: {
      &amp;quot;title&amp;quot;: &amp;quot;My Awesome T-shirt&amp;quot;,  
      &amp;quot;description&amp;quot;: &amp;quot;All about the details. Of course it's black, and longsleeve.&amp;quot;,  
      &amp;quot;images&amp;quot;: [  
        {  
          &amp;quot;kind&amp;quot;: &amp;quot;thumbnail&amp;quot;,  
          &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/main.jpg&amp;quot;  
        }  
      ],  
      &amp;quot;categories&amp;quot;: [  
          { &amp;quot;name&amp;quot;: &amp;quot;Clothes&amp;quot; },
          { &amp;quot;name&amp;quot;: &amp;quot;Shirts&amp;quot; } 
      ],  
      &amp;quot;style&amp;quot;: &amp;quot;1234&amp;quot;,  
      &amp;quot;variants&amp;quot;: [  
        {  
          &amp;quot;color&amp;quot;: &amp;quot;Black&amp;quot;,  
          &amp;quot;images&amp;quot;: [  
            {  
              &amp;quot;kind&amp;quot;: &amp;quot;zoom&amp;quot;,  
              &amp;quot;url&amp;quot;: &amp;quot;images/products/1234/zoom.jpg&amp;quot;  
            }
          ],  
          &amp;quot;sizes&amp;quot;: [  
            {  
              &amp;quot;size&amp;quot;: &amp;quot;L&amp;quot;,  
              &amp;quot;available&amp;quot;: 77,  
              &amp;quot;sku&amp;quot;: &amp;quot;CAT-1234-Blk-L&amp;quot;,  
              &amp;quot;price&amp;quot;: 99.99  
            }
          ]  
        }  
      ],
      &amp;quot;catalogs&amp;quot;: [
          { &amp;quot;name&amp;quot;: &amp;quot;Apparel&amp;quot; }
      ]  
    }, 
    success: function(data, textStatus, jqXHR) { 
        console.log(&amp;quot;PUT resposne:&amp;quot;); 
        console.dir(data); 
        console.log(textStatus); 
        console.dir(jqXHR); 
    }
});

// Delete

jQuery.ajax({url: &amp;quot;/api/products/4f34734d21289c1c28000007&amp;quot;, type: &amp;quot;DELETE&amp;quot;, success: function(data, textStatus, jqXHR) { console.dir(data); }});
&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;h3&gt;Post Hoc&lt;/h3&gt;

&lt;p&gt;This tutorial came about as a desire to develop with a local API. Using a local API, I can develop a client application with Backbone.js and utilize the asynchronous behaviors that come with the API. I am not suggesting that anyone uses this tutorial to build a RESTful API for a production ecommerce application. However, I do advocate developing with a local API rather then just mocking a server without asynchronous interations with JSON data. If you are not working with a RESTful API and are not consuming data using AJAX, in a few hours you can be.&lt;/p&gt;

&lt;p&gt;JavaScript runs in so many applications, and since I already know JavaScript I would rather fiddle with Node.js than build an API for my local development needs in PHP or Ruby. Also, this exercise helps me to understand more about JSON, REST and jQuery AJAX development. Getting to know these technologies and developing solid skills using asynchronous behavior, necessary to build HTML5 apps for desktop and/or mobile browsers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Completing this tutorial will likely take a few hours, even longer if you do not have node and npm running on your development environment.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Reference&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.apigee.com/detail/restful_api_design_nouns_are_good_verbs_are_bad/&quot; title=&quot;API design nouns are good, verbs are bad&quot;&gt;API design nouns are good, verbs are bad.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joyent/node/wiki/Installation&quot; title=&quot;Building and Installing Node.js&quot;&gt;Installing Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://npmjs.org/&quot; title=&quot;npm is a package manager for node.&quot;&gt;npm is a package manager for node.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mongoosejs.com/docs/model-definition.html&quot; title=&quot;Models are defined by passing a Schema instance to mongoose.model&quot;&gt;Models are defined by passing a Schema instance to mongoose.model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mongoosejs.com/docs/schematypes.html&quot; title=&quot;SchemaTypes take care of validation, casting, defaults, and other general options in our models&quot;&gt;SchemaTypes take care of validation, casting, defaults, and other general options in our models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mongoosejs.com/docs/embedded-documents.html&quot; title=&quot;Embedded documents are documents with schemas of their own that are part of other documents&quot;&gt;Embedded documents are documents with schemas of their own that are part of other documents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/addyosmani/backbone-boilerplates&quot; title=&quot;Backbone Todo boilerplates demonstrating integration with Node.js, Express, MongoDB&quot;&gt;Backbone Todo boilerplates demonstrating integration with Node.js, Express, MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mongodb.org/&quot; title=&quot;MongoDB (from 'humongous') - Document-oriented storage&quot;&gt;MongoDB (from 'humongous') - Document-oriented storage&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mongodb.org/display/DOCS/Quickstart&quot; title=&quot;MongoDB Quickstart&quot;&gt;MongoDB Quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mongodb.org/display/DOCS/Tutorial&quot; title=&quot;Try manipulating the Mongo database with the database shell&quot;&gt;Try manipulating the Mongo database with the database shell&lt;/a&gt; or &lt;a href=&quot;http://try.mongodb.org/&quot; title=&quot;MongoDB browser shell&quot;&gt;MongoDB browser shell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mongoosejs.com/&quot; title=&quot;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&quot;&gt;Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://expressjs.com/&quot; title=&quot;High performance, high class Web development for Node.js&quot;&gt;High performance, high class Web development for Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://expressjs.com/guide.html&quot; title=&quot;npm install express&quot;&gt;npm install express&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/addyosmani/backbone-fundamentals#restful&quot; title=&quot;Using Node.js, Express, Mongoose and MongoDB&quot;&gt;Using Node.js, Express, Mongoose and MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Developing a Modular JavaScript Application With RequireJS and Backbone.js</title>
    <link href="http://pixelhandler.com/blog/2012/02/03/developing-a-modular-javascript-application-with-requirejs-and-backbone-js/"/>
    <updated>2012-02-03T00:15:00-08:00</updated>
    <id>http://pixelhandler.com/blog/2012/02/03/developing-a-modular-javascript-application-with-requirejs-and-backbone-js</id>
    <content type="html">&lt;h2&gt;A few reasons I enjoy the JavaScript development community&lt;/h2&gt;

&lt;p&gt;Currently I am developing a JavaScript application using open source frameworks and libraries. Included the mix are... &lt;a href=&quot;http://jquerymobile.com/&quot; title=&quot;jQuery Mobile&quot;&gt;jQuery Mobile&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/underscore/&quot; title=&quot;Underscore.js&quot;&gt;Underscore.js&lt;/a&gt;, &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; title=&quot;Backbone.js&quot;&gt;Backbone.js&lt;/a&gt;, &lt;a href=&quot;http://requirejs.org/&quot; title=&quot;RequireJS&quot;&gt;RequireJS&lt;/a&gt;, &lt;a href=&quot;https://github.com/janl/mustache.js&quot; title=&quot;Mustache.js source code and documentation on github&quot;&gt;mustache.js&lt;/a&gt;, &lt;a href=&quot;http://nodejs.org/&quot; title=&quot;Node.js&quot;&gt;Node.js&lt;/a&gt;, &lt;a href=&quot;http://pivotal.github.com/jasmine/&quot; title=&quot;Jasmine is a behavior-driven development framework for testing your JavaScript code&quot;&gt;Jasmine&lt;/a&gt;, &lt;a href=&quot;http://sinonjs.org/&quot; title=&quot;Sinon.JS&quot;&gt;Sinon.JS&lt;/a&gt;, &lt;a href=&quot;https://github.com/velesin/jasmine-jquery&quot; title=&quot;jQuery matchers and fixture loader for Jasmine framework&quot;&gt;Jasmine-jQuery&lt;/a&gt;,  and the &lt;a href=&quot;https://github.com/amdjs/amdjs-api/wiki/AMD&quot; title=&quot;Asynchronous Module Definition (AMD)&quot;&gt;Asynchronous Module Definition (AMD)&lt;/a&gt; specification. The web application is backed with a RESTful API. So, in researching on all the JavaScript based MVC type of frameworks, comparing &lt;a href=&quot;http://knockoutjs.com/&quot; title=&quot;Knockout&quot;&gt;Knockout&lt;/a&gt;, &lt;a href=&quot;http://emberjs.com/&quot; title=&quot;Ember.js&quot;&gt;Ember.js&lt;/a&gt; (Sproutcore 2), &lt;a href=&quot;http://javascriptmvc.com/&quot; title=&quot;JavaScript MVC&quot;&gt;JavaScript MVC&lt;/a&gt;, and &lt;strong&gt;Backbone.js&lt;/strong&gt; I ended up selecting Backbone as my first choice. The community of developers using Backbone appears very active, there are plenty of blog posts, articles, tutorials, and videos on how to author code using Backbone.&lt;/p&gt;

&lt;p&gt;I find it refreshing that many of these libraries have a fair amount of adoption within the development community. One of the primary objectives on this project is to build the application with modular code. Also to load modules when the specific components are needed for execution rather than the entire library which becomes the finish application. The AMD specification and the compatibility with RequireJS and other libraries is very attractive. RequireJS gives me the ability to author various modules and manage the code dependencies efficiently. Also with the build and optimization features of RequireJS I am able to organize the modules within packages. I broke down the file organization by having common directories for models, views, collections (objects defined using Backbone) and a few other directories, like syncs, utils to extend the functionality of Backbone. The modules in each directory are built into a single common package of modules and the package can be required by other modules which reside in other packages (groups of code for specific feature/component implementation, e.g. site chrome). I forked an open source book &lt;a href=&quot;https://github.com/pixelhandler/backbone-fundamentals&quot; title=&quot;Backbone.js Fundamentals&quot;&gt;Backbone.js Fundamentals&lt;/a&gt; on these topics adding an explanation on how I am building and optimizing using packages of modules; see the section &quot;Optimize and Build a Backbone JavaScript application with Require.JS using Packages&quot;. I posted this section on the &lt;a href=&quot;http://www.hautelooktech.com/2012/02/01/optimize-and-build-a-backbone-js-javascript-application-with-require-js-using-packages/&quot; title=&quot;Optimize and Build a Backbone.js JavaScript application with Require.JS using Packages&quot;&gt;HauteLookTech.com blog&lt;/a&gt; as well.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;After spending a few weeks during code freeze at work and trying out all these libraries we began development for a mobile application. In an effort to rapidly prototype the web application I began to build with &lt;a href=&quot;http://jquerymobile.com/demos/1.0.1/docs/about/getting-started.html&quot; title=&quot;Getting started with jQuery Mobile&quot;&gt;jQuery Mobile&lt;/a&gt;. This gave our team common components that work across a wide range of devices without overloading us with testing. Also the theme roller for jQuery Mobile is a handy tool for the building a base skin for the mobile site. With only a few sketches and by generating a mobile theme that looked very &lt;em&gt;blueprint-ish&lt;/em&gt; we began authoring a site prototype to work out the features and components that should be included in the mobile site application. Since the site framework is built with Backbone we will not use the jQuery Mobile routing features; however for the prototype this mobile framework was very handy right out of the box. Recently there have been many talks and articles on the concept of &lt;strong&gt;&quot;mobile first&quot;&lt;/strong&gt;, basically the small screen helps to define what really matters and helps to put usability as a high priority. This ends up striking a nice balance between identifying requirements for design, usability and the application's functionality. Using the logic-less template library, Mustache to render JSON from the web service layer is much funner than all kinds of crazy DOM fragment manipulation to render data. I found a great tutorial post on using &lt;a href=&quot;http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/&quot; title=&quot;Tutorial: HTML Templates with Mustache.js&quot;&gt;HTML Templates with Mustache.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am developing the framework based on Backbone.js which has the dependency of the Underscore.js library - a very robust set of tools that complement Backbone, especially with filtering collections. Also, Backbone needs either jQuery or Zepto, I am content with jQuery. The Deferred and Callbacks objects in the current version of jQuery also help to manage asynchronous behaviors of the components within the framework. For example, I can add a Deferred object to a collection and within a view object only render after the resolution of the deferred property of the required collection object. The Callbacks object comes in handy using a view object that programmatically renders partial templates based on various child views, I can iterate over options passed to a view and define child views based on the options, then add to the (parent) view object's render method callbacks to render the child views. Though Backbone does not provide (out of the box) a collection view; there are good solutions posted online. So, when I need to program some behavior that is not included in Backbone, I often discover good solutions online that I can borrow from. For me, the bottom line is that Backbone gives common patterns for developing a data-driven application backed by a RESTful API and is very extendable. Backbone does not box me in, yet is fairly straight forward for me to build on top of, also giving solid structure to the components I need in developing a modular application.&lt;/p&gt;

&lt;p&gt;About modular code, which JavaScript does not currently provide a standard, there are plenty of patterns you can use. For me &lt;a href=&quot;http://requirejs.org/docs/whyamd.html&quot; title=&quot;use of the Asynchronous Module Definition (AMD) API for JavaScript modules&quot;&gt;AMD&lt;/a&gt; is just fine. Even though a future standard my be different than the way AMD operates, the API fits well into current libraries. One thing I notice is that when there is a need for some functionality in JavaScript many solutions pop up in the community; which is great. However, it would be nice if developers find a good solution and adopt it; it would seem that more adoption and development using the ‘good’ solution would lead to the said solution becoming &lt;em&gt;even better&lt;/em&gt; or &lt;em&gt;great&lt;/em&gt; and the use of the solution would become easier for other developers to adopt and implement. AMD is a good solution for &lt;a href=&quot;http://requirejs.org/docs/why.html&quot; title=&quot;why modules on the web are useful&quot;&gt;modules using RequireJS&lt;/a&gt;, some would argue &lt;em&gt;‘the’&lt;/em&gt; solution. For now, it is a viable solution and I’m using it. The Group for AMD JS Module API has forks for AMD compatible versions of &lt;a href=&quot;https://github.com/amdjs/backbone&quot; title=&quot;forked from documentcloud/backbone&quot;&gt;Backbone.js&lt;/a&gt; and &lt;a href=&quot;https://github.com/amdjs/underscore&quot; title=&quot;forked from documentcloud/underscore&quot;&gt;Underscore.js&lt;/a&gt; libraries.&lt;/p&gt;

&lt;p&gt;Perhaps the most enjoyment I find in JavaScript development with this mix of libraries is the discovery of a solution based on using &lt;a href=&quot;http://dannorth.net/introducing-bdd/&quot; title=&quot;Introducing BDD&quot;&gt;behavior-driven development (BDD)&lt;/a&gt; methodologies; and of course discovering though this &lt;em&gt;lather, rinse, repeat&lt;/em&gt; (test-driven development) practice. The combination of &lt;a href=&quot;http://pivotal.github.com/jasmine/&quot; title=&quot;Jasmine is a behavior-driven development framework for testing your JavaScript code&quot;&gt;Jasmine&lt;/a&gt;, &lt;a href=&quot;https://github.com/velesin/jasmine-jquery&quot; title=&quot;jQuery matchers and fixture loader for Jasmine framework&quot;&gt;jQuery-Jasmin&lt;/a&gt; and &lt;a href=&quot;http://sinonjs.org/&quot; title=&quot;Sinon.JS&quot;&gt;Sinon.JS&lt;/a&gt; testing libraries is powerful to say the least. I really enjoy getting from red to green, in passing the tests. I find that sometimes the hardest part is to guess what exactly will prove the solution yet to be discovered. This development approach helps to break down a solution by proving the expected behavior with simpler units of behavior which can be tested and verified independently from the application itself. Sinon.JS provides an nice and &lt;a href=&quot;http://sinonjs.org/docs/#server&quot; title=&quot;Fake XMLHttpRequest&quot;&gt;fake XHR server&lt;/a&gt; for &lt;a href=&quot;http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html&quot; title=&quot;Testing Backbone applications with Jasmine and Sinon&quot;&gt;testing Backbone.js applications&lt;/a&gt;. Jasmine has &lt;a href=&quot;https://github.com/pivotal/jasmine/wiki/Spies&quot; title=&quot;A 'spy' replaces the function it is spying on&quot;&gt;spies&lt;/a&gt; which replace a function that it is spying on, and Jasmine-jQuery adds the sweetness of fixtures, jQuery based matchers and event spies to complete a solid suite for a front-end developer to embrace the process of test-driven development. It is very nice to execute the tests on various mobile devices during development to ensure cross platform/device compatibility.&lt;/p&gt;

&lt;p&gt;Node.js came in very handy in authoring a shell script to prep and build using the &lt;a href=&quot;http://requirejs.org/docs/optimization.html&quot; title=&quot;RequireJS Optimizer&quot;&gt;r.js optimizer&lt;/a&gt;. I needed to have a site that can be hosted in a cloud environment with out any server-side script execution. So adding to the RequireJS optimizer script I added a release script to modify my build.js and index.html files to utilize a specified build directory. And, node is just cool, right?&lt;/p&gt;

&lt;p&gt;I would like tell an anecdote from my youth to summarize the experience I have using this combination of JavaScript libraries and frameworks. When I was a kid I loved wearing Docs (Dr. Martens). These are warehouse style boots with air-cushioned soles (dubbed &lt;strong&gt;Bouncing Soles&lt;/strong&gt;). A kid I knew wrote a song, &quot;I can climb mountains, I can climb rocks, I can do anything when I wear my Docs.&quot; These bouncing soles give a sense of invincibility to a young man full of spit and well you know. I feel the same way when developing with Backbone, Underscore, Node.js, AMD, Jasmine, jQuery and RequireJS. Perhaps I should write a song, &quot;I can pass my specs, I can mock my requests, I can build anything with Backbone, Underscore, jQuery and RequireJS&quot;. On second thought, I'll spare you the pain of my lack of musical talent. to wrap it up happy developer build awesome stuff, and these group of libraries and the community behind them makes me a kick-xxx happy developer, seriously.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Use Newer jQuery Features When Your App Is Stuck on Older Version</title>
    <link href="http://pixelhandler.com/blog/2011/10/08/use-newer-jquery-features-when-your-app-is-stuck-on-older-version/"/>
    <updated>2011-10-08T17:46:00-07:00</updated>
    <id>http://pixelhandler.com/blog/2011/10/08/use-newer-jquery-features-when-your-app-is-stuck-on-older-version</id>
    <content type="html">&lt;h2&gt;So, your app only uses a certain version of jQuery from last year sometime, e.g. v 1.4.2&lt;/h2&gt;

&lt;p&gt;Not a problem, you can add in the newer features you need by copying form the source and defining any dependencies used by the newer code, also copied from the source. &lt;em&gt;Use the Source, Luke&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This example shows how to add $.Deferred and the jQuery promise methods to your app which is still using version 1.4.2; perhaps some mission critical plugin or other code is preventing you from an upgrade to the lasted jQuery release.&lt;/p&gt;

&lt;h3&gt;Links on the topic of Deferreds / Promises&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://api.jquery.com/jQuery.ajax/&quot;&gt;http://api.jquery.com/jQuery.ajax/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/scriptjunkie/gg723713&quot;&gt;http://msdn.microsoft.com/en-us/scriptjunkie/gg723713&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://quickleft.com/blog/jquery-15-hotness-part-2&quot;&gt;http://quickleft.com/blog/jquery-15-hotness-part-2&lt;/a&gt; | &lt;a href=&quot;https://gist.github.com/862567&quot;&gt;https://gist.github.com/862567&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/&quot;&gt;http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Short explanation&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You really want to use jQuery methods : $.Deferred() .promise() .done() .fail() .isResolved() .isRejected() .then() .always() .pipe() .when()&lt;/li&gt;
&lt;li&gt;You may be using a service to get some data e.g. via .ajax()&lt;/li&gt;
&lt;li&gt;You need both ajax actions to complete (with success) then your code responds after both actions are done.&lt;/li&gt;
&lt;li&gt;See Gists below ... &lt;a href=&quot;https://gist.github.com/1273143&quot;&gt;https://gist.github.com/1273143&lt;/a&gt; | &lt;a href=&quot;https://gist.github.com/1273133&quot;&gt;https://gist.github.com/1273133&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;See working example at&lt;/strong&gt; : &lt;a href=&quot;http://pixelhandler.com/downloads/code/deferred-promise/&quot;&gt;http://pixelhandler.com/downloads/code/deferred-promise/&lt;/a&gt;&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;Gists ...&lt;/h2&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1273143.js?file=deferred-promise.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!docType html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Deferred / Promise&amp;lt;/title&amp;gt;
  &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
  &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=edge,chrome=1&amp;quot;&amp;gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery-1.6.4-promises.js&amp;quot;&amp;gt;// get script at https://gist.github.com/1273133 &amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Deferred / Promise Example using jQuery 1.4.2 by adding implementation in newer version&amp;lt;/h1&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;

(function($){ // IIFE ...
  
$(function(){ // doc ready ...
  
  // Code below borrowed from ...
  //    Deferreds post : http://quickleft.com/blog/jquery-15-hotness-part-2
  //    Code : https://gist.github.com/862567

  var container = $( &amp;quot;&amp;lt;div/&amp;gt;&amp;quot; ).appendTo( document.body );

  // List of resources we want to load
  var things = [
    {
      url: &amp;quot;/downloads/code/deferred-promise/services/?type=XML&amp;quot;,
      data_type: &amp;quot;xml&amp;quot;,
      name: &amp;quot;Products XML&amp;quot;
    },
    {
      url: &amp;quot;/downloads/code/deferred-promise/services/?type=JSON&amp;quot;,
      data_type: &amp;quot;json&amp;quot;,
      name: &amp;quot;Products JSON&amp;quot;
    }
  ];

  // Container to hold our promises
  var promises = [];

  function getSomething(thing){

    // Create our deferred
    var dfd = $.Deferred();

    // - Make a request and resolve our deferred onSuccess
    // - You can get super fancy here with $.ajax and explicitly
    //   set fail or rejected states
    $.get(
      thing.url,
      function() { dfd.resolve(); },
      thing.data_type
    );

    // We return a promise so we can watch it for a resolution
    return dfd.promise();

  }

  // Iterate through our requests
  $.each( things, function(_, thing){
    // - Each getSomething() call will return a promise, so let's
    //   push them into our promises array
    promises.push( getSomething(thing).done(function(){
      // - This is an inline done() handler which will fire when
      //   the individual promise is resolved
      container.append( '&amp;lt;p&amp;gt;Loaded ' + thing.name  + '.&amp;lt;/p&amp;gt;' );
      // - You could string other handlers like fail() after this
      //   if you want to try a broken link or other situation
    }) );
  });

  // We can even wait a bit before we handle our promises.
  // If they have already been resolved, jQuery will remember!
  setTimeout(function(){

    // Apply entire array of promises to a $.when listener
    $.when.apply( null,  promises ).then(function(){
      // All promises have been resolved :)
      container.append( '&amp;lt;p class=&amp;quot;green&amp;quot;&amp;gt;Finished loading All Files!&amp;lt;/p&amp;gt;' );
    });

  }, 5000);

}); // end ready

}(jQuery)); // end IIFE

&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Uses code from:&lt;/strong&gt;&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/1273133.js?file=jquery-1.6.4-promises.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;(function($){

    var // Promise methods
        promiseMethods = &amp;quot;done fail isResolved isRejected promise then always pipe&amp;quot;.split( &amp;quot; &amp;quot; ),
        // Static reference to slice
        sliceDeferred = [].slice;

    if (typeof $ !== 'function') {
        return false;
    } else {
        jQuery.each(promiseMethods, function(){
            if (typeof jQuery[this] !== 'undefined') {
                return false;
            }
        });
    }

    // dependencies
    if (typeof jQuery.type === 'undefined') {
        var class2type = {};
        // Populate the class2type map
        jQuery.each(&amp;quot;Boolean Number String Function Array Date RegExp Object&amp;quot;.split(&amp;quot; &amp;quot;), function(i, name) {
            class2type[ &amp;quot;[object &amp;quot; + name + &amp;quot;]&amp;quot; ] = name.toLowerCase();
        });
        jQuery.extend({
            type: function( obj ) {
                return obj == null ?
                    String( obj ) :
                    class2type[ toString.call(obj) ] || &amp;quot;object&amp;quot;;
            }
            // redefine isFunction using type method
            //isFunction: function( obj ) {
            //  return jQuery.type(obj) === &amp;quot;function&amp;quot;;
            //}
        });

    }

    jQuery.extend({
        // Create a simple deferred (one callbacks list)
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i &amp;lt; length; i++ ) {
                                elem = args[ i ];
                                type = jQuery.type( elem );
                                if ( type === &amp;quot;array&amp;quot; ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === &amp;quot;function&amp;quot; ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled &amp;amp;&amp;amp; !fired &amp;amp;&amp;amp; !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },

        // Full fledged deferred (two callbacks list)
        Deferred: function( func ) {
            var deferred = jQuery._Deferred(),
                failDeferred = jQuery._Deferred(),
                promise;
            // Add errorDeferred methods, then and promise
            jQuery.extend( deferred, {
                then: function( doneCallbacks, failCallbacks ) {
                    deferred.done( doneCallbacks ).fail( failCallbacks );
                    return this;
                },
                always: function() {
                    return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
                },
                fail: failDeferred.done,
                rejectWith: failDeferred.resolveWith,
                reject: failDeferred.resolve,
                isRejected: failDeferred.isResolved,
                pipe: function( fnDone, fnFail ) {
                    return jQuery.Deferred(function( newDefer ) {
                        jQuery.each( {
                            done: [ fnDone, &amp;quot;resolve&amp;quot; ],
                            fail: [ fnFail, &amp;quot;reject&amp;quot; ]
                        }, function( handler, data ) {
                            var fn = data[ 0 ],
                                action = data[ 1 ],
                                returned;
                            if ( jQuery.isFunction( fn ) ) {
                                deferred[ handler ](function() {
                                    returned = fn.apply( this, arguments );
                                    if ( returned &amp;amp;&amp;amp; jQuery.isFunction( returned.promise ) ) {
                                        returned.promise().then( newDefer.resolve, newDefer.reject );
                                    } else {
                                        newDefer[ action + &amp;quot;With&amp;quot; ]( this === deferred ? newDefer : this, [ returned ] );
                                    }
                                });
                            } else {
                                deferred[ handler ]( newDefer[ action ] );
                            }
                        });
                    }).promise();
                },
                // Get a promise for this deferred
                // If obj is provided, the promise aspect is added to the object
                promise: function( obj ) {
                    if ( obj == null ) {
                        if ( promise ) {
                            return promise;
                        }
                        promise = obj = {};
                    }
                    var i = promiseMethods.length;
                    while( i-- ) {
                        obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
                    }
                    return obj;
                }
            });
            // Make sure only one callback list will be used
            deferred.done( failDeferred.cancel ).fail( deferred.cancel );
            // Unexpose cancel
            delete deferred.cancel;
            // Call given func if any
            if ( func ) {
                func.call( deferred, deferred );
            }
            return deferred;
        },

        // Deferred helper
        when: function( firstParam ) {
            var args = arguments,
                i = 0,
                length = args.length,
                count = length,
                deferred = length &amp;lt;= 1 &amp;amp;&amp;amp; firstParam &amp;amp;&amp;amp; jQuery.isFunction( firstParam.promise ) ?
                    firstParam :
                    jQuery.Deferred();
            function resolveFunc( i ) {
                return function( value ) {
                    args[ i ] = arguments.length &amp;gt; 1 ? sliceDeferred.call( arguments, 0 ) : value;
                    if ( !( --count ) ) {
                        // Strange bug in FF4:
                        // Values changed onto the arguments object sometimes end up as undefined values
                        // outside the $.when method. Cloning the object into a fresh array solves the issue
                        deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
                    }
                };
            }
            if ( length &amp;gt; 1 ) {
                for( ; i &amp;lt; length; i++ ) {
                    if ( args[ i ] &amp;amp;&amp;amp; jQuery.isFunction( args[ i ].promise ) ) {
                        args[ i ].promise().then( resolveFunc(i), deferred.reject );
                    } else {
                        --count;
                    }
                }
                if ( !count ) {
                    deferred.resolveWith( deferred, args );
                }
            } else if ( deferred !== firstParam ) {
                deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
            }
            return deferred.promise();
        }
    });


}(jQuery));&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>HTML5 Video Package for CMS Using VideoJS</title>
    <link href="http://pixelhandler.com/blog/2011/08/29/html5-video-package-for-cms-using-videojs/"/>
    <updated>2011-08-29T12:01:00-07:00</updated>
    <id>http://pixelhandler.com/blog/2011/08/29/html5-video-package-for-cms-using-videojs</id>
    <content type="html">&lt;h2&gt;Screencast: Demo of HTML5 video used in a CMS block&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;videojs_player package as add-on for &lt;a href=&quot;http://www.concrete5.org/marketplace/addons/&quot; title=&quot;Add-ons page&quot;&gt;Concrete5.org&lt;/a&gt; CMS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The screencast below shows how to use the videojs_player package and also notes the tools used to prepare video for the block.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Screencast Demo&lt;/em&gt;&lt;br/&gt;
&lt;video width='864' height='540' preload='none' controls poster=' /uploads/html5-video-block-demo.png'&gt;&lt;source src='http://pixelhandler.com/uploads/videojs_player_demo.mp4' type='video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;'/&gt;&lt;/video&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Notes:&lt;/em&gt; For info on HTML5 video see : &lt;a href=&quot;http://diveintohtml5.org/video.html&quot;&gt;http://diveintohtml5.org/video.html&lt;/a&gt; which has a tutorial for video conversion for web using the (free) Miro Video Converter. As HTML5 video implementations vary per web browser, to use this block you will need to prepare (4) files: .mp4, .ogv, .webm and have a preview or &quot;poster&quot; image. Also, if needed, Flowplayer (free) plays your .mp4 as flash media content.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CMS Block supports videos playback using the following supporting files&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preview Image: Choose a 'Poster' image, file with a .png or .jpg extension; e.g. still frame from video.&lt;/li&gt;
&lt;li&gt;MPEG 4 (.mp4): Choose a file with a .mp4 extension as common HTML5 video format; also used for flash fallback&lt;/li&gt;
&lt;li&gt;Ogg video (.ogv): Choose a file with a .ogv extension; &quot;Theora&quot; file, HTML5 video format e.g. for FireFox&lt;/li&gt;
&lt;li&gt;WebM video (.webm): Choose a file with a .webm extension; HTML5 video format e.g. for MSIE 9+&lt;/li&gt;
&lt;li&gt;Maximum Dimensions: Input the maximum width and height in pixels&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;em&gt;Links and References:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source code : &lt;a href=&quot;https://github.com/pixelhandler/videojs_player&quot;&gt;https://github.com/pixelhandler/videojs_player&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CMS: &lt;a href=&quot;http://www.concrete5.org/&quot;&gt;http://www.concrete5.org/&lt;/a&gt; | add-on: &lt;a href=&quot;http://www.concrete5.org/marketplace/addons/video-js-player/&quot;&gt;http://www.concrete5.org/marketplace/addons/video-js-player/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;HTML5 video: &lt;a href=&quot;http://diveintohtml5.org/video.html&quot;&gt;http://diveintohtml5.org/video.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Video Converter: &lt;a href=&quot;http://www.mirovideoconverter.com/&quot;&gt;http://www.mirovideoconverter.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VideoJS: JavaScript for HTML5 video player - &lt;a href=&quot;http://videojs.com/&quot;&gt;http://videojs.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Flowplayer free: Flash fallback for playing videos for browsers that do not support &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element - &lt;a href=&quot;http://flowplayer.org/index.html&quot;&gt;http://flowplayer.org/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Alternate location to view tutorial : &lt;a href=&quot;http://www.vimeo.com/28320066&quot;&gt;http://www.vimeo.com/28320066&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>A Few Reasons I Decided to Switch to Octopress (From Wordress)</title>
    <link href="http://pixelhandler.com/blog/2011/08/08/a-few-reasons-i-decided-to-switch-to-octopress-from-wordress/"/>
    <updated>2011-08-08T14:26:00-07:00</updated>
    <id>http://pixelhandler.com/blog/2011/08/08/a-few-reasons-i-decided-to-switch-to-octopress-from-wordress</id>
    <content type="html">&lt;p&gt;Over the weekend I noticed a few coding bloggers had switched to &lt;a href=&quot;http://octopress.org/docs/&quot; title=&quot;Octotopress Docs&quot;&gt;Octopress&lt;/a&gt;. I noticed the advantages for a developer who doesn't need a content management system (CMS) using web forms to update a website. It may sound like I am reverting to the way people blogged 10 years ago with a static HTML website; but is not at all the case. With modern programming tools like...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ruby gems like capistrano for deployment,&lt;/li&gt;
&lt;li&gt;Git (SCM) to manage both the code to generate my site and generated code,&lt;/li&gt;
&lt;li&gt;local development using Ruby to build my now Jekyll powered website,&lt;/li&gt;
&lt;li&gt;and my favorite text editor, TextMate, to generate, edit and preview the content&lt;/li&gt;
&lt;/ul&gt;


&lt;!--more--&gt;


&lt;p&gt;... the choice of leaving WordPress for my personal blog/site and using Octopress (Ruby, Jekyll) and some using handy tools like Git and Capistrano just felt right. And yeah my site is now static HTML, Javascript, CSS and not using any PHP, MySQL, and I like it that way.&lt;/p&gt;

&lt;p&gt;And to boot any other content, or code (e.g. demos, apps) that I choose to add to my site, doesn't need to be part of any CMS and can deploy along site the blog.&lt;/p&gt;

&lt;p&gt;A few other things that just make me happy are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no WordPress updates when a security issues is discovered&lt;/li&gt;
&lt;li&gt;The Octopress plugins are cool: Gist Tag, Render Partial, Github Style codeblock, Category Generator

&lt;ul&gt;
&lt;li&gt;I can include code snippets from a download folder&lt;/li&gt;
&lt;li&gt;Or import a Gist from github.com&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Since the site is generated with rake tasks, resulting in Web standards code (HTML, CSS, Javascript) I can test preview the site on my localhost easily...&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Well that sums up what made me happy about the switch.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>OSX Upgrade to Lion went well, and so far native PHP and MySQL server playing nice</title>
    <link href="http://pixelhandler.com/blog/2011/07/21/osx-upgrade-to-lion-went-well-and-so-far-native-php-and-mysql-server-playing-nice/"/>
    <updated>2011-07-21T09:19:25-07:00</updated>
    <id>http://pixelhandler.com/blog/2011/07/21/osx-upgrade-to-lion-went-well-and-so-far-native-php-and-mysql-server-playing-nice</id>
    <content type="html">Today I upgraded to Lion (was on Snow Leopard). My main concern was that the OSX (native) PHP would break and that MySQL server (community) installation would not be compatible. I found an article on the topic at : &lt;a href=&quot;http://www.september28.co.uk/blog/2011/07/20/fixing-mysql-in-os-x-lion-upgrade/&quot; target=&quot;_blank&quot;&gt;http://www.september28.co.uk/blog/2011/07/20/fixing-mysql-in-os-x-lion-upgrade/&lt;/a&gt; which eased my nerves so I:
&lt;!--more--&gt;

&lt;ol&gt;
	&lt;li&gt;Ran Software Update,&lt;/li&gt;
	&lt;li&gt;backed up with Time Machine,&lt;/li&gt;
	&lt;li&gt;repaired disk permissions,&lt;/li&gt;
	&lt;li&gt;and verified my disk.&lt;/li&gt;
	&lt;li&gt;Then purchased Lion in the app store on my mac.&lt;/li&gt;
	&lt;li&gt;Made a backup of my /private/etc/php.ini file&lt;/li&gt;
	&lt;li&gt;Installed Lion&lt;/li&gt;
	&lt;li&gt;Ran Software Update again, e.g. for Java updates&lt;/li&gt;
&lt;/ol&gt;
Next, I checked my localhost/phpmyadmin and checked my phpinfo.php files. The article 'Fixing mysql in OS X Lion upgrade' (link above) was correct. I needed to:
&lt;ol&gt;
	&lt;li&gt;Place my copy of php.ini back to its original location at /private/etc/php.ini&lt;/li&gt;
	&lt;li&gt;Update the php.ini file to change mysqli setting...
;mysqli.default_socket = /var/mysql/mysql.sock
mysqli.default_socket = /tmp/mysql.sock&lt;/li&gt;
&lt;/ol&gt;
My current LAMP dev projects seem just fine so far. Notes on localhost environment on Lion :
&lt;ul&gt;
	&lt;li&gt;mysql --version
mysql  Ver 14.14 Distrib 5.5.12, for osx10.6 (i386) using readline 5.1&lt;/li&gt;
	&lt;li&gt;php --version
PHP 5.3.6 with Suhosin-Patch (cli) (built: Jun 16 2011 22:26:57)&lt;/li&gt;
	&lt;li&gt;httpd -v
Server version: Apache/2.2.19 (Unix)&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>Wireframing Templates for Magento Commerce with User Experience Notes</title>
    <link href="http://pixelhandler.com/blog/2011/07/13/wireframing-templates-for-magento-commerce-with-user-experience-notes/"/>
    <updated>2011-07-13T04:44:51-07:00</updated>
    <id>http://pixelhandler.com/blog/2011/07/13/wireframing-templates-for-magento-commerce-with-user-experience-notes</id>
    <content type="html">Building an ecommerce site and considering magento commerce as the code base? Well then, I have a treat for you. I've decided to share my &lt;strong&gt;magento commerce wireframes, &lt;/strong&gt;click below to view the PDF and/or download the templates files:
&lt;ol&gt;
	&lt;li&gt;PDF of wireframe templates: &lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes.pdf&quot;&gt;magento-wireframes&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;ZIP of Adobe Illustrator files: &lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes.zip&quot;&gt;magento-wireframes&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
The following is a summary of the annotations that accompany the wireframe templates. These notes can be used to establish/inform your client of the user experience(s) that can be expected from an online store build with magento commerce.
&lt;!--more--&gt;
Surround your pullquote like this {&quot; text to be quoted &quot;}
&lt;h2&gt;&lt;em&gt;Project : Online Storefront&lt;/em&gt;&lt;/h2&gt;
&lt;h3&gt;Page: Home&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-1-e1310555340154.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-827&quot; title=&quot;magento-wireframes-1&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-1-e1310555340154.png&quot; alt=&quot;Magento Wireframe of homepage&quot; width=&quot;579&quot; height=&quot;337&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Presented with multiple options to browse store (targeting various user types) slideshow, featured promotions/banners/products, by category, or by searching. As shopper searches for a product, suggestions result from user input (with search bar). Follows traditional navigation on top to view categories. Interacts with store widgets like mini-cart, recently viewed, search suggestions.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Uses content management tools to update scenes based on marketing objectives, upcoming offerings, categories, etc. Adds graphics for banner promotions and informational badges.

&lt;em&gt;Interactive / Elements: &lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Branding image and top navigation&lt;/li&gt;
	&lt;li&gt;Storefront navigation&lt;/li&gt;
	&lt;li&gt;Search bar with interactive suggestions&lt;/li&gt;
	&lt;li&gt;Interactive slides to promote targeted sections or products&lt;/li&gt;
	&lt;li&gt;Sidebar area to hold blocks for banners, badges and dynamic blocks like, recently viewed and mini-cart&lt;/li&gt;
	&lt;li&gt;Featured category image linked to category pages bundle of products)&lt;/li&gt;
	&lt;li&gt;Featured products (configurable by options or as&lt;/li&gt;
	&lt;li&gt;Footer area, navigation links, copyright, policy, newsletter sign-up etc.&lt;/li&gt;
	&lt;li&gt;CMS structural block for adding promotional content.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: Category / Search Results&lt;/h3&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-2.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-828&quot; title=&quot;magento-wireframes-2&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-2.png&quot; alt=&quot;Magento wireframe of category or search results page&quot; width=&quot;580&quot; height=&quot;340&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-3.png&quot;&gt;&lt;img title=&quot;magento-wireframes-3&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-3.png&quot; alt=&quot;Magento commerce wireframe of category page with quick view layout&quot; width=&quot;570&quot; height=&quot;334&quot; /&gt;&lt;/a&gt;

&lt;strong&gt;Shopper&lt;/strong&gt; - Presented with listing of products within specific categories including filtered navigation allowing user to further limit display to desired category and/or product attributes. Shopper may sort the category list or search results by price and other sortable attributes. The list/search results are paginated. Shopper may add to cart or save to a wish list (creates login to save products). Mini-cart in sidebar is updated when user adds product to cart; also the mini cart is editable so user may remove products as well.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Using back-office tools, organizes product categories and defines attributes based on merchandising objectives. Products may be associated with multiple categories to facilitate various shopping choices.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;

Filtered navigation on category and search results pages. Uses context specific product categories and attributes to help shopper find relevant products.

Mini-cart, interacts with user actions and displays quantity, total amount and mini views of products in cart; user can remove items from cart or click through to view fill shopping cart page.
&lt;ul&gt;
	&lt;li&gt;Product navigation, with breadcrumbs, pagination, sorting options, subscribe to RSS feed.&lt;/li&gt;
	&lt;li&gt;Products rendered in main area and paginated images and titles clickable to details pages.&lt;/li&gt;
	&lt;li&gt;Actions to purchase, add to cart updates mini cart, if configurable with options user is taken to details page.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: Product Details&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-4.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-830&quot; title=&quot;magento-wireframes-4&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-4.png&quot; alt=&quot;Magento Commerce wireframe of product details page&quot; width=&quot;570&quot; height=&quot;334&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-5.png&quot;&gt;&lt;img title=&quot;magento-wireframes-5&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-5.png&quot; alt=&quot;Magento Commerce wireframe of bundled product layout&quot; width=&quot;570&quot; height=&quot;333&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Presented with product details, short description, purchase options, alternate views, price, availability, tabbed display of related products and long description/specifics. Interacts with options/quantity inputs to make a purchase decision. Supporting interactions: views alternate image, zooming to view details; sidebar reminds shopper of recently viewed products and prominent position of mini cart encourages checkout.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Using back-office tools, updates product information including title, descriptions, pricing, multiple images, attributes (options may update pricing), manage inventory, setup related product offers (merchandising), and more.

Interactive / Elements:
&lt;ul&gt;
	&lt;li&gt;Recently viewed products listed in sidebar&lt;/li&gt;
	&lt;li&gt;Product details, main image, name, availability, short description, link to email a friend&lt;/li&gt;
	&lt;li&gt;Product options (required for configurable products) based on product attributes&lt;/li&gt;
	&lt;li&gt;More views: alternate images of product, click changes main image, zooming feature to view detail.&lt;/li&gt;
	&lt;li&gt;Add to cart / quantity input. Button click updates mini cart and user is notified at top of page; or (as set in back-office) user can be directed to the shopping cart page to begin checkout.&lt;/li&gt;
	&lt;li&gt;Recommended (product specific merchandising)&lt;/li&gt;
	&lt;li&gt;Long description and product specs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: Shopping Cart&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-6.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-832&quot; title=&quot;magento-wireframes-6&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-6.png&quot; alt=&quot;Magento commerce wireframe of shopping cart&quot; width=&quot;570&quot; height=&quot;335&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Reviews shopping choices in cart table and my edit quantity (update) and remove items, or continue to shop. In addition more (cross-sell) products are offered to shopper on the cart page. shopper may choose to use a discount if one is available or use the form to estimate shopping costs; with or without acting on the ‘discount’ and ‘estimate’ forms the shopper can ‘proceed to checkout’.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Using back-office tools, sets up offers a cross-sells based on products visible in the shopping cart. May offer discount (coupon) code for special marketing campaigns. Other offers can be product / price based in addition to coupon based. Shipping form is based on shipping configuration in the back-office.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Shopping cart table, editable quantity, displays any product options selected by shopper; line items include product icon name and unit price.&lt;/li&gt;
	&lt;li&gt;Update shopping cart, when user changes quantity the pricing can be updated with this button&lt;/li&gt;
	&lt;li&gt;Cross-sell offers on the cart page are based on products that the shopper has added to the cart&lt;/li&gt;
	&lt;li&gt;Discount code form for redemption of coupon codes&lt;/li&gt;
	&lt;li&gt;Shipping estimate form to help shopper to get a quote on total purchase cost&lt;/li&gt;
	&lt;li&gt;Proceed to checkout begins the one-page checkout process, as a best practice the button is above and below the ‘fold’ (always visible when scrolling)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: One-page Checkout (step one)&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-7.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-833&quot; title=&quot;magento-wireframes-7&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-7.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (login / guest)&quot; width=&quot;570&quot; height=&quot;331&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;&lt;strong&gt;User Experiences:&lt;/strong&gt;&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - First step in one-page checkout experience. Shopper may create a new account, login with previously created account or checkout anonymously without saving account details. Forgot password tools to recover existing account password if needed. Registered shoppers benefit from returning to check order status and history also secondary purchases are quicker as billing and shipping addresses are stored in the shopper account. Anonymous checkout is for shoppers who would rather not have a stored account.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Manage customer accounts using the back-office tools, Customer service may reset account passwords return orders process cancellations and other order fulfillment tasks.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Checkout Method is the fist step. Create an account, login or checkout as guest&lt;/li&gt;
	&lt;li&gt;Steps in checkout flow are reported on screen to indicate progress and confirm shopper billing, shipping address and method as well payment method&lt;/li&gt;
	&lt;li&gt;Options for first time customers to purchase as anonymous shopper (guest) or choose to save information in ‘My Account’ to register as a shopper&lt;/li&gt;
	&lt;li&gt;Continue initiates the second step in the flow&lt;/li&gt;
	&lt;li&gt;Login retrieves stored shopper details to facilitate completing of checkout forms and auto-populates the fields for ease of use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: One-page Checkout (step two/three)&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-8.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-834&quot; title=&quot;magento-wireframes-8&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-8.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (billing / shipping)&quot; width=&quot;570&quot; height=&quot;331&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Second step in one-page checkout flow, AJAX interaction updates the page for shopper to enter or confirm billing information and choose the same address for shipping or select to enter a different shipping address. Returning customers have the fields pre-populated for easy checkout.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Customer service may edit shopper shipping address if necessary to complete the transaction. This step is for the shopper to send their billing details. The back office collects customer data when shopper chooses to create account.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Billing information is the second step in the AJAX experience.&lt;/li&gt;
	&lt;li&gt;Steps in checkout flow are reported on screen to indicate progress and confirm shopper billing, shipping address and method as well payment method&lt;/li&gt;
	&lt;li&gt;Shopper chooses whether or not to use the same address as billing to ship the purchase to or create a new address entry for shipment in the third step. When shopper elects to ship to the same address as billing the next (3rd) step is skipped as billing address is stored for the shipping address too&lt;/li&gt;
	&lt;li&gt;Continue initiates the third or fourth step in the flow&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: One-page Checkout (step four)&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-9.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-835&quot; title=&quot;magento-wireframes-9&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-9.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (shipping options)&quot; width=&quot;570&quot; height=&quot;333&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Fourth step in one-page checkout flow, (third step is address entry for shipping, very similar to billing address form). AJAX interaction updates the page for shopper to choose a shipping method. Also shopper has an option to ‘gift’ the purchase and notify the recipient by email with a ‘gift message’.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Customer service process the order/shipment and notifies the shopper when the shipment is fulfilled using back-office tools.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Shipping Method is the fourth (4th) step in the flow&lt;/li&gt;
	&lt;li&gt;Steps in checkout flow are reported on screen to indicate progress and confirm shopper billing, shipping address and method as well payment method&lt;/li&gt;
	&lt;li&gt;Option to ‘gift’ the purchase and notify the recipient by email suing the ‘gift message’&lt;/li&gt;
	&lt;li&gt;Continue initiates the third or fifth step in the flow&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: One-page Checkout (step five)&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-10.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-836&quot; title=&quot;magento-wireframes-10&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-10.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (payment options)&quot; width=&quot;570&quot; height=&quot;331&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Fifth (5th) step in one-page checkout flow. Shopper selects an available payment methods and screen is updated with entry form; shopper completes form and payment information is stored; When the shopper continues the next step is to review/confirm the order details.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Customer service verifies payment processing depending on options set-up in the back-office for the payment gateway. Orders may be declined if fraud is suspected. The payment authorization process uses the information supplied by shopper here.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Payment Method is the fifth (5th) step in the flow&lt;/li&gt;
	&lt;li&gt;Steps in checkout flow are reported on screen to indicate progress and confirm shopper billing, shipping address and method as well payment method&lt;/li&gt;
	&lt;li&gt;In this example the method chosen is Credit Card. Payment information is collected and processed with payment gateway selected in the back-office.&lt;/li&gt;
	&lt;li&gt;Continue initiates the final ‘review’ step in the flow&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: One-page Checkout (step six)&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-11.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-837&quot; title=&quot;magento-wireframes-11&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-11.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (review / confirm order info)&quot; width=&quot;570&quot; height=&quot;334&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Final (6th) step in one-page checkout flow. Shopper reviews the order details and total cost; also may follow link to edit the items the cart to add or correct quantities, etc. After reviewing the details presented shopper clicks ‘place order’ button to complete the order. Shopper will be notified with a success page in response to the order posting, or if there was any error on the transaction.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Customer service will also be notified by email of the purchase and then manages the order with back-office tools. Various notifications are managed in the back-office for shipment notifications order cancellation, etc. Returns may also be posted in the back-office. Depending on payment gateway options store manager should process payments using gateway user interface (separate from back-office).

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Order Review is the final (6th) step in the flow&lt;/li&gt;
	&lt;li&gt;Steps in checkout flow are reported on screen to indicate progress and confirm shopper billing, shipping address and method as well payment method&lt;/li&gt;
	&lt;li&gt;Purchase summary of items and total cost for shopper confirmation&lt;/li&gt;
	&lt;li&gt;Option to edit the items in the cart, add, etc.&lt;/li&gt;
	&lt;li&gt;Place order action competes the purchase. The shopper will be notified with a success page in response to the order posting or if there was any error on the transaction&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page: Checkout Success&lt;/h3&gt;
&lt;a href=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-12.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-838&quot; title=&quot;magento-wireframes-12&quot; src=&quot;http://pixelhandler.com/wp-content/uploads/2011/07/magento-wireframes-12.png&quot; alt=&quot;Magento Commerce wireframe of one step checkout (success / thank you page)&quot; width=&quot;570&quot; height=&quot;332&quot; /&gt;&lt;/a&gt;
&lt;h4&gt;User Experiences:&lt;/h4&gt;
&lt;strong&gt;Shopper&lt;/strong&gt; - Success page shows order number link to shopper to view and print order invoice and details. Continue shopping button provides an option to shopper to go back to the storefront and browser more products. My Orders block show customer recent purchase and give an option to add products to a now empty cart.

&lt;strong&gt;Store Manager&lt;/strong&gt; - Orders collected on storefront are stored in the back office tools for store management / customer service to interact with including notification of shipping, status updates (complete, pending, etc.); store manager view sales reports, status of orders, inventory, merchandising, storefront content, product details and many other tasks to successfully interact with online shoppers.

&lt;em&gt;Interactive / Elements:&lt;/em&gt;
&lt;ul&gt;
	&lt;li&gt;Order Completed, Link to order details and button to continue shopping&lt;/li&gt;
	&lt;li&gt;Mini-cart is now empty following competed order&lt;/li&gt;
	&lt;li&gt;My Orders block shows recent purchases to allow quick re-order of products&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>Test-driven Development (TDD) Using Javascript with QUnit</title>
    <link href="http://pixelhandler.com/blog/2010/12/02/test-driven-development-tdd-using-javascript-with-qunit/"/>
    <updated>2010-12-02T09:15:04-08:00</updated>
    <id>http://pixelhandler.com/blog/2010/12/02/test-driven-development-tdd-using-javascript-with-qunit</id>
    <content type="html">&lt;h3&gt;Who writes tests anyway?&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;jQuery uses QUnit
  &lt;p&gt;
    Docs: &lt;a href=&quot;http://docs.jquery.com/Qunit&quot;&gt;http://docs.jquery.com/Qunit&lt;/a&gt;&lt;br /&gt;
    Code: &lt;a href=&quot;https://github.com/jquery/qunit&quot;&gt;https://github.com/jquery/qunit&lt;/a&gt;
  &lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;QUnit is a powerful, easy-to-use, JavaScript test suite.&lt;/li&gt;
  &lt;li&gt;It's used by the jQuery project to test its code and plugins but is capable of testing any generic JavaScript code&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;h3&gt;Test-driven development (TDD) :&lt;/h3&gt;
&lt;p&gt;
  A software development process that relies on the repetition of a very short development cycle: &lt;strong&gt;first&lt;/strong&gt; the developer writes a &lt;strong&gt;failing automated test case&lt;/strong&gt; that defines a desired improvement or new function, &lt;strong&gt;then&lt;/strong&gt; produces &lt;strong&gt;code to pass that test&lt;/strong&gt; and finally refactors the new code to acceptable standards.
&lt;/p&gt;
&lt;p&gt;
  ref: &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;http://en.wikipedia.org/wiki/Test-driven_development&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;Behavior-driven development (BDD)&lt;/h3&gt;
&lt;p&gt;
  Introducing BDD : &lt;a href=&quot;http://blog.dannorth.net/introducing-bdd/&quot;&gt;http://blog.dannorth.net/introducing-bdd/&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;...where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
  Basically use language/terminology that everyone on the project understands; using a pattern (e.g. Given, When, Then.) to test expected behavior.
&lt;/p&gt;
&lt;p&gt;
  &lt;em&gt;&amp;quot;Developers discovered it could do at least some of their documentation for them, so they started to write test methods that were real sentences.&amp;quot;&lt;/em&gt;
&lt;/p&gt;

&lt;h3&gt;This article is about...&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;Using QUnit with test-driven development (TDD)&lt;/li&gt;
  &lt;li&gt;Example: utility method for weekend (only) content&lt;/li&gt;
  &lt;li&gt;First, write tests to describe the expected behavior that fail&lt;/li&gt;
  &lt;li&gt;Next, code to pass the tests&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The result&lt;/strong&gt;: a short utility function, the test script describes what the code does (behavior), is unit tested, and doubles as documentation for the code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;TDD Process&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;Add a test&lt;/li&gt;
  &lt;li&gt;Run all tests and see if the new one fails&lt;/li&gt;
  &lt;li&gt;Write some code&lt;/li&gt;
  &lt;li&gt;Run the automated tests and see them succeed&lt;/li&gt;
  &lt;li&gt;Refactor code&lt;/li&gt;
  &lt;li&gt;Repeat&lt;/li&gt; 
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Test-driven development constantly repeats the steps of adding test cases that fail, passing them, and refactoring. Receiving the expected test results at each stage reinforces the programmer's mental model of the code, boosts confidence and increases productivity.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- Lather, Rinse, Repeat&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Maybe the task is worth it...&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;From marketForce :&lt;/strong&gt; For weekend traffic, the one word difference had a +17.58% RPV Lift (98.01% Confidence) and a +16.15% Conversion Lift (97.53% Confidence) &lt;em&gt;So, I think it’s worth...&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;– this forecasts to an incremental &lt;strong&gt;$XXX,000&lt;/strong&gt; in annual revenues.&lt;/p&gt;


&lt;h3&gt;Time will only tell...&lt;/h3&gt;
&lt;p&gt;Could have used&amp;hellip;&lt;/p&gt;
&lt;pre&gt;
  var today = new Date(); 
  if (today.getDay() == 0 || today.getDay() == 6) { 
    $('#dr_billingContainer h3:eq(0)').html('XXXX XXXX');
  }
&lt;/pre&gt;
&lt;p&gt;&amp;hellip;Instead chose to make a jQuery plugin that acts as a utility method that can easily be reused for other sites&lt;/p&gt;

&lt;blockquote&gt;Javascript is all about behavior. Begin by writing some use cases or stories of what users will experience.&lt;/blockquote&gt;

&lt;h3&gt;Plugin / utility method : &lt;span style=&quot;font-weight:normal;&quot;&gt; TODO&amp;hellip;&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  /**  
   *  $.fn.isWeekend() plugin to test if browsing on Sat./Sun.
   *  checks a date object to see if the day is a weekend day, Saturday / Sunday
   *  requires Date object as argument and jQuery
   *  dr.isWeekend alias for plugin to use as utility function
   *  @return true/false
   */
&lt;/pre&gt;
&lt;p class=&quot;left-20&quot;&gt;What's Needed? What behavior will we test for?&lt;/p&gt;
&lt;ul class=&quot;left-20&quot;&gt;
  &lt;li&gt;is dr a global variable.&lt;/li&gt;
  &lt;li&gt;dr.isWeekend() expects argument of object type Date&lt;/li&gt;
  &lt;li&gt;dr.isWeekend() plugin returns true or false for each day of the week&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;QUnit : &lt;span class=&quot;normal&quot;&gt;Start w/ HTML&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;!DoCtYpE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;!-- QUnit CSS, JS, etc. --&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1 id=&amp;quot;qunit-header&amp;quot;&amp;gt;QUnit Tests for ...&amp;lt;/h3&amp;gt;
    &amp;lt;h2 id=&amp;quot;qunit-banner&amp;quot;&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;div id=&amp;quot;qunit-testrunner-toolbar&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;h2 id=&amp;quot;qunit-userAgent&amp;quot;&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;ol id=&amp;quot;qunit-tests&amp;quot;&amp;gt;&amp;lt;/ol&amp;gt;
    &amp;lt;div id=&amp;quot;qunit-fixture&amp;quot;&amp;gt;test markup&amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;What does this look like? Let&amp;#x27;s see it in action with JSFIDDLE&lt;/h3&gt;
&lt;blockquote&gt;Tip: click the &amp;#x27;Result&amp;#x27; tab to see test results; then click the test to expand (0, 1, 1) and see the details.&lt;/blockquote&gt;

&lt;h3&gt;Setup testing : &lt;span class=&quot;normal&quot;&gt;&lt;a href=&quot;http://jsfiddle.net/pixelhandler/NwPD5/&quot;&gt;JSFIDDLE&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Write a test : &lt;span style=&quot;font-weight:normal;&quot;&gt;to fail&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  /* namespace */
  module('namespace check');
  test('is dr a global variable.',function(){
      expect(1);
      ok( window.dr, 'dr namespace is present');
  });
&lt;/pre&gt;



&lt;h3&gt;Add namespace test : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;fails&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/1/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Add some code : &lt;/h3&gt;
&lt;pre&gt;
  if (!window.dr) { var dr = {}; } // using dr as namespace
&lt;/pre&gt;


&lt;h3&gt;Code for namesapce : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;passes&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/2/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Add some helper code : &lt;span class=&quot;normal&quot;&gt; in a module&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  module(&amp;quot;dr.isWeekend() utility fn uses jQuery&amp;quot;, {
    setup: function() {
      dr.date = new Date();
      dr.weekdays = [1,2,3,4,5];
      dr.weekends = [0,6];
    },
    teardown: function() {
      delete dr.date;
      delete dr.weekdays;
      delete dr.weekends;
    }
  });
&lt;/pre&gt;

&lt;h3&gt;Add a module w/ fixture : &lt;span class=&quot;normal&quot;&gt;to run with each test&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/3/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Add a test : &lt;span class=&quot;normal&quot;&gt; Arrange, Act, Assert&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  test(&amp;quot;dr.isWeekend() expects argument of object type Date&amp;quot;, function(){
      // Arrange - use setup() for dr.date
      var testPluginDefault;
      // Act
      testPluginDefault = dr.isWeekend();
      // Assert
      expect(1);
      notStrictEqual( testPluginDefault, 'error', &amp;quot;Plugin does not return 'error' comparing with notStrictEqual&amp;quot;);
  });
&lt;/pre&gt;

&lt;h3&gt;Test for plugin / method : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;fails&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/4/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Code for plugin : &lt;span class=&quot;normal&quot;&gt; skeleton&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  (function($) {

  $.fn.isWeekend = function(options) {
      var defaults = {};
      opts = $.extend({},defaults, options);
      // return this.each(function() { 
          // code plugin here ...
      // });
  };
  dr.isWeekend = $.fn.isWeekend;

  })(jQuery);
&lt;/pre&gt;

&lt;h3&gt;Code for plugin skeleton : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;passes&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/5/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Add more to the test : &lt;span class=&quot;normal&quot;&gt; date object?&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;
  test(&amp;quot;dr.isWeekend() expects argument of object type Date&amp;quot;, function(){
      // ...
      failDate = [];
      testPluginFalse = dr.isWeekend({ date: failDate });
      // Assert
      expect(2);
      // ...
      equal( testPluginFalse, 'invalid', &amp;quot;Plugin returns sting 'invalid' if argument is not Date object&amp;quot;);
  });
&lt;/pre&gt;

&lt;h3&gt;Add more to the test : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;fails&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/6/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Work it out : &lt;/h3&gt;
&lt;pre&gt;
  $.fn.isWeekend = function(options) {
      var defaults, opts;
      defaults = { date: new Date() };
      opts = $.extend({},defaults, options);
      if (Object.prototype.toString.call(opts.date) === '[object Date]') {
          opts.dateOk = true;
      } else {
          return 'invalid';
      }
  };
&lt;/pre&gt;

&lt;h3&gt;Code to : &lt;span class=&quot;normal&quot;&gt; pass the test&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/7/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;More testing : &lt;/h3&gt;
&lt;pre&gt;
  // Act
  // ...
  testPluginTrue = dr.isWeekend({ date: dr.date });
  // Assert
  expect(3);
  // ...
  notStrictEqual( testPluginTrue, 'invalid', &amp;quot;Plugin does not return 'invalid' comparing with notStrictEqual&amp;quot;);
&lt;/pre&gt;

&lt;h3&gt;More testing : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;passes, already :)&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/8/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Write some tests for logic &lt;/h3&gt;
&lt;pre&gt;
  test(&amp;quot;dr.isWeekend() plugin returns true or false for each day of the week&amp;quot;, function(){
      // Arrange - use setup() for dr.date, dr.weekdays, dr.weekends
      var n, weekday, weekend;

      // Act
      n = 0;
      weekend = $.inArray(n, dr.weekends);
      n = 1;
      weekday = $.inArray(n, dr.weekdays);

      // Assert
      expect(2);
      equal(weekend, 0, &amp;quot;testing a weekend value&amp;quot;);
      equal(weekday, 0, &amp;quot;testing a weekday value&amp;quot;);
  });
&lt;/pre&gt;

&lt;h3&gt;Write some tests for logic : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;passes&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/9/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Write some test for behavior : &lt;/h3&gt;
&lt;pre&gt;
  // Assert
  expect(11);
  equal(weekend, 0, &amp;quot;testing a weekend value&amp;quot;);
  equal(weekday, 0, &amp;quot;testing a weekday value&amp;quot;);
  equal(isSunday, true, &amp;quot;Yes, 11/28/2010 is Sunday a weekend&amp;quot; );
  equal(isMonday, false, &amp;quot;Yes, 11/29/2010 is Monday a weekday&amp;quot; );
  equal(isTuesday, false, &amp;quot;Yes, Tuesday a weekday&amp;quot; );
  equal(isWednesday, false, &amp;quot;Yes, Wednesday a weekday&amp;quot; );
  equal(isThursday, false, &amp;quot;Yes, Thursday a weekday&amp;quot; );
  equal(isFriday, false, &amp;quot;Yes, Friday a weekday&amp;quot; );
  equal(isSaturday, true, &amp;quot;Yes, Saturday a weekday&amp;quot; );
  equal(isTodayAWeekend, true, &amp;quot;Is today a weekend: true if today is a weekend&amp;quot; );
  equal(isTodayAWeekend, false, &amp;quot;Is today a weekend: false if today is a weekday&amp;quot; );
&lt;/pre&gt;

&lt;h3&gt;Write some test for behavior : &lt;span class=&quot;normal&quot;&gt; &amp;hellip;fails&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/10/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Code the expected behavior : &lt;/h3&gt;
&lt;pre&gt;
  // ...
  weekdays = [1,2,3,4,5];
  weekends = [0,6];
  if (Object.prototype.toString.call(opts.date) === '[object Date]') {
      // check if weekend using getDay() -&amp;gt; returns number 0-6 for day of week
      opts.n = opts.date.getDay();
      if ( $.inArray(opts.n , weekends) &amp;gt; -1 ) {
          return true;
      } else if ( $.inArray(opts.n , weekdays) &amp;gt; -1 ) {
          return false;
      }
      return 'error';
  } else {
      return 'invalid';
  }
&lt;/pre&gt;

&lt;h3&gt;1 fail &lt;span class=&quot;normal&quot;&gt; &amp;hellip; everyday can't be a weekend :(&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://jsfiddle.net/pixelhandler/NwPD5/11/embedded/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Another example : &lt;span class=&quot;normal&quot;&gt; input helper text&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://code.html-src.com/665652/&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Another example : &lt;span class=&quot;normal&quot;&gt; input helper text&lt;/span&gt;&lt;/h3&gt;
&lt;iframe class=&quot;sectionframe&quot; src=&quot;http://code.html-src.com/665652/unitTests.html&quot;&gt;&lt;/iframe&gt;

&lt;h3&gt;Links :&lt;/h3&gt;
&lt;ul class=&quot;left-20&quot;&gt;
  &lt;li&gt;This code - &lt;a href=&quot;https://gist.github.com/d379c952af637aeb0e51&quot;&gt;(github.com) gist&lt;/a&gt; | &lt;a href=&quot;http://jsfiddle.net/pixelhandler/NwPD5/&quot;&gt;jsfiddle.net ( append 1/ - 11/ )&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;This presentation Source - &lt;a href=&quot;https://gist.github.com/eee65f0f1d3b82b53ed9&quot;&gt;gist&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;QUnit - &lt;a href=&quot;http://docs.jquery.com/Qunit&quot;&gt;Documentation&lt;/a&gt; | &lt;a href=&quot;https://github.com/jquery/qunit&quot;&gt;Code&lt;/a&gt; | &lt;a href=&quot;https://github.com/jquery/qunit/raw/master/qunit/qunit.js&quot;&gt;JS&lt;/a&gt; | &lt;a href=&quot;https://github.com/jquery/qunit/raw/master/qunit/qunit.css&quot;&gt;CSS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Notes - &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD (wikipedia)&lt;/a&gt; | &lt;a href=&quot;http://blog.dannorth.net/introducing-bdd/&quot;&gt;BDD (blog.dannorth.net)&lt;/a&gt; | &lt;a href=&quot;http://integralpath.blogs.com/thinkingoutloud/2005/09/principles_of_t.html&quot;&gt;3-A's &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Tools - &lt;a href=&quot;http://jslint.com/&quot;&gt;jslint.com&lt;/a&gt; | &lt;a href=&quot;http://javascriptcompressor.com/&quot;&gt;javascriptcompressor.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Presentation: &lt;a href=&quot;http://skript.co/talks/qunit/&quot;&gt;Slides&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>QUnit tests for .searchText() search form helper plugin</title>
    <link href="http://pixelhandler.com/blog/2010/11/11/qunit-tests-for-searchtext-search-form-helper-plugin/"/>
    <updated>2010-11-11T08:32:19-08:00</updated>
    <id>http://pixelhandler.com/blog/2010/11/11/qunit-tests-for-searchtext-search-form-helper-plugin</id>
    <content type="html">The purpose of this code is to test the behavior of the &lt;a href=&quot;http://html-src.com/web-dev/71/searchtext-jquery-plugin-to-add-helper-text-in-search-input/&quot; target=&quot;_blank&quot;&gt;.searchText() jQuery plugin&lt;/a&gt;. 

&lt;strong&gt;&lt;a href=&quot;https://gist.github.com/665652&quot;&gt;Source Code&lt;/a&gt; | &lt;a href=&quot;http://code.html-src.com/665652/&quot;&gt;Demo and QUnit tests&lt;/a&gt;&lt;/strong&gt;

&lt;p&gt;Each test will get values at different stages of user interaction with text input field.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;simulate user entering text within input field&lt;/li&gt;
&lt;li&gt;simulate user leaving input field&lt;/li&gt;
&lt;li&gt;simulate user re-entering input&lt;/li&gt;
&lt;/ol&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;strong&gt;Tests:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Search form value empty prior to using searchText plugin&lt;/li&gt;
&lt;li&gt;searchText jQuery Plugin With No Parameters&lt;/li&gt;
&lt;li&gt;searchText jQuery Plugin With helperText Parameter&lt;/li&gt;
&lt;li&gt;searchText jQuery Plugin With forceReset Parameter&lt;/li&gt;
&lt;/ol&gt;

&lt;em&gt;&lt;a href=&quot;http://docs.jquery.com/QUnit&quot;&gt;QUnit&lt;/a&gt; is a lean testing framework used by the contributors to the jQuery JavaScript library. &lt;/em&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/665652.js?file=tests.js #'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// documentation on writing tests here: http://docs.jquery.com/QUnit
// source : https://github.com/jquery/qunit

// global var htmlsrc for namespace
if (!window.htmlsrc) {var htmlsrc = {};}
/*
 * .searchText() testing user interaction with form input behaviors
 */

/* namespace */
module('namespace check');
test('is htmlsrc a global variable',function(){
	expect(1);
	ok( window.htmlsrc, 'htmlsrc namespace is present');
});

/* fixture */
htmlsrc.testMarkup = '#qunit-fixture';

module(&amp;quot;.searchText() jQuery Plugin&amp;quot;, {
  setup: function() {
    htmlsrc.testForm = '&amp;lt;form action=&amp;quot;submit&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;searchform&amp;quot;&amp;gt;&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;s&amp;quot; /&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;&amp;amp;rarr;&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;&amp;lt;/form&amp;gt;';
  },
  teardown: function() {
    $(htmlsrc.testMarkup).empty();
  }
});

test(&amp;quot;Search form value empty prior to using searchText plugin&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value;  
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);

  // Act
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';
  _Value = $(_Selector,_Form).val();

  // Assert
  expect(1);
  same(_Value,&amp;quot;&amp;quot;, &amp;quot;text input field should have be empty, value is empty string&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With No Parameters&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};  
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);

  // Act
  _Form.searchText();
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';
  _Value.a = $(_Selector, _Form).val();
  _Value.b = $(_Selector, _Form).focus().val();
  _Value.c = $(_Selector, _Form).focus().blur().val();
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();

  // Assert
  expect(3);
  same(_Value.a, &amp;quot;Search&amp;quot;, &amp;quot;text input field should have the text 'Search'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;Search&amp;quot;, &amp;quot;text 'Search' is devault after blur event&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With helperText Parameter&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';

  // Act
  _Form.searchText({ 
    helperText	: &amp;quot;Search our site...&amp;quot;
  });
  // get values at different stages of user interaction with text input field
  _Value.a = $(_Selector, _Form).val();
  // simulate user entering text within input field
  $(_Selector, _Form).focus();
  _Value.b = $(_Selector, _Form).val();
  $(_Selector, _Form).val(&amp;quot;find it please&amp;quot;);
  // simulate user leaving input field
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();
  // simulate user re-entering input
  $(_Selector, _Form).focus();
  _Value.d = $(_Selector, _Form).val();

  // Assert
  expect(4);
  same(_Value.a, &amp;quot;Search our site...&amp;quot;, &amp;quot;text input field should have the custom text 'Search our site...'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;find it please&amp;quot;, &amp;quot;new text value is kept after blur event&amp;quot;);
  same(_Value.d, &amp;quot;find it please&amp;quot;, &amp;quot;new text value is not reset after re-entering input field&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With forceReset Parameter&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';

  // Act
  _Form.searchText({ 
    forceReset : true
  });
  // get values at different stages of user interaction with text input field
  _Value.a = $(_Selector, _Form).val();
  // simulate user entering text within input field
  $(_Selector, _Form).focus();
  _Value.b = $(_Selector, _Form).val();
  $(_Selector, _Form).val(&amp;quot;I am looking for cheese&amp;quot;);
  // simulate user leaving input field
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();
  // simulate user re-entering input
  $(_Selector, _Form).focus();
  _Value.d = $(_Selector, _Form).val();

  // Assert
  expect(4);
  same(_Value.a, &amp;quot;Search&amp;quot;, &amp;quot;text input field should have the default text 'Search'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;I am looking for cheese&amp;quot;, &amp;quot;new text value is kept after blur event&amp;quot;);
  same(_Value.d, &amp;quot;&amp;quot;, &amp;quot;new text value is forced to reset after re-entering (focus) input&amp;quot;);
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;

</content>
  </entry>
  
  <entry>
    <title>Event Pooling example using jQuery</title>
    <link href="http://pixelhandler.com/blog/2010/11/06/event-pooling-example-using-jquery/"/>
    <updated>2010-11-06T12:53:46-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/11/06/event-pooling-example-using-jquery</id>
    <content type="html">Example of using custom events in jQuery for event pooling. Elements broadcast (trigger) events and the document listens (binds) responding with calls to handlers based on. So, the methods to handle the events are loosely coupled with the UI elements and their behaviors. similar to other bind and trigger type of pub/sub (observer pattern).&lt;br/&gt;

&lt;!--more--&gt;

Working example at : &lt;a href=&quot;http://code.html-src.com/621429/&quot;&gt;code.html-src.com/621429&lt;/a&gt; be sure to view your browser console.

&lt;div&gt;&lt;script src='https://gist.github.com/621429.js?file=index.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;/&amp;gt;
    &amp;lt;title&amp;gt;Event Pooling, or perhaps Pub/Sub&amp;lt;/title&amp;gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot; src=&amp;quot;http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.2.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;strong&amp;gt;Who is this?&amp;lt;/strong&amp;gt;
&amp;lt;form action=&amp;quot;#&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;whoisit&amp;quot;&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;label for=&amp;quot;name&amp;quot;&amp;gt;name&amp;lt;/label&amp;gt; &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;name&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;name&amp;quot;&amp;gt;
    &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;label for=&amp;quot;email&amp;quot;&amp;gt;email&amp;lt;/label&amp;gt; &amp;lt;input type=&amp;quot;email&amp;quot; name=&amp;quot;email&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;email&amp;quot;&amp;gt;
    &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Continue &amp;amp;rarr;&amp;quot; id=&amp;quot;submit&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot; src=&amp;quot;script.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;div&gt;&lt;script src='https://gist.github.com/621429.js?file=script.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// Event pooling script
(function($) { // $ is jQuery 

    var eventpooling = function() {
        // broadcast events on elements
        $('#name').bind('blur', function(event) {
            $(document).trigger('NAME_CHANGED',event.target);
        });
        $('#email').bind('blur', function(event) {
            $(document).trigger('EMAIL_CHANGED',event.target);
        });
        $('#submit').bind('click', function(event) {
            $(document).trigger('SUBMIT_CLICKED',event);
        });

        // Pool events on document
        $(document).bind('NAME_CHANGED EMAIL_CHANGED SUBMIT_CLICKED', function(event) {
            //Handler(s)
            $.log(event.type);
        })
        .bind('NAME_CHANGED', function(event, obj) {
            //Handler(s)
            nameChangedHandler(event, obj);
        })
        .bind('EMAIL_CHANGED', function(event, obj) {
            //Handler(s)
            emailChangedHandler(event, obj);
        })
        .bind('SUBMIT_CLICKED', function(event) {
            //Handler(s)
            alert(&amp;quot;form valid? &amp;quot;+submitClickHandler(event));
        });

        // properties
        var IS_NAME_VALID, IS_EMAIL_VALID;

        // Common methods
        function responder(str) {
            var response = &amp;quot;Are you really named: &amp;quot;;
            return response + str;
        }
        function readyToSubmit() {
            var ready = (IS_NAME_VALID === true &amp;amp;&amp;amp; IS_EMAIL_VALID === true) || false;
            if (ready === true) {
                $('#submit').removeAttr('disabled');
            }
            return ready;
        }

        // validation methods
        function validater(event,obj) {
            $.log('validating: '+ event.type);
            var valid = false;
            var $obj = $(obj);
            $obj.str = $obj.val();
            $.log('value: '+ $obj.str);
            if (event.type == 'NAME_CHANGED') {
                valid = notEmpty($obj.str);
                IS_NAME_VALID = valid;
            }
            if (event.type == 'EMAIL_CHANGED') {
                if (notEmpty($obj.str) &amp;amp;&amp;amp; validEmail($obj.str)) {
                    valid = true;
                    IS_EMAIL_VALID = valid;
                } 
            }
            $.log('valid field: '+ valid);
            return readyToSubmit();
        }
        function notEmpty(str) {
            if (str!=='') {
                return true;
            } else {
                return false;
            }
        }
        function validEmail(elmValue){
           var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
           return emailPattern.test(elmValue);
        }

        // Event handlers
        function submitClickHandler(event) {
            validater(event);
            return readyToSubmit();
        }
        function nameChangedHandler(event, obj) {
            var name = $(obj).val();
            $.log(responder(name));
            validater(event,obj);
        }
        function emailChangedHandler(event, obj) {
            var email = $(obj).val();
            alert('please confirm your email: '+ email);
            validater(event,obj);
        }
        // initialize behavior
        var init = (function(){
            $('#submit').attr('disabled', 'disabled');
        })();
        return init;
    };
    
    // debugging methods
    $.fn.debug = function() {
        return this.each(function(){
            alert(this);
        });
    };
    $.log = function(message) {
        if(window.console) {
             console.debug(message);
        } else {
             alert(message);
        }
    };
    
    // doc ready
    $(function() {
        try {
            eventpooling();
        } catch(oops) {
            $.log(oops);
        }
    });
    
})(jQuery);&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;
</content>
  </entry>
  
  <entry>
    <title>searchText() jQuery plugin to add helper text in search input</title>
    <link href="http://pixelhandler.com/blog/2010/09/02/searchtext-jquery-plugin-to-add-helper-text-in-search-input/"/>
    <updated>2010-09-02T23:44:34-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/09/02/searchtext-jquery-plugin-to-add-helper-text-in-search-input</id>
    <content type="html">This jQuery plugin script added text to an input field in a search form. The defaults are set to the IDs used in a WordPress search form. The behavior can be set to force clearing of text every time user causes focus event to fire in text input (clicks to type). The function tirggers the focus event to start off with the helper text in the input field.

&lt;a href=&quot;http://code.html-src.com/665652/&quot;&gt;Demo and Qunit tests&lt;/a&gt;

&lt;!--more--&gt;

Liquid error: bad URI(is not URI?): https://raw.github.com/gist/665652/jquery.htmlsrc.searchText.js #

&lt;strong&gt;Use the plugin in your document ready :&lt;/strong&gt;
&lt;pre&gt;
// use plugin when WordPress search form id is present
$('#searchform').searchText();
&lt;/pre&gt;
&lt;strong&gt;Or,&lt;/strong&gt;
&lt;pre&gt;
// call plugin with option to force reseting the text on focus
$('#searchform').searchText({
	helperText : 'Search',
	inputId    : '#s',
	forceReset : true
});
&lt;/pre&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/665652.js?file=index.html'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;HTML for .searchText() jQuery Plugin, custom helper text input value&amp;lt;/title&amp;gt;
  &amp;lt;script src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;.searchText() jQuery Plugin, adding search helper text / behavior&amp;lt;/h1&amp;gt;
  &amp;lt;ol&amp;gt;
    &amp;lt;li&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Default options&amp;lt;/strong&amp;gt;, &amp;amp;quot;Search&amp;amp;quot; text added to input&amp;amp;hellip;&amp;lt;/p&amp;gt;
      &amp;lt;form action=&amp;quot;#&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;defaultform&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;d&amp;quot; /&amp;gt;
        &amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;submit&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/li&amp;gt;
  
    &amp;lt;li&amp;gt;
      &amp;lt;p&amp;gt;Extend default options, forcing text to &amp;lt;strong&amp;gt;reset upon re-entry&amp;lt;/strong&amp;gt;&amp;amp;hellip;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
      &amp;lt;form action=&amp;quot;#&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;searchform&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;s&amp;quot; /&amp;gt;
        &amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;submit&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/li&amp;gt;
  
    &amp;lt;li&amp;gt;
      &amp;lt;p&amp;gt;Extend default options, with &amp;lt;strong&amp;gt;custom helper&amp;lt;/strong&amp;gt; text&amp;amp;hellip;&amp;lt;/p&amp;gt;
      &amp;lt;form action=&amp;quot;#&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;findform&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;f&amp;quot; /&amp;gt;
        &amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;submit&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/li&amp;gt;
  
    &amp;lt;li&amp;gt;
      &amp;lt;p&amp;gt;Extend default options, with &amp;lt;strong&amp;gt;helperText&amp;lt;/strong&amp;gt; and &amp;lt;strong&amp;gt;forceReset&amp;lt;/strong&amp;gt; options&amp;amp;hellip;&amp;lt;/p&amp;gt;
      &amp;lt;form action=&amp;quot;#&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;whereform&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;w&amp;quot; /&amp;gt;
        &amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;submit&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ol&amp;gt;
  &amp;lt;h2&amp;gt;Unit Tests&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;unitTests.html&amp;quot;&amp;gt;Click to run tests with QUnit!&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;script src=&amp;quot;jquery.htmlsrc.searchText.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;
  (function($){
    // 1. Extend default options
    $('#defaultform').searchText({
    	inputId    : '#d'
    });

    // 2. Extend default options, forcing field to reset upon re-entry
    // was already in the jquery.htmlsrc.searchText.js file

    // 3. Extend default options, with custom helper text
    $('#findform').searchText({
    	helperText : 'Find something...',
    	inputId    : '#f'
    });

    // 4. 
    $('#whereform').searchText({
    	helperText : 'where is...',
    	inputId    : '#w',
    	forceReset : true
    });

  })(this.jQuery);
  &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;strong&gt;Clone the code snippet with git&amp;hellip;&lt;/strong&gt;
&lt;pre&gt;
git clone git://gist.github.com/665652.git
&lt;/pre&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/665652.js?file=tests.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;// documentation on writing tests here: http://docs.jquery.com/QUnit
// source : https://github.com/jquery/qunit

// global var htmlsrc for namespace
if (!window.htmlsrc) {var htmlsrc = {};}
/*
 * .searchText() testing user interaction with form input behaviors
 */

/* namespace */
module('namespace check');
test('is htmlsrc a global variable',function(){
	expect(1);
	ok( window.htmlsrc, 'htmlsrc namespace is present');
});

/* fixture */
htmlsrc.testMarkup = '#qunit-fixture';

module(&amp;quot;.searchText() jQuery Plugin&amp;quot;, {
  setup: function() {
    htmlsrc.testForm = '&amp;lt;form action=&amp;quot;submit&amp;quot; method=&amp;quot;get&amp;quot; accept-charset=&amp;quot;utf-8&amp;quot; id=&amp;quot;searchform&amp;quot;&amp;gt;&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;s&amp;quot; value=&amp;quot;&amp;quot; id=&amp;quot;s&amp;quot; /&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; val=&amp;quot;&amp;amp;rarr;&amp;quot; name=&amp;quot;submit&amp;quot; /&amp;gt;&amp;lt;/form&amp;gt;';
  },
  teardown: function() {
    $(htmlsrc.testMarkup).empty();
  }
});

test(&amp;quot;Search form value empty prior to using searchText plugin&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value;  
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);

  // Act
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';
  _Value = $(_Selector,_Form).val();

  // Assert
  expect(1);
  same(_Value,&amp;quot;&amp;quot;, &amp;quot;text input field should have be empty, value is empty string&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With No Parameters&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};  
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);

  // Act
  _Form.searchText();
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';
  _Value.a = $(_Selector, _Form).val();
  _Value.b = $(_Selector, _Form).focus().val();
  _Value.c = $(_Selector, _Form).focus().blur().val();
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();

  // Assert
  expect(3);
  same(_Value.a, &amp;quot;Search&amp;quot;, &amp;quot;text input field should have the text 'Search'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;Search&amp;quot;, &amp;quot;text 'Search' is devault after blur event&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With helperText Parameter&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';

  // Act
  _Form.searchText({ 
    helperText	: &amp;quot;Search our site...&amp;quot;
  });
  // get values at different stages of user interaction with text input field
  _Value.a = $(_Selector, _Form).val();
  // simulate user entering text within input field
  $(_Selector, _Form).focus();
  _Value.b = $(_Selector, _Form).val();
  $(_Selector, _Form).val(&amp;quot;find it please&amp;quot;);
  // simulate user leaving input field
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();
  // simulate user re-entering input
  $(_Selector, _Form).focus();
  _Value.d = $(_Selector, _Form).val();

  // Assert
  expect(4);
  same(_Value.a, &amp;quot;Search our site...&amp;quot;, &amp;quot;text input field should have the custom text 'Search our site...'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;find it please&amp;quot;, &amp;quot;new text value is kept after blur event&amp;quot;);
  same(_Value.d, &amp;quot;find it please&amp;quot;, &amp;quot;new text value is not reset after re-entering input field&amp;quot;);
});

test(&amp;quot;searchText jQuery Plugin With forceReset Parameter&amp;quot;, function() {

  // Arrange
  var _Form, _Selector, _Value = {};
  _Form = $(htmlsrc.testForm).appendTo(htmlsrc.testMarkup);
  _Selector = 'input[type=&amp;quot;text&amp;quot;]';

  // Act
  _Form.searchText({ 
    forceReset : true
  });
  // get values at different stages of user interaction with text input field
  _Value.a = $(_Selector, _Form).val();
  // simulate user entering text within input field
  $(_Selector, _Form).focus();
  _Value.b = $(_Selector, _Form).val();
  $(_Selector, _Form).val(&amp;quot;I am looking for cheese&amp;quot;);
  // simulate user leaving input field
  $(_Selector, _Form).blur();
  _Value.c = $(_Selector, _Form).val();
  // simulate user re-entering input
  $(_Selector, _Form).focus();
  _Value.d = $(_Selector, _Form).val();

  // Assert
  expect(4);
  same(_Value.a, &amp;quot;Search&amp;quot;, &amp;quot;text input field should have the default text 'Search'&amp;quot;);
  same(_Value.b, &amp;quot;&amp;quot;, &amp;quot;text input field should not have any text on focus event&amp;quot;);
  same(_Value.c, &amp;quot;I am looking for cheese&amp;quot;, &amp;quot;new text value is kept after blur event&amp;quot;);
  same(_Value.d, &amp;quot;&amp;quot;, &amp;quot;new text value is forced to reset after re-entering (focus) input&amp;quot;);
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;

</content>
  </entry>
  
  <entry>
    <title>jQuery plugin to 'matchHeight' of multiple columns with floating elements</title>
    <link href="http://pixelhandler.com/blog/2010/08/26/jquery-plugin-to-matchheight-of-multiple-columns-with-floating-elements/"/>
    <updated>2010-08-26T20:35:30-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/26/jquery-plugin-to-matchheight-of-multiple-columns-with-floating-elements</id>
    <content type="html">jQuery plugin to line up columns in a CSS layout with floating divs. This code has an option to use a fixed height instead of the greatest height among the column elements by setting a string as a (excluded) selector to indicate when to use the fixed height.

&lt;!--more--&gt;

Call the plugin on a containing layout element with multiple columns

&lt;div&gt;&lt;script src='https://gist.github.com/1081916.js?file=matchHeight.js'&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;(function($) {
/**
 *  .matchHeight()
 *    - match heights of multiple columns that use css layout with floating elements
 */
$.fn.matchHeight = function(options) {
    // set the containing element and set elements used as columns
    var defaults = {
        container : '.main',
        columns   : 'div',
        excluded  : '.dontChangeThis, .dontChangeThat',
        fixed     : 200
    };
    var opts = $.extend(defaults, options);
    return this.each(function() {
        var _ = { self : $(this) };
        _.px = {};
        _.cols = $(opts.container+' &amp;gt; '+opts.columns);
        _.cols.each(function(index) {
            _.px.index = $(this).height();
            if ($(opts.excluded).length&amp;gt;0) {
                _.colheight = opts.fixed;
                return;
            } else {
                if (index &amp;lt; 1) {
                    _.colheight = _.px.index;
                } else {
                    if (_.px.index &amp;gt; _.colheight) {
                        _.colheight = _.px.index;
                    }
                }
            }
        }).each(function(index) {
            $(this).css({ height : _.colheight });
        });
    });
};
})(jQuery);

//
// Call the plugin on a containing layout element with multiple columns
//

/**
 * Stuff to do as soon as the DOM is ready
 *  - enable plugin behavior(s)
 */
$(function() {
    $('.main-container')matchHeight({
                container : '.main',
                columns   : 'div.cols',
                excluded  : 'body.page2, div.noColumns',
                fixed  : 200
     });
    // or us the defaults
    // $('.container').matchHeight();
});&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


</content>
  </entry>
  
  <entry>
    <title>Simple PHP skinning scripts using basic template class</title>
    <link href="http://pixelhandler.com/blog/2010/08/15/simple-php-skinning-scripts-using-basic-template-class/"/>
    <updated>2010-08-15T02:28:11-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/15/simple-php-skinning-scripts-using-basic-template-class</id>
    <content type="html">This example is based on a MAMP environment with DNS setup for a .local domain, using MAMP apache's httpd.conf to set up vhosts; notes on this are in the index.php file.

Source code on github : &lt;a href=&quot;http://github.com/pixelhandler/simplephpskinner&quot;&gt;http://github.com/pixelhandler/simplephpskinner&lt;/a&gt;

&lt;h2&gt;Files used to create simple skinning scripts&lt;/h2&gt;
&lt;li&gt;css&lt;/li&gt;
	&lt;li&gt;style.css&lt;/li&gt;
&lt;li&gt;includes
	&lt;ul&gt;&lt;li&gt;body_bottom.phtml&lt;/li&gt;
	&lt;li&gt;body_top.phtml&lt;/li&gt;
	&lt;li&gt;class_template.php&lt;/li&gt;
	&lt;li&gt;config.php&lt;/li&gt;
	&lt;li&gt;footer.phtml&lt;/li&gt;
	&lt;li&gt;head.phtml&lt;/li&gt;
	&lt;li&gt;topnav.phtml&lt;/li&gt;
	&lt;li&gt;tracking.phtml&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;index.php&lt;/li&gt;
&lt;li&gt;js
	&lt;ul&gt;&lt;li&gt;jquery.plugins.js&lt;/li&gt;
	&lt;li&gt;tail.js&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;

&lt;!--more--&gt;

&lt;pre&gt;
&amp;lt;?php
/*
See more info on this article or source for setup on .local domain with MAMP
*/
require_once($_SERVER['DOCUMENT_ROOT'].'/includes/config.php');
// arg &amp;quot;Home&amp;quot; appends page title, &amp;quot;home&amp;quot; is id for body, site is owner
$template = new pageTemplate(&amp;quot;Home&amp;quot;,&amp;quot;home&amp;quot;,&amp;quot;/&amp;quot;,$site);
$template-&amp;gt;description = &amp;quot;yada yada&amp;quot;;
require_once($root.'/includes/head.phtml');
require_once($root.'/includes/body_top.phtml');
require_once($root.'/includes/topnav.phtml');	
?&amp;gt;
&amp;lt;div id=&amp;quot;leader&amp;quot; class=&amp;quot;full-16&amp;quot;&amp;gt;
&amp;lt;!-- content here --&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;?php
require_once($root.'/includes/footer.phtml');	
require_once($root.'/includes/body_bottom.phtml');	
?&amp;gt;
&lt;/pre&gt;

&lt;!--more--&gt;

&lt;h3&gt;includes/config.php&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;?php

# extra for testing, debugging, etc
# die(&amp;quot;ERROR on line:&amp;quot; . __line__);
error_reporting(E_ALL);
ini_set('display_errors','on');
# print_r($_SERVER);
# if (!session_id()) session_start();

# Globals
$root = $_SERVER['DOCUMENT_ROOT'];
$site = &amp;quot;My Site&amp;quot;;
$url = $_SERVER['SERVER_NAME'];
$prod = &amp;quot;domain.com&amp;quot;;
$local = &amp;quot;http://mysite.local:8888/&amp;quot;;
$googleAnalytics = &amp;quot;XX-xxxxxxx-XX&amp;quot;;

if (TRUE) { 
	// override for local work , use FALSE for prod. use
	$url = $local;
} else {
	// running in prod
	$url = $prod;
	if ($_SERVER['SERVER_NAME'] != $prod) {
		header( 'Location: ' . 'http://' . $prod . '/') ;
	}
}

# Class
require_once($root.'/includes/class_template.php');
?&amp;gt;
&lt;/pre&gt;


&lt;h3&gt;includes/class_template.php&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;?php 
// template class

class pageTemplate
{
	
	var $title;
	var $description;
	var $name;
	var $type;
	var $dir;
	
	function __construct($pagetitle=&amp;quot;&amp;quot;,$pagetype=&amp;quot;details&amp;quot;,$path=&amp;quot;&amp;quot;,$owner=&amp;quot;&amp;quot;)
	{
		$this-&amp;gt;title = $owner;
		if ($this-&amp;gt;title != &amp;quot;&amp;quot;) 
		{
			$this-&amp;gt;title .= &amp;quot; | &amp;quot; . $pagetitle;
		} 
		else 
		{
			$this-&amp;gt;title = $pagetitle;
		}
		$this-&amp;gt;name = $pagetitle;
		$this-&amp;gt;description = $pagetitle;
		$this-&amp;gt;type = strtolower($pagetype);
		$this-&amp;gt;owner = $owner;
		$this-&amp;gt;dir = strtolower($path);
	}
	
	function style($cssfile,$stamp=&amp;quot;&amp;quot;)
	{
		echo &amp;quot;&amp;lt;link href=&amp;quot;&amp;quot; . $cssfile . &amp;quot;?&amp;quot; . round(time(), -3) . &amp;quot;&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; media=&amp;quot;screen&amp;quot; /&amp;gt;rn&amp;quot;;
	}
	
	function script($jsfile)
	{
		echo &amp;quot;&amp;lt;script src=&amp;quot;&amp;quot; . $jsfile . &amp;quot;?&amp;quot; . round(time(), -3) . &amp;quot;&amp;quot; type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;rn&amp;quot;;
	}
	
	function pagetitle()
	{
		echo &amp;quot;&amp;lt;title&amp;gt;&amp;quot; . $this-&amp;gt;title . &amp;quot;&amp;lt;/title&amp;gt;rn&amp;quot;;
	}

}

?&amp;gt;
&lt;/pre&gt;


&lt;h3&gt;css/style.css&lt;/h3&gt;
&lt;pre&gt;
/* =========================== 
   Setup your grid here... 
   http://html-src.com/web-dev/53/use-ruby-gem-sass-to-generate-a-css-grid-layout/
   =========================*/
&lt;/pre&gt;


&lt;h3&gt;includes/head.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xml:lang=&amp;quot;en&amp;quot; lang=&amp;quot;en&amp;quot;&amp;gt;

&amp;lt;head&amp;gt;
	&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot;/&amp;gt;
	&amp;lt;?php echo $template-&amp;gt;pagetitle(); ?&amp;gt;
	&amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;&amp;lt;?php echo $template-&amp;gt;description; ?&amp;gt;&amp;quot;&amp;gt;
	&amp;lt;link rel=&amp;quot;icon&amp;quot; href=&amp;quot;favicon.ico&amp;quot; type=&amp;quot;image/x-icon&amp;quot; /&amp;gt;
	&amp;lt;link rel=&amp;quot;shortcut icon&amp;quot; href=&amp;quot;favicon.ico&amp;quot; type=&amp;quot;image/x-icon&amp;quot; /&amp;gt;
	&amp;lt;?php echo $template-&amp;gt;style(&amp;quot;/css/style.css&amp;quot;); ?&amp;gt;
	&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
	&amp;lt;?php echo $template-&amp;gt;script(&amp;quot;/js/jquery.plugins.js&amp;quot;); ?&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;includes/body_top.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;body id=&amp;quot;&amp;lt;?php echo $template-&amp;gt;type ?&amp;gt;&amp;quot; class=&amp;quot;&amp;lt;?php echo $template-&amp;gt;name ?&amp;gt;&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;wrapper&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;header&amp;quot; class=&amp;quot;full-16&amp;quot;&amp;gt;
	&amp;lt;div class=&amp;quot;inset&amp;quot;&amp;gt;
		&amp;lt;a href=&amp;quot;#mainContent&amp;quot; class=&amp;quot;accessibility&amp;quot;&amp;gt;&amp;amp;#x2193; Skip to page content&amp;lt;/a&amp;gt;
		&amp;lt;a id=&amp;quot;mainMenu&amp;quot; class=&amp;quot;accessibility&amp;quot;&amp;gt;Main Menu&amp;lt;/a&amp;gt;
	&amp;lt;/div&amp;gt;&amp;lt;!--/.inset--&amp;gt;
	&amp;lt;hr class=&amp;quot;accessibility&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;


&lt;h3&gt;includes/topnav.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;div id=&amp;quot;topnav&amp;quot;&amp;gt;
	&amp;lt;ul id=&amp;quot;menu&amp;quot; class=&amp;quot;nav&amp;quot;&amp;gt;
		&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;ul&amp;gt;
			&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/articles/&amp;quot;&amp;gt;Articles&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;
		&amp;lt;/li&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;!--/#topnav--&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;index.php&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;?php
/*
# DNS notes, running on MAMP
# instructions for running your site on http://mysite.local:8888/

# edit your hosts file with Textmate
mate /etc/hosts

# add your site
127.0.0.1 mysite.local

# if needed flush DNS on mac 
dscacheutil -flushcache

# add vhosts include:
mate /Applications/MAMP/conf/apache/httpd.conf 
# the code below needs to be at the end of our httpd.conf file ...

# NameVirtualHost *
Include /Applications/MAMP/conf/apache/httpd-vhosts.conf

mate /Applications/MAMP/conf/apache/httpd-vhosts.conf
# below are the contents of the httpd-vhosts.conf file ...
# be sure to change yourhomedirectory to the result of 
cd ~
pwd
# remember to start/stop MAMP when all setup

#
# Virtual Hosts
#
NameVirtualHost *:8888

&amp;lt;VirtualHost *:8888&amp;gt;
	DocumentRoot /Users/home/Sites/htdocs
	ServerName localhost
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:8888&amp;gt; 
  &amp;lt;Directory /Users/yourhomedirectory/Sites/htdocs/simplephpskinner&amp;gt; 
    AllowOverride All 
  &amp;lt;/Directory&amp;gt; 
  DocumentRoot /Users/yourhomedirectory/Sites/htdocs/simplephpskinner
  ServerName mysite.local
&amp;lt;/VirtualHost&amp;gt;

*/
require_once($_SERVER['DOCUMENT_ROOT'].'/includes/config.php');
// arg &amp;quot;Home&amp;quot; appends page title, &amp;quot;home&amp;quot; is id for body, site is owner
$template = new pageTemplate(&amp;quot;Home&amp;quot;,&amp;quot;home&amp;quot;,&amp;quot;/&amp;quot;,$site);
$template-&amp;gt;description = &amp;quot;yada yada&amp;quot;;
require_once($root.'/includes/head.phtml');
require_once($root.'/includes/body_top.phtml');
require_once($root.'/includes/topnav.phtml');	
?&amp;gt;
&amp;lt;div id=&amp;quot;leader&amp;quot; class=&amp;quot;full-16&amp;quot;&amp;gt;
&amp;lt;!-- content here --&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;?php
require_once($root.'/includes/footer.phtml');	
require_once($root.'/includes/body_bottom.phtml');	
?&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;includes/footer.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;div id=&amp;quot;footer&amp;quot;&amp;gt;
	&amp;lt;p class=&amp;quot;quarter&amp;quot;&amp;gt;&amp;amp;copy; 2010 &amp;lt;?php echo $template-&amp;gt;owner ?&amp;gt;&amp;lt;/p&amp;gt;
	&amp;lt;div class=&amp;quot;threeQuarter&amp;quot; id=&amp;quot;nav&amp;quot;&amp;gt;
		&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt; |
	&amp;lt;/div&amp;gt;
	&amp;lt;br class=&amp;quot;clearLeft&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;includes/body_bottom.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;a href=&amp;quot;#mainContent&amp;quot; class=&amp;quot;accessibility&amp;quot;&amp;gt;&amp;amp;#x2191; Back to page content&amp;lt;/a&amp;gt;
&amp;lt;a href=&amp;quot;#mainMenu&amp;quot; class=&amp;quot;accessibility&amp;quot;&amp;gt;&amp;amp;#x2191; Back to main menu&amp;lt;/a&amp;gt;
	&amp;lt;!-- &amp;lt;div class=&amp;quot;test&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/div&amp;gt; --&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;!--/#wrapper--&amp;gt;
&amp;lt;?php echo $template-&amp;gt;script(&amp;quot;js/tail.js&amp;quot;); ?&amp;gt;
&amp;lt;?php # require_once($root.'/includes/tracking.phtml'); ?&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&amp;lt;!-- &amp;lt;?php echo(date(&amp;quot;D F d Y&amp;quot;,time())); ?&amp;gt; --&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;includes/tracking.phtml&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', '&amp;lt;?php echo $googleAnalytics ?&amp;gt;']);
  _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;js/jquery.plugins.js&lt;/h3&gt;
&lt;pre&gt;
/**
 * jQuery go in here plugins.
 */
&lt;/pre&gt;

&lt;h3&gt;js/tail.js&lt;/h3&gt;
&lt;pre&gt;
/* load at end of page */
$(document).ready(function() { 

}); // end doc ready
&lt;/pre&gt;




</content>
  </entry>
  
  <entry>
    <title>Use ruby gem, Sass to generate a CSS grid layout</title>
    <link href="http://pixelhandler.com/blog/2010/08/15/use-ruby-gem-sass-to-generate-a-css-grid-layout/"/>
    <updated>2010-08-15T00:13:07-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/15/use-ruby-gem-sass-to-generate-a-css-grid-layout</id>
    <content type="html">This is a basic template tool for generating your own grid system using Sass, and builds on best practices of existing CSS grid systems like 960.gs or Blueprint in a bare bones fashion. The generated CSS includes classes for prototyping or designing in a browser; and also creates variables for assignment to your semantic id’s for cleaner markup.

&lt;!--more--&gt;

More on this topic see : &lt;a href=&quot;http://sass-lang.com/&quot;&gt;sass-lang.com&lt;/a&gt;

&lt;h2&gt;In your grid.sass file:&lt;/h2&gt;
&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Grid CSS as SASS (grid.sass)&lt;/span&gt; &lt;a href='http://pixelhandler.com/downloads/code/sass/grid.sass'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;span class='line'&gt;36&lt;/span&gt;
&lt;span class='line'&gt;37&lt;/span&gt;
&lt;span class='line'&gt;38&lt;/span&gt;
&lt;span class='line'&gt;39&lt;/span&gt;
&lt;span class='line'&gt;40&lt;/span&gt;
&lt;span class='line'&gt;41&lt;/span&gt;
&lt;span class='line'&gt;42&lt;/span&gt;
&lt;span class='line'&gt;43&lt;/span&gt;
&lt;span class='line'&gt;44&lt;/span&gt;
&lt;span class='line'&gt;45&lt;/span&gt;
&lt;span class='line'&gt;46&lt;/span&gt;
&lt;span class='line'&gt;47&lt;/span&gt;
&lt;span class='line'&gt;48&lt;/span&gt;
&lt;span class='line'&gt;49&lt;/span&gt;
&lt;span class='line'&gt;50&lt;/span&gt;
&lt;span class='line'&gt;51&lt;/span&gt;
&lt;span class='line'&gt;52&lt;/span&gt;
&lt;span class='line'&gt;53&lt;/span&gt;
&lt;span class='line'&gt;54&lt;/span&gt;
&lt;span class='line'&gt;55&lt;/span&gt;
&lt;span class='line'&gt;56&lt;/span&gt;
&lt;span class='line'&gt;57&lt;/span&gt;
&lt;span class='line'&gt;58&lt;/span&gt;
&lt;span class='line'&gt;59&lt;/span&gt;
&lt;span class='line'&gt;60&lt;/span&gt;
&lt;span class='line'&gt;61&lt;/span&gt;
&lt;span class='line'&gt;62&lt;/span&gt;
&lt;span class='line'&gt;63&lt;/span&gt;
&lt;span class='line'&gt;64&lt;/span&gt;
&lt;span class='line'&gt;65&lt;/span&gt;
&lt;span class='line'&gt;66&lt;/span&gt;
&lt;span class='line'&gt;67&lt;/span&gt;
&lt;span class='line'&gt;68&lt;/span&gt;
&lt;span class='line'&gt;69&lt;/span&gt;
&lt;span class='line'&gt;70&lt;/span&gt;
&lt;span class='line'&gt;71&lt;/span&gt;
&lt;span class='line'&gt;72&lt;/span&gt;
&lt;span class='line'&gt;73&lt;/span&gt;
&lt;span class='line'&gt;74&lt;/span&gt;
&lt;span class='line'&gt;75&lt;/span&gt;
&lt;span class='line'&gt;76&lt;/span&gt;
&lt;span class='line'&gt;77&lt;/span&gt;
&lt;span class='line'&gt;78&lt;/span&gt;
&lt;span class='line'&gt;79&lt;/span&gt;
&lt;span class='line'&gt;80&lt;/span&gt;
&lt;span class='line'&gt;81&lt;/span&gt;
&lt;span class='line'&gt;82&lt;/span&gt;
&lt;span class='line'&gt;83&lt;/span&gt;
&lt;span class='line'&gt;84&lt;/span&gt;
&lt;span class='line'&gt;85&lt;/span&gt;
&lt;span class='line'&gt;86&lt;/span&gt;
&lt;span class='line'&gt;87&lt;/span&gt;
&lt;span class='line'&gt;88&lt;/span&gt;
&lt;span class='line'&gt;89&lt;/span&gt;
&lt;span class='line'&gt;90&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='sass'&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Grid &lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// =========================== &lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// e.g. 960px, 12 columns (px) : | 10+ | 60 + 20 (x11) | 60 + 10 | &lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// Setup your grid ...&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// total page width&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!gTotal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;960&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// number of columns&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!grid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// gutter between columns&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// set margin at half of gutter	&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// single column width&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gTotal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!grid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// assign gird values to variables for use with semantic #id&amp;#39;s&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!col4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nv&quot;&gt;!col16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!grid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!grid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// mixins&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nf&quot;&gt;=colWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;!c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!c&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gGutter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nf&quot;&gt;=column&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;inline&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;left&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// simple example...&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// =========================== &lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.wide&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;left&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.wide&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nd&quot;&gt;+colWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!col16&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.quarter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.half&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.threeQuarter&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;left&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.quarter&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!col4&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.half&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!col4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.threeQuarter&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!col4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// design or prototype use...&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// =========================== &lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nf&quot;&gt;=gridTest&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;#ccc&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.5&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;em&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.5&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;em&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;px&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-13&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-15&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-16&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nd&quot;&gt;+column&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nd&quot;&gt;+gridTest&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-16&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;transparent&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// loop to create column widths&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;@for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;through&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nc&quot;&gt;.col-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nd&quot;&gt;+colWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;c1&quot;&gt;//width = ( !gCol * !i ) + ( !gGutter * ( !i - 1 ) )&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full-16&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;auto&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gTotal&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;@for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;through&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nc&quot;&gt;.push-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;@for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;through&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nc&quot;&gt;.pull-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;// helpers&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.first&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;left&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.last&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.indentLeft&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.indentRight&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.extend&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;padding-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;na&quot;&gt;padding-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt; =&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;!gMargin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

&lt;h3&gt;Execute on the command line&lt;/h3&gt;
&lt;pre&gt;
# turns ruby into CSS
sass grid.sass grid.css

# check it out with textmate
mate grid.css
&lt;/pre&gt;

this is part of my &lt;a href=&quot;http://github.com/pixelhandler/simpleSassFramework&quot;&gt;SimpleSassFramework&lt;/a&gt; for generating a boilerplate html site.

See the CSS output...
&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Grid SASS output (grid.css)&lt;/span&gt; &lt;a href='http://pixelhandler.com/downloads/code/css/grid.css'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;span class='line'&gt;15&lt;/span&gt;
&lt;span class='line'&gt;16&lt;/span&gt;
&lt;span class='line'&gt;17&lt;/span&gt;
&lt;span class='line'&gt;18&lt;/span&gt;
&lt;span class='line'&gt;19&lt;/span&gt;
&lt;span class='line'&gt;20&lt;/span&gt;
&lt;span class='line'&gt;21&lt;/span&gt;
&lt;span class='line'&gt;22&lt;/span&gt;
&lt;span class='line'&gt;23&lt;/span&gt;
&lt;span class='line'&gt;24&lt;/span&gt;
&lt;span class='line'&gt;25&lt;/span&gt;
&lt;span class='line'&gt;26&lt;/span&gt;
&lt;span class='line'&gt;27&lt;/span&gt;
&lt;span class='line'&gt;28&lt;/span&gt;
&lt;span class='line'&gt;29&lt;/span&gt;
&lt;span class='line'&gt;30&lt;/span&gt;
&lt;span class='line'&gt;31&lt;/span&gt;
&lt;span class='line'&gt;32&lt;/span&gt;
&lt;span class='line'&gt;33&lt;/span&gt;
&lt;span class='line'&gt;34&lt;/span&gt;
&lt;span class='line'&gt;35&lt;/span&gt;
&lt;span class='line'&gt;36&lt;/span&gt;
&lt;span class='line'&gt;37&lt;/span&gt;
&lt;span class='line'&gt;38&lt;/span&gt;
&lt;span class='line'&gt;39&lt;/span&gt;
&lt;span class='line'&gt;40&lt;/span&gt;
&lt;span class='line'&gt;41&lt;/span&gt;
&lt;span class='line'&gt;42&lt;/span&gt;
&lt;span class='line'&gt;43&lt;/span&gt;
&lt;span class='line'&gt;44&lt;/span&gt;
&lt;span class='line'&gt;45&lt;/span&gt;
&lt;span class='line'&gt;46&lt;/span&gt;
&lt;span class='line'&gt;47&lt;/span&gt;
&lt;span class='line'&gt;48&lt;/span&gt;
&lt;span class='line'&gt;49&lt;/span&gt;
&lt;span class='line'&gt;50&lt;/span&gt;
&lt;span class='line'&gt;51&lt;/span&gt;
&lt;span class='line'&gt;52&lt;/span&gt;
&lt;span class='line'&gt;53&lt;/span&gt;
&lt;span class='line'&gt;54&lt;/span&gt;
&lt;span class='line'&gt;55&lt;/span&gt;
&lt;span class='line'&gt;56&lt;/span&gt;
&lt;span class='line'&gt;57&lt;/span&gt;
&lt;span class='line'&gt;58&lt;/span&gt;
&lt;span class='line'&gt;59&lt;/span&gt;
&lt;span class='line'&gt;60&lt;/span&gt;
&lt;span class='line'&gt;61&lt;/span&gt;
&lt;span class='line'&gt;62&lt;/span&gt;
&lt;span class='line'&gt;63&lt;/span&gt;
&lt;span class='line'&gt;64&lt;/span&gt;
&lt;span class='line'&gt;65&lt;/span&gt;
&lt;span class='line'&gt;66&lt;/span&gt;
&lt;span class='line'&gt;67&lt;/span&gt;
&lt;span class='line'&gt;68&lt;/span&gt;
&lt;span class='line'&gt;69&lt;/span&gt;
&lt;span class='line'&gt;70&lt;/span&gt;
&lt;span class='line'&gt;71&lt;/span&gt;
&lt;span class='line'&gt;72&lt;/span&gt;
&lt;span class='line'&gt;73&lt;/span&gt;
&lt;span class='line'&gt;74&lt;/span&gt;
&lt;span class='line'&gt;75&lt;/span&gt;
&lt;span class='line'&gt;76&lt;/span&gt;
&lt;span class='line'&gt;77&lt;/span&gt;
&lt;span class='line'&gt;78&lt;/span&gt;
&lt;span class='line'&gt;79&lt;/span&gt;
&lt;span class='line'&gt;80&lt;/span&gt;
&lt;span class='line'&gt;81&lt;/span&gt;
&lt;span class='line'&gt;82&lt;/span&gt;
&lt;span class='line'&gt;83&lt;/span&gt;
&lt;span class='line'&gt;84&lt;/span&gt;
&lt;span class='line'&gt;85&lt;/span&gt;
&lt;span class='line'&gt;86&lt;/span&gt;
&lt;span class='line'&gt;87&lt;/span&gt;
&lt;span class='line'&gt;88&lt;/span&gt;
&lt;span class='line'&gt;89&lt;/span&gt;
&lt;span class='line'&gt;90&lt;/span&gt;
&lt;span class='line'&gt;91&lt;/span&gt;
&lt;span class='line'&gt;92&lt;/span&gt;
&lt;span class='line'&gt;93&lt;/span&gt;
&lt;span class='line'&gt;94&lt;/span&gt;
&lt;span class='line'&gt;95&lt;/span&gt;
&lt;span class='line'&gt;96&lt;/span&gt;
&lt;span class='line'&gt;97&lt;/span&gt;
&lt;span class='line'&gt;98&lt;/span&gt;
&lt;span class='line'&gt;99&lt;/span&gt;
&lt;span class='line'&gt;100&lt;/span&gt;
&lt;span class='line'&gt;101&lt;/span&gt;
&lt;span class='line'&gt;102&lt;/span&gt;
&lt;span class='line'&gt;103&lt;/span&gt;
&lt;span class='line'&gt;104&lt;/span&gt;
&lt;span class='line'&gt;105&lt;/span&gt;
&lt;span class='line'&gt;106&lt;/span&gt;
&lt;span class='line'&gt;107&lt;/span&gt;
&lt;span class='line'&gt;108&lt;/span&gt;
&lt;span class='line'&gt;109&lt;/span&gt;
&lt;span class='line'&gt;110&lt;/span&gt;
&lt;span class='line'&gt;111&lt;/span&gt;
&lt;span class='line'&gt;112&lt;/span&gt;
&lt;span class='line'&gt;113&lt;/span&gt;
&lt;span class='line'&gt;114&lt;/span&gt;
&lt;span class='line'&gt;115&lt;/span&gt;
&lt;span class='line'&gt;116&lt;/span&gt;
&lt;span class='line'&gt;117&lt;/span&gt;
&lt;span class='line'&gt;118&lt;/span&gt;
&lt;span class='line'&gt;119&lt;/span&gt;
&lt;span class='line'&gt;120&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.wide&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.wide&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;940px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;940px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.quarter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.half&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.threeQuarter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.quarter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;220px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.half&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;440px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.threeQuarter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;660px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-13&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-15&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.col-16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#ccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;.5em&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;.5em&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;80px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;transparent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;40px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;160px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;220px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;280px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;340px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-7&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;400px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;460px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;520px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;580px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-11&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;640px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.col-12&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;700px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.full-16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;960px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.push-1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;50px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.push-2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.push-3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;150px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.push-4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;200px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.pull-1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-50px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.pull-2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-100px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.pull-3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-150px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.pull-4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-200px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.first&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.last&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.indentLeft&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.indentRight&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;nc&quot;&gt;.extend&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;padding-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;padding-right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
</content>
  </entry>
  
  <entry>
    <title>Fancy up a list of articles into a dynamic rotation of text</title>
    <link href="http://pixelhandler.com/blog/2010/08/14/fancy-up-a-list-of-articles-into-a-dynamic-rotation-of-text/"/>
    <updated>2010-08-14T23:54:25-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/14/fancy-up-a-list-of-articles-into-a-dynamic-rotation-of-text</id>
    <content type="html">This script and html are used to fancy up a list of articles then rotate the article teaser text...
&lt;!--more--&gt;
&lt;h2&gt;Script to change list of articles into a rotation of text&lt;/h2&gt;
&lt;pre&gt;
// rotate the articles
var $text = $('#section div.article');
$text.remove();
$text.teasers = [];
$.each($text, function(){
	$text.teasers.push(this);
});
$text.idx = 0;
$text.stage = $('#section div.inset');
$text.stage.html($text.teasers[$text.idx]);
setInterval(function() { 
	if ( $text.teasers.length &amp;gt; ($text.idx+1) ) {
		$text.idx ++ ;
	} else {
		$text.idx = 0;
	}
	$text.stage.html($text.teasers[$text.idx]);
}, 12000);
&lt;/pre&gt;


&lt;h3&gt;Soure HTML that script read to rotate articles&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;div id=&amp;quot;section&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;inset&amp;quot;&amp;gt;
	&amp;lt;div class=&amp;quot;article&amp;quot;&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;link&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;p&amp;gt;article teaser text...&amp;lt;/p&amp;gt;
	&amp;lt;/div&amp;gt;
	&amp;lt;div class=&amp;quot;article&amp;quot;&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;link&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;p&amp;gt;article text...&amp;lt;/p&amp;gt;
	&amp;lt;/div&amp;gt;
	&amp;lt;div class=&amp;quot;article&amp;quot;&amp;gt;
		&amp;lt;h3&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;link&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;
		&amp;lt;p&amp;gt;another article text...&amp;lt;/p&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;!-- Example at http://quinnmedical.com under 'Headlines'  --&gt;
</content>
  </entry>
  
  <entry>
    <title>Ruby block to create random token string without offending</title>
    <link href="http://pixelhandler.com/blog/2010/08/14/ruby-block-to-create-random-token-string-without-offending/"/>
    <updated>2010-08-14T23:37:12-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/14/ruby-block-to-create-random-token-string-without-offending</id>
    <content type="html">In creating rant.cc as a short URL generator I wanted to avoid generating random text that would be offensive, so the block below attempts to avoid creating some text string you may have to apologize to your mother about.

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Create random token with Ruby (random_token.rb)&lt;/span&gt; &lt;a href='http://pixelhandler.com/downloads/code/ruby/random_token.rb'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='rb'&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;random_token&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;BCDFGHJKLMNPQRSTVWXYZbcdfghjkmnpqrstvwxyz23456789-_&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;temp_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nb&quot;&gt;srand&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;no&quot;&gt;TOKEN_LENGTH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;n&quot;&gt;temp_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;temp_token&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
</content>
  </entry>
  
  <entry>
    <title>Import a URL with Ruby</title>
    <link href="http://pixelhandler.com/blog/2010/08/14/import-a-url-with-ruby/"/>
    <updated>2010-08-14T23:28:13-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/14/import-a-url-with-ruby</id>
    <content type="html">Simple blocks to use as a method to import a url in a rails app, like using content from another api

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;import HTML with Ruby (importHTML.rb)&lt;/span&gt; &lt;a href='http://pixelhandler.com/downloads/code/ruby/importHTML.rb'&gt;download&lt;/a&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='rb'&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;importHTML&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;open-uri&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;vi&quot;&gt;@source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;c1&quot;&gt;# uses a reference parameter when getting remote XML&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;importXML&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;open-uri&amp;#39;&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;vi&quot;&gt;@aclass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;AClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# expecting a param named ref&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@aclass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xml&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;n&quot;&gt;respond_to&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xml&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:xml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@content&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;

</content>
  </entry>
  
  <entry>
    <title>Use proxy file with PHP to load a URL from remote domain</title>
    <link href="http://pixelhandler.com/blog/2010/08/14/use-proxy-file-with-php-to-load-a-url-from-remote-domain/"/>
    <updated>2010-08-14T23:12:08-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/14/use-proxy-file-with-php-to-load-a-url-from-remote-domain</id>
    <content type="html">To get around cross domain issues use a local proxy.php file to load the remote url that you would like to use on your domain and interact with AJAX.

&lt;!--more--&gt;

&lt;h2&gt;Create your proxy.php file&lt;/h2&gt;
&lt;pre&gt;
&amp;lt;?php
// Set your return content type
header('Content-type: text/html');

// Website url to open
$daurl = 'htts://domain.com';

// Get that website's content
$handle = fopen($daurl, &amp;quot;r&amp;quot;);

// If there is something, read and return
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        echo $buffer;
    }
    fclose($handle);
}
?&amp;gt;
&lt;/pre&gt;

&lt;h3&gt;Call your proxy file with AJAX using jQuery&lt;/h3&gt;
&lt;pre&gt;
// requires jQuery $
$(function(){ 
	// you will need a proxy script to load remote content
	var proxy = 'proxy.php'; 
	$('div.container').hide();
	$('div.container').load( proxy + ' div#id', function() {
		$('div.container').show()
	});
});
&lt;/pre&gt;
</content>
  </entry>
  
  <entry>
    <title>Clean up directories prior to initializing repository</title>
    <link href="http://pixelhandler.com/blog/2010/08/14/clean-up-directories-prior-to-initializing-repository/"/>
    <updated>2010-08-14T22:34:04-07:00</updated>
    <id>http://pixelhandler.com/blog/2010/08/14/clean-up-directories-prior-to-initializing-repository</id>
    <content type="html">Use command line to clean up directories prior to initializing repository :

&lt;ul&gt;
	&lt;li&gt;remove junk like .DS_Store or clean out repositories like folders named CVS .svn .git &lt;/li&gt;
	&lt;li&gt;-type d for directories f for files&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;
find . -name '.svn' -type d | xargs echo

find . -name '.svn' -type d | xargs rm -rf

find . -name '.git' -exec rm -rf {} ;

find . -name '.DS_Store' -type f | xargs rm -rf
&lt;/pre&gt;
</content>
  </entry>
  
</feed>

