You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2014/02/12 07:19:55 UTC

[01/52] [abbrv] Fauxton: move modules to addons

Updated Branches:
  refs/heads/import-master [created] d11b90b8c


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/fauxton/layout.js
----------------------------------------------------------------------
diff --git a/app/modules/fauxton/layout.js b/app/modules/fauxton/layout.js
deleted file mode 100644
index 1422241..0000000
--- a/app/modules/fauxton/layout.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define(["backbone"],
-
-function(Backbone) {
-
-  // A wrapper of the main Backbone.layoutmanager
-  // Allows the main layout of the page to be changed by any plugin.
-  // Exposes the different views:
-  //    navBar -> the top navigation bar
-  //    dashboardContent -> Main display view
-  //    breadcrumbs -> Breadcrumbs navigation section
-  var Layout = function (navBar, apiBar) {
-    this.navBar = navBar;
-    this.apiBar = apiBar;
-
-    this.layout = new Backbone.Layout({
-      template: "templates/layouts/with_sidebar",
-
-      views: {
-        "#primary-navbar": this.navBar,
-        "#api-navbar": this.apiBar
-      },
-      afterRender: function(){
-
-      }
-    });
-
-    this.layoutViews = {};
-    //this.hooks = {};
-
-    this.el = this.layout.el;
-  };
-
-  // creatings the dashboard object same way backbone does
-  _.extend(Layout.prototype, {
-    render: function () {
-      return this.layout.render();
-    },
-
-    setTemplate: function(template) {
-      if (template.prefix){
-        this.layout.template = template.prefix + template.name;
-      } else{
-        this.layout.template = "templates/layouts/" + template;
-      }
-      // If we're changing layouts all bets are off, so kill off all the
-      // existing views in the layout.
-      _.each(this.layoutViews, function(view){view.remove();});
-      this.layoutViews = {};
-      this.render();
-    },
-
-    setTabs: function(view){
-      // TODO: Not sure I like this - seems fragile/repetitive
-      this.tabs = this.layout.setView("#tabs", view);
-      this.tabs.render();
-    },
-
-    setBreadcrumbs: function(view) {
-      this.breadcrumbs = this.layout.setView("#breadcrumbs", view);
-      this.breadcrumbs.render();
-    },
-
-    clearBreadcrumbs: function () {
-      if (!this.breadcrumbs) {return ;}
-
-      this.breadcrumbs.remove();
-    },
-
-    setView: function(selector, view) {
-      this.layoutViews[selector] = this.layout.setView(selector, view, false);
-    },
-
-    renderView: function(selector) {
-      var view = this.layoutViews[selector];
-      if (!view) {
-        return false;
-      } else {
-        return view.render();
-      }
-    }
-
-  });
-
-  return Layout;
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/pouchdb/base.js
----------------------------------------------------------------------
diff --git a/app/modules/pouchdb/base.js b/app/modules/pouchdb/base.js
deleted file mode 100644
index ee323a7..0000000
--- a/app/modules/pouchdb/base.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * NOTE:
- * This temporarily uses the PouchDB map reduce implementation
- * These files are modified locally until we make a more general version and
- * push it back upstream.
- */
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/pouchdb/pouchdb.mapreduce.js"
-],
-
-function(app, FauxtonAPI, MapReduce) {
-  var Pouch = {};
-  Pouch.MapReduce = MapReduce;
-
-  Pouch.runViewQuery = function(fun, opts) {
-    /*docs = [
-      {_id: 'test_doc_1', foo: 'bar-1'},
-      {_id: 'test_doc_2', foo: 'bar-2'},
-      {_id: 'test_doc_3', foo: 'bar-3'},
-      {_id: 'test_doc_4', foo: 'bar-4'},
-      {_id: 'test_doc_5', foo: 'bar-5'},
-      {_id: 'test_doc_6', foo: 'bar-6'},
-      {_id: 'test_doc_7', foo: 'bar-7'},
-      {_id: 'test_doc_8', foo: 'bar-8'},
-      {_id: 'test_doc_9', foo: 'bar-9'},
-      {_id: 'test_doc_10', foo: 'bar-10'}
-    ];*/
-
-    var deferred = FauxtonAPI.Deferred();
-    var complete = function(resp, rows) {
-      deferred.resolve(rows);
-    };
-
-    var options = _.extend(opts, {complete: complete});
-
-    Pouch.MapReduce.query(fun, options);
-    return deferred;
-  };
-  //pdb.runViewQuery({map:function(doc) { emit(doc._id, doc.foo) }})
-  return Pouch;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/pouchdb/pouch.collate.js
----------------------------------------------------------------------
diff --git a/app/modules/pouchdb/pouch.collate.js b/app/modules/pouchdb/pouch.collate.js
deleted file mode 100644
index 7cc5f9c..0000000
--- a/app/modules/pouchdb/pouch.collate.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * NOTE:
- * This temporarily uses the PouchDB map reduce implementation
- * These files are modified locally until we make a more general version and
- * push it back upstream.
- * Original file:
- * https://github.com/daleharvey/pouchdb/blob/master/src/pouch.collate.js
- */
-
-/*
-(function() {
-  // a few hacks to get things in the right place for node.js
-  if (typeof module !== 'undefined' && module.exports) {
-    module.exports = Pouch;
-  }
-*/
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/pouchdb/pouch.collate.js"
-],
-
-function(app, FauxtonAPI, Collate) {
-  var Pouch = {};
-
-  Pouch.collate = function(a, b) {
-    var ai = collationIndex(a);
-    var bi = collationIndex(b);
-    if ((ai - bi) !== 0) {
-      return ai - bi;
-    }
-    if (a === null) {
-      return 0;
-    }
-    if (typeof a === 'number') {
-      return a - b;
-    }
-    if (typeof a === 'boolean') {
-      return a < b ? -1 : 1;
-    }
-    if (typeof a === 'string') {
-      return stringCollate(a, b);
-    }
-    if (Array.isArray(a)) {
-      return arrayCollate(a, b);
-    }
-    if (typeof a === 'object') {
-      return objectCollate(a, b);
-    }
-  };
-
-  var stringCollate = function(a, b) {
-    // See: https://github.com/daleharvey/pouchdb/issues/40
-    // This is incompatible with the CouchDB implementation, but its the
-    // best we can do for now
-    return (a === b) ? 0 : ((a > b) ? 1 : -1);
-  };
-
-  var objectCollate = function(a, b) {
-    var ak = Object.keys(a), bk = Object.keys(b);
-    var len = Math.min(ak.length, bk.length);
-    for (var i = 0; i < len; i++) {
-      // First sort the keys
-      var sort = Pouch.collate(ak[i], bk[i]);
-      if (sort !== 0) {
-        return sort;
-      }
-      // if the keys are equal sort the values
-      sort = Pouch.collate(a[ak[i]], b[bk[i]]);
-      if (sort !== 0) {
-        return sort;
-      }
-
-    }
-    return (ak.length === bk.length) ? 0 :
-      (ak.length > bk.length) ? 1 : -1;
-  };
-
-  var arrayCollate = function(a, b) {
-    var len = Math.min(a.length, b.length);
-    for (var i = 0; i < len; i++) {
-      var sort = Pouch.collate(a[i], b[i]);
-      if (sort !== 0) {
-        return sort;
-      }
-    }
-    return (a.length === b.length) ? 0 :
-      (a.length > b.length) ? 1 : -1;
-  };
-
-  // The collation is defined by erlangs ordered terms
-  // the atoms null, true, false come first, then numbers, strings,
-  // arrays, then objects
-  var collationIndex = function(x) {
-    var id = ['boolean', 'number', 'string', 'object'];
-    if (id.indexOf(typeof x) !== -1) {
-      if (x === null) {
-        return 1;
-      }
-      return id.indexOf(typeof x) + 2;
-    }
-    if (Array.isArray(x)) {
-      return 4.5;
-    }
-  };
-
-  return Pouch;
-
-//}).call(this);
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/pouchdb/pouchdb.mapreduce.js
----------------------------------------------------------------------
diff --git a/app/modules/pouchdb/pouchdb.mapreduce.js b/app/modules/pouchdb/pouchdb.mapreduce.js
deleted file mode 100644
index a2d0b91..0000000
--- a/app/modules/pouchdb/pouchdb.mapreduce.js
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * NOTE:
- * This temporarily uses the PouchDB map reduce implementation
- * These files are modified locally until we make a more general version and
- * push it back upstream.
- * Original file:
- * https://github.com/daleharvey/pouchdb/blob/master/src/plugins/pouchdb.mapreduce.js
- */
-
-/*global Pouch: true */
-
-//"use strict";
-
-// This is the first implementation of a basic plugin, we register the
-// plugin object with pouch and it is mixin'd to each database created
-// (regardless of adapter), adapters can override plugins by providing
-// their own implementation. functions on the plugin object that start
-// with _ are reserved function that are called by pouchdb for special
-// notifications.
-
-// If we wanted to store incremental views we can do it here by listening
-// to the changes feed (keeping track of our last update_seq between page loads)
-// and storing the result of the map function (possibly using the upcoming
-// extracted adapter functions)
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/pouchdb/pouch.collate.js"
-],
-
-function(app, FauxtonAPI, Collate) {
-  var Pouch = {};
-  Pouch.collate = Collate.collate;
-
-  //var MapReduce = function(db) {
-  var MapReduce = function() {
-
-    var builtInReduce = {
-      "_sum": function(keys, values){
-        return sum(values);
-      },
-
-      "_count": function(keys, values, rereduce){
-        if (rereduce){
-          return sum(values);
-        } else {
-          return values.length;
-        }
-      },
-
-      "_stats": function(keys, values, rereduce){
-        return {
-          'sum': sum(values),
-          'min': Math.min.apply(null, values),
-          'max': Math.max.apply(null, values),
-          'count': values.length,
-          'sumsqr': (function(){
-            _sumsqr = 0;
-            for(var idx in values){
-              _sumsqr += values[idx] * values[idx];
-            }
-            return _sumsqr;
-          })()
-        };
-      }
-    };
-
-    function viewQuery(fun, options) {
-      console.log("IN VIEW QUERY");
-      if (!options.complete) {
-        return;
-      }
-
-      function sum(values) {
-        return values.reduce(function(a, b) { return a + b; }, 0);
-      }
-
-      var results = [];
-      var current = null;
-      var num_started= 0;
-      var completed= false;
-
-      var emit = function(key, val) {
-        //console.log("IN EMIT: ", key, val, current);
-        var viewRow = {
-          id: current.doc._id,
-          key: key,
-          value: val
-        }; 
-        //console.log("VIEW ROW: ", viewRow);
-
-        if (options.startkey && Pouch.collate(key, options.startkey) < 0) return;
-        if (options.endkey && Pouch.collate(key, options.endkey) > 0) return;
-        if (options.key && Pouch.collate(key, options.key) !== 0) return;
-        num_started++;
-        if (options.include_docs) {
-          // TODO:: FIX
-          throw({error: "Include Docs not supported"});
-          /*
-
-          //in this special case, join on _id (issue #106)
-          if (val && typeof val === 'object' && val._id){
-            db.get(val._id,
-                function(_, joined_doc){
-                  if (joined_doc) {
-                    viewRow.doc = joined_doc;
-                  }
-                  results.push(viewRow);
-                  checkComplete();
-                });
-            return;
-          } else {
-            viewRow.doc = current.doc;
-          }
-          */
-        }
-        console.log("EMITTING: ", viewRow);
-        results.push(viewRow);
-      };
-
-      // ugly way to make sure references to 'emit' in map/reduce bind to the
-      // above emit
-      eval('fun.map = ' + fun.map.toString() + ';');
-      if (fun.reduce && options.reduce) {
-        if (builtInReduce[fun.reduce]) {
-          console.log('built in reduce');
-          fun.reduce = builtInReduce[fun.reduce];
-        }
-        eval('fun.reduce = ' + fun.reduce.toString() + ';');
-      }
-
-      // exclude  _conflicts key by default
-      // or to use options.conflicts if it's set when called by db.query
-      var conflicts = ('conflicts' in options ? options.conflicts : false);
-
-      //only proceed once all documents are mapped and joined
-      var checkComplete= function(){
-        console.log('check');
-        if (completed && results.length == num_started){
-          results.sort(function(a, b) {
-            return Pouch.collate(a.key, b.key);
-          });
-          if (options.descending) {
-            results.reverse();
-          }
-          if (options.reduce === false) {
-            return options.complete(null, {rows: results});
-          }
-
-          console.log('reducing', options);
-          var groups = [];
-          results.forEach(function(e) {
-            var last = groups[groups.length-1] || null;
-            if (last && Pouch.collate(last.key[0][0], e.key) === 0) {
-              last.key.push([e.key, e.id]);
-              last.value.push(e.value);
-              return;
-            }
-            groups.push({key: [[e.key, e.id]], value: [e.value]});
-          });
-          groups.forEach(function(e) {
-            e.value = fun.reduce(e.key, e.value) || null;
-            e.key = e.key[0][0];
-          });
-          console.log('GROUPs', groups);
-          options.complete(null, {rows: groups});
-        }
-      };
-
-      if (options.docs) {
-        //console.log("RUNNING MR ON DOCS: ", options.docs);
-        _.each(options.docs, function(doc) {
-          current = {doc: doc};
-          fun.map.call(this, doc);
-        }, this);
-        completed = true;
-        return checkComplete();//options.complete(null, {rows: results});
-      } else {
-        //console.log("COULD NOT FIND DOCS");
-        return false;
-      }
-
-      /*
-      db.changes({
-        conflicts: conflicts,
-        include_docs: true,
-        onChange: function(doc) {
-          if (!('deleted' in doc)) {
-            current = {doc: doc.doc};
-            fun.map.call(this, doc.doc);
-          }
-        },
-        complete: function() {
-          completed= true;
-          checkComplete();
-        }
-      });
-      */
-    }
-
-    /*
-    function httpQuery(fun, opts, callback) {
-
-      // List of parameters to add to the PUT request
-      var params = [];
-      var body = undefined;
-      var method = 'GET';
-
-      // If opts.reduce exists and is defined, then add it to the list
-      // of parameters.
-      // If reduce=false then the results are that of only the map function
-      // not the final result of map and reduce.
-      if (typeof opts.reduce !== 'undefined') {
-        params.push('reduce=' + opts.reduce);
-      }
-      if (typeof opts.include_docs !== 'undefined') {
-        params.push('include_docs=' + opts.include_docs);
-      }
-      if (typeof opts.limit !== 'undefined') {
-        params.push('limit=' + opts.limit);
-      }
-      if (typeof opts.descending !== 'undefined') {
-        params.push('descending=' + opts.descending);
-      }
-      if (typeof opts.startkey !== 'undefined') {
-        params.push('startkey=' + encodeURIComponent(JSON.stringify(opts.startkey)));
-      }
-      if (typeof opts.endkey !== 'undefined') {
-        params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey)));
-      }
-      if (typeof opts.key !== 'undefined') {
-        params.push('key=' + encodeURIComponent(JSON.stringify(opts.key)));
-      }
-
-      // If keys are supplied, issue a POST request to circumvent GET query string limits
-      // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
-      if (typeof opts.keys !== 'undefined') {
-        method = 'POST';
-        body = JSON.stringify({keys:opts.keys});
-      }
-
-      // Format the list of parameters into a valid URI query string
-      params = params.join('&');
-      params = params === '' ? '' : '?' + params;
-
-      // We are referencing a query defined in the design doc
-      if (typeof fun === 'string') {
-        var parts = fun.split('/');
-        db.request({
-          method: method,
-          url: '_design/' + parts[0] + '/_view/' + parts[1] + params,
-          body: body
-        }, callback);
-        return;
-      }
-
-      // We are using a temporary view, terrible for performance but good for testing
-      var queryObject = JSON.parse(JSON.stringify(fun, function(key, val) {
-        if (typeof val === 'function') {
-          return val + ''; // implicitly `toString` it
-        }
-        return val;
-      }));
-
-      db.request({
-        method:'POST',
-        url: '_temp_view' + params,
-        body: queryObject
-      }, callback);
-    }
-    */
-
-    function query(fun, opts, callback) {
-      if (typeof opts === 'function') {
-        callback = opts;
-        opts = {};
-      }
-
-      if (callback) {
-        opts.complete = callback;
-      }
-
-      /*
-      if (db.type() === 'http') {
-        return httpQuery(fun, opts, callback);
-      }
-      */
-
-      if (typeof fun === 'object') {
-        console.log("RUNNING VIEW QUERY", fun, opts, arguments);
-        return viewQuery(fun, opts);
-      }
-
-      throw({error: "Shouldn't have gotten here"});
-
-      /*
-      var parts = fun.split('/');
-      db.get('_design/' + parts[0], function(err, doc) {
-        if (err) {
-          if (callback) callback(err);
-          return;
-        }
-        viewQuery({
-          map: doc.views[parts[1]].map,
-          reduce: doc.views[parts[1]].reduce
-        }, opts);
-      });
-      */
-    }
-
-    return {'query': query};
-  };
-
-  // Deletion is a noop since we dont store the results of the view
-  MapReduce._delete = function() { };
-
-  //Pouch.plugin('mapreduce', MapReduce);
-
-  return MapReduce();
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/router.js
----------------------------------------------------------------------
diff --git a/app/router.js b/app/router.js
index e3a1636..7cf69ad 100644
--- a/app/router.js
+++ b/app/router.js
@@ -25,27 +25,14 @@ define([
        "api",
 
        // Modules
-       "modules/fauxton/base",
+       "addons/fauxton/base",
        // Layout
-       "modules/fauxton/layout",
-
-       // Routes return the module that they define routes for
-       "modules/databases/base",
-       "modules/documents/base",
-       "modules/pouchdb/base",
-
-
-       // this needs to be added as a plugin later
-       // "modules/logs/base",
-       // "modules/config/base",
+       "addons/fauxton/layout",
 
        "load_addons"
 ],
 
-function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases, Documents, Pouch, LoadAddons) {
-
-  // TODO: auto generate this list if possible
-  var modules = [Databases, Documents];
+function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, LoadAddons) {
 
   var beforeUnloads = {};
 
@@ -106,11 +93,6 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases, Documents
     },
 
     setModuleRoutes: function() {
-      _.each(modules, function(module) {
-        if (module){
-          _.each(module.RouteObjects, this.addModuleRouteObject, this);
-        }
-      }, this);
       _.each(LoadAddons.addons, function(module) {
         if (module){
           module.initialize();
@@ -122,21 +104,6 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases, Documents
       }, this);
     },
 
-    /*setAddonHooks: function() {
-      _.each(LoadAddons.addons, function(module) {
-        // This is updates to views by the addon
-        if (module && module.hooks){
-          _.each(module.hooks, function(callback, route){
-            if (this.masterLayout.hooks[route]) {
-              this.masterLayout.hooks[route].push(callback);
-            } else {
-              this.masterLayout.hooks[route] = [callback];
-            }
-          }, this);
-        }
-      }, this);
-    },*/
-
     initialize: function() {
       //TODO: It would be nice to handle this with a router
       this.navBar = app.navBar = new Fauxton.NavBar();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/settings.json.default
----------------------------------------------------------------------
diff --git a/settings.json.default b/settings.json.default
index ad7e6b5..cb09eb2 100644
--- a/settings.json.default
+++ b/settings.json.default
@@ -1,5 +1,8 @@
 {
   "deps": [
+  { "name": "databases" },
+  { "name": "documents" },
+  { "name": "pouchdb" },
   { "name": "activetasks" },
   { "name": "config" },
   { "name": "logs" },


[42/52] [abbrv] 2029 Consolidate CSS/LESS class name usage to minimize custom-ness

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/settings.json.dev
----------------------------------------------------------------------
diff --git a/settings.json.dev b/settings.json.dev
new file mode 100644
index 0000000..e2df66b
--- /dev/null
+++ b/settings.json.dev
@@ -0,0 +1,59 @@
+{
+  "deps": [
+  { "name": "databases" },
+  { "name": "documents" },
+  { "name": "pouchdb" },
+  { "name": "activetasks" },
+  { "name": "config" },
+  { "name": "logs" },
+  { "name": "stats" },
+  { "name": "replication" },
+  { "name": "plugins" },
+  { "name": "contribute" },
+  { "name": "permissions" },
+  { "name": "compaction" },
+  { "name": "auth" },
+  { "name": "verifyinstall" },
+  { "name": "styletests" }
+  ],
+    "template": {
+      "development": {
+        "src": "assets/index.underscore",
+        "dest": "dist/debug/index.html",
+        "variables": {
+          "requirejs": "/assets/js/libs/require.js",
+          "css": "./css/index.css",
+          "base": null
+        },
+        "app": {
+          "root": "/",
+          "host": "../..",
+          "version": "1.0.dev"
+        }
+      },
+      "release": {
+        "src": "assets/index.underscore",
+        "dest": "dist/debug/index.html",
+        "variables": {
+          "requirejs": "./js/require.js",
+          "css": "./css/index.css",
+          "base": null
+        },
+        "app": {
+          "root": "/_utils/fauxton/",
+          "host": "../..",
+          "version": "1.0"
+        }
+      }
+    },
+
+    "couch_config": {
+      "fauxton": {
+        "db": "http://localhost:5984/fauxton",
+        "app": "./couchapp.js",
+        "options": {
+          "okay_if_missing": true
+        }
+      }
+    }
+}


[18/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Clean up active xhr


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/015829c2
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/015829c2
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/015829c2

Branch: refs/heads/import-master
Commit: 015829c25213066b37597cf9bc200e7099939986
Parents: 921ff62
Author: Garren Smith <ga...@gmail.com>
Authored: Thu Dec 19 15:52:22 2013 +0200
Committer: suelockwood <de...@apache.org>
Committed: Tue Jan 14 10:45:55 2014 -0500

----------------------------------------------------------------------
 app/api.js    | 41 ++++++++++++++++++++++++++++++++++++++---
 app/router.js |  2 +-
 2 files changed, 39 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/015829c2/app/api.js
----------------------------------------------------------------------
diff --git a/app/api.js b/app/api.js
index f423ef5..6d450de 100644
--- a/app/api.js
+++ b/app/api.js
@@ -290,6 +290,7 @@ function(app, Fauxton) {
     establish: function() {},
     route: function() {},
     roles: [],
+    _promises: [],
     initialize: function() {}
   }, {
 
@@ -319,7 +320,9 @@ function(app, Fauxton) {
       }
 
       triggerBroadcast('beforeEstablish');
-      FauxtonAPI.when(this.establish()).then(function(resp) {
+      var establishPromise = this.establish();
+      this.addPromise(establishPromise);
+      FauxtonAPI.when(establishPromise).then(function(resp) {
         triggerBroadcast('afterEstablish');
         _.each(routeObject.getViews(), function(view, selector) {
           if(view.hasRendered) { 
@@ -328,6 +331,8 @@ function(app, Fauxton) {
           }
 
           triggerBroadcast('beforeRender', view, selector);
+          var viewPromise = view.establish();
+          routeObject.addPromise(viewPromise);
           FauxtonAPI.when(view.establish()).then(function(resp) {
             masterLayout.setView(selector, view);
 
@@ -339,7 +344,7 @@ function(app, Fauxton) {
                 reason: resp
               };
 
-              if (resp) { 
+              if (resp && resp.responseText) { 
                 var errorText = JSON.parse(resp.responseText).reason;
                 FauxtonAPI.addNotification({
                   msg: 'An Error occurred: ' + errorText,
@@ -353,7 +358,7 @@ function(app, Fauxton) {
 
         });
       }.bind(this), function (resp) {
-          if (!resp) { return; }
+          if (!resp || !resp.responseText) { return; }
           FauxtonAPI.addNotification({
                 msg: 'An Error occurred' + JSON.parse(resp.responseText).reason,
                 type: 'error',
@@ -422,6 +427,36 @@ function(app, Fauxton) {
       }, this);
     },
 
+    addPromise: function (promise) {
+      if (_.isEmpty(promise)) { return; }
+
+      if (_.isArray(promise)) {
+        return _.each(promise, function (p) {
+          this._promises.push(p);
+        }, this);
+      }
+
+     this._promises.push(promise);
+    },
+
+    cleanup: function () {
+      this.removeViews();
+      this.rejectPromises();
+    },
+
+    rejectPromises: function () {
+      _.each(this._promises, function (promise) {
+        if (promise.state() === "resolved") { return; }
+        if (promise.abort) {
+          return promise.abort("Route change");
+        } 
+
+        promise.reject();
+      }, this);
+
+      this._promises = [];
+    },
+
     getRouteUrls: function () {
       return _.keys(this.get('routes'));
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/015829c2/app/router.js
----------------------------------------------------------------------
diff --git a/app/router.js b/app/router.js
index 7cf69ad..89c60cf 100644
--- a/app/router.js
+++ b/app/router.js
@@ -76,7 +76,7 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, LoadAddons) {
           authPromise.then(function () {
             if (!that.activeRouteObject || !that.activeRouteObject.hasRoute(route)) {
               if (that.activeRouteObject) {
-                that.activeRouteObject.removeViews();
+                that.activeRouteObject.cleanup();
               }
               that.activeRouteObject = new RouteObject(route, masterLayout, args);
             }


[38/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Make a ModalView to dry the code a bit


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/895cf6d2
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/895cf6d2
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/895cf6d2

Branch: refs/heads/import-master
Commit: 895cf6d26e36cb1cd8ce82c9e6204432a042c6a1
Parents: 470cdd5
Author: Simon Metson <si...@cloudant.com>
Authored: Mon Jan 27 11:38:35 2014 +0000
Committer: suelockwood <de...@apache.org>
Committed: Wed Jan 29 10:34:29 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js    | 94 ++---------------------------------
 app/addons/fauxton/components.js | 43 +++++++++++++++-
 2 files changed, 46 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/895cf6d2/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 455bfda..8ddf46f 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -113,15 +113,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     }
   });
 
-  Views.DeleteDBModal = FauxtonAPI.View.extend({
+  Views.DeleteDBModal = Components.ModalView.extend({
     template: "addons/documents/templates/delete_database_modal",
 
-    disableLoader: true,
-
-    initialize: function (options) {
-      _.bindAll(this);
-    },
-
     events: {
       "click a#delete-db-btn": "deleteDatabase",
       "submit #delete-db-check": "deleteDatabase"
@@ -155,43 +149,12 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
           clear: true
         });
       });
-    },
-
-    showModal: function () {
-      this.clear_error_msg();
-      this.$('.modal').modal();
-      // hack to get modal visible
-      $('.modal-backdrop').css('z-index',1025);
-    },
-
-    hideModal: function () {
-      this.$('.modal').modal('hide');
-    },
-
-    set_error_msg: function (msg) {
-      var text;
-      if (typeof(msg) == 'string') {
-        text = msg;
-      } else {
-        text = JSON.parse(msg.responseText).reason;
-      }
-      this.$('#modal-error').text(text).removeClass('hide');
-    },
-
-    clear_error_msg: function () {
-      this.$('#modal-error').text(' ').addClass('hide');
     }
   });
 
-  Views.UploadModal = FauxtonAPI.View.extend({
+  Views.UploadModal = Components.ModalView.extend({
     template: "addons/documents/templates/upload_modal",
 
-    disableLoader: true,
-
-    initialize: function (options) {
-      _.bindAll(this);
-    },
-
     events: {
       "click a#upload-btn": "uploadFile"
     },
@@ -247,39 +210,13 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.$('.progress').removeClass('hide');
     },
 
-    showModal: function () {
+    _showModal: function () {
       this.$('.bar').css({width: '0%'});
       this.$('.progress').addClass('hide');
-      this.clear_error_msg();
-      this.$('.modal').modal();
-      // hack to get modal visible
-      $('.modal-backdrop').css('z-index',1025);
-    },
-
-    hideModal: function () {
-      this.$('.modal').modal('hide');
-    },
-
-    set_error_msg: function (msg) {
-      var text;
-      if (typeof(msg) == 'string') {
-        text = msg;
-      } else {
-        text = JSON.parse(msg.responseText).reason;
-      }
-      this.$('#modal-error').text(text).removeClass('hide');
-    },
-
-    clear_error_msg: function () {
-      this.$('#modal-error').text(' ').addClass('hide');
-    },
-
-    serialize: function () {
-      return this.model.toJSON();
     }
   });
 
-  Views.DuplicateDocModal = FauxtonAPI.View.extend({
+  Views.DuplicateDocModal = Components.ModalView.extend({
     template: "addons/documents/templates/duplicate_doc_modal",
 
     initialize: function () {
@@ -325,30 +262,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
     setDefaultIdValue: function (id) {
       this.$('#dup-id').val(id);
-    },
-
-    hideModal: function () {
-      this.$('.modal').modal('hide');
-    },
-
-    set_error_msg: function (msg) {
-      var text;
-      if (typeof(msg) == 'string') {
-        text = msg;
-      } else {
-        text = JSON.parse(msg.responseText).reason;
-      }
-      this.$('#modal-error').text(text).removeClass('hide');
-    },
-
-    clear_error_msg: function () {
-      this.$('#modal-error').text(' ').addClass('hide');
-    },
-
-    serialize: function () {
-      return this.model.toJSON();
     }
-
   });
 
   Views.FieldEditorTabs = FauxtonAPI.View.extend({

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/895cf6d2/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index c26fc96..1f5e4ad 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -119,7 +119,7 @@ function(app, FauxtonAPI, ace, spin) {
     },
 
     pageStart: function () {
-      return (this.previousParams.length * this.pageLimit()) + 1; 
+      return (this.previousParams.length * this.pageLimit()) + 1;
 
     },
 
@@ -160,6 +160,47 @@ function(app, FauxtonAPI, ace, spin) {
 
   });
 
+  Components.ModalView = FauxtonAPI.View.extend({
+
+    disableLoader: true,
+
+    initialize: function (options) {
+      _.bindAll(this);
+    },
+
+    showModal: function () {
+      if (this._showModal){ this._showModal();}
+      this.clear_error_msg();
+      this.$('.modal').modal();
+      // hack to get modal visible
+      $('.modal-backdrop').css('z-index',1025);
+    },
+
+    hideModal: function () {
+      this.$('.modal').modal('hide');
+    },
+
+    set_error_msg: function (msg) {
+      var text;
+      if (typeof(msg) == 'string') {
+        text = msg;
+      } else {
+        text = JSON.parse(msg.responseText).reason;
+      }
+      this.$('#modal-error').text(text).removeClass('hide');
+    },
+
+    clear_error_msg: function () {
+      this.$('#modal-error').text(' ').addClass('hide');
+    },
+
+    serialize: function () {
+      if (this.model){
+        return this.model.toJSON();
+      }
+      return {};
+    }
+  });
 
   Components.DbSearchTypeahead = Components.Typeahead.extend({
     initialize: function (options) {


[30/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Beautify Code button for minified code entered by users. Allows them to unminify


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/77ce5d09
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/77ce5d09
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/77ce5d09

Branch: refs/heads/import-master
Commit: 77ce5d0943ce6bc8925081debc06ab0367d51a29
Parents: c67fc29
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 27 15:01:04 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 27 15:41:36 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/assets/less/documents.less |    4 +-
 app/addons/documents/templates/view_editor.html |    2 +
 app/addons/documents/views.js                   |   29 +-
 app/addons/fauxton/components.js                |    4 +
 app/config.js                                   |    1 +
 assets/js/plugins/beautify.js                   | 1639 ++++++++++++++++++
 6 files changed, 1674 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index 38fd792..68fc58d 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -19,4 +19,6 @@ tr.all-docs-item{
         top: 6px;
     }
 }
-
+button.beautify {
+	margin-top: 20px;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
index ddb5a0c..bf31ba2 100644
--- a/app/addons/documents/templates/view_editor.html
+++ b/app/addons/documents/templates/view_editor.html
@@ -41,6 +41,7 @@ the License.
             <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
             <% } else { %>
             <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
+            <button class="beautify beautify_map button hidden beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 
@@ -63,6 +64,7 @@ the License.
             <div class="js-editor" id="reduce-function"><%= langTemplates.reduce %></div>
             <% } else { %>
             <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
+            <button class="beautify beautify_reduce button hidden beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index d5319f3..bd89527 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -24,11 +24,13 @@ define([
        "resizeColumns",
 
        // Plugins
-       "plugins/prettify"
+       "plugins/beautify",
+       "plugins/prettify",
+
 
 ],
 
-function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns) {
+function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns, beautify) {
   var Views = {};
   Views.Tabs = FauxtonAPI.View.extend({
     template: "addons/documents/templates/tabs",
@@ -1246,7 +1248,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       "click button.delete": "deleteView",
       "change select#reduce-function-selector": "updateReduce",
       "click button.preview": "previewView",
-      "click #db-views-tabs-nav": 'toggleIndexNav'
+      "click #db-views-tabs-nav": 'toggleIndexNav',
+      "click .beautify_map":  "beautifyCode",
+      "click .beautify_reduce":  "beautifyCode"
     },
 
     langTemplates: {
@@ -1591,6 +1595,11 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         couchJSHINT: true
       });
       this.reduceEditor.render();
+
+      if (this.reduceEditor.getLines() === 1){
+        this.$('.beautify_reduce').removeClass("hidden");
+        $('.beautify-tooltip').tooltip();
+      }
     },
 
     beforeRender: function () {
@@ -1639,6 +1648,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         this.$('#index').hide();
         this.$('#index-nav').parent().removeClass('active');
       }
+
+
     },
 
     showEditors: function () {
@@ -1663,8 +1674,18 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
       this.mapEditor.editSaved();
       this.reduceEditor && this.reduceEditor.editSaved();
-    },
 
+      if (this.mapEditor.getLines() === 1){
+        this.$('.beautify_map').removeClass("hidden");
+        $('.beautify-tooltip').tooltip();
+      }
+    },
+    beautifyCode: function(e){
+      e.preventDefault();
+      var targetEditor = $(e.currentTarget).hasClass('beautify_reduce')?this.reduceEditor:this.mapEditor;
+      var beautifiedCode = beautify(targetEditor.getValue());
+      targetEditor.setValue(beautifiedCode);
+    },
     cleanup: function () {
       this.mapEditor && this.mapEditor.remove();
       this.reduceEditor && this.reduceEditor.remove();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index cda61c5..8b8aa5b 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -284,6 +284,10 @@ function(app, FauxtonAPI, ace) {
       this.editor.resize();
     },
 
+    getLines: function(){
+      return this.editor.getSession().getDocument().getLength();
+    },
+
     addCommands: function () {
       _.each(this.commands, function (command) {
         this.editor.commands.addCommand(command);

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/app/config.js
----------------------------------------------------------------------
diff --git a/app/config.js b/app/config.js
index 2977969..057523b 100644
--- a/app/config.js
+++ b/app/config.js
@@ -54,6 +54,7 @@ require.config({
     },
 
     "plugins/prettify": [],
+    "plugins/beautify": [],
 
     "plugins/jquery.form": ["jquery"]
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/77ce5d09/assets/js/plugins/beautify.js
----------------------------------------------------------------------
diff --git a/assets/js/plugins/beautify.js b/assets/js/plugins/beautify.js
new file mode 100644
index 0000000..e934fe3
--- /dev/null
+++ b/assets/js/plugins/beautify.js
@@ -0,0 +1,1639 @@
+/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
+/*
+
+  The MIT License (MIT)
+
+  Copyright (c) 2007-2013 Einar Lielmanis and contributors.
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+
+ JS Beautifier
+---------------
+
+
+  Written by Einar Lielmanis, <ei...@jsbeautifier.org>
+      http://jsbeautifier.org/
+
+  Originally converted to javascript by Vital, <vi...@gmail.com>
+  "End braces on own line" added by Chris J. Shull, <ch...@gmail.com>
+  Parsing improvements for brace-less statements by Liam Newman <bi...@gmail.com>
+
+
+  Usage:
+    js_beautify(js_source_text);
+    js_beautify(js_source_text, options);
+
+  The options are:
+    indent_size (default 4)          - indentation size,
+    indent_char (default space)      - character to indent with,
+    preserve_newlines (default true) - whether existing line breaks should be preserved,
+    max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,
+
+    jslint_happy (default false) - if true, then jslint-stricter mode is enforced.
+
+            jslint_happy   !jslint_happy
+            ---------------------------------
+             function ()      function()
+
+    brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
+            put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
+
+    space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)",
+
+    unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65"
+
+    wrap_line_length (default unlimited) - lines should wrap at next opportunity after this number of characters.
+          NOTE: This is not a hard limit. Lines will continue until a point where a newline would
+                be preserved if it were present.
+
+    e.g
+
+    js_beautify(js_source_text, {
+      'indent_size': 1,
+      'indent_char': '\t'
+    });
+
+*/
+
+
+(function() {
+    function js_beautify(js_source_text, options) {
+        "use strict";
+        var beautifier = new Beautifier(js_source_text, options);
+        return beautifier.beautify();
+    }
+
+    function Beautifier(js_source_text, options) {
+        "use strict";
+        var input, output_lines;
+        var token_text, token_type, last_type, last_last_text, indent_string;
+        var flags, previous_flags, flag_store;
+        var whitespace, wordchar, punct, parser_pos, line_starters, digits;
+        var prefix;
+        var input_wanted_newline;
+        var output_wrapped, output_space_before_token;
+        var input_length, n_newlines, whitespace_before_token;
+        var handlers, MODE, opt;
+        var preindent_string = '';
+
+        whitespace = "\n\r\t ".split('');
+        wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
+        digits = '0123456789'.split('');
+
+        punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';
+        punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers
+        punct = punct.split(' ');
+
+        // words which should always start on new line.
+        line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
+
+        MODE = {
+            BlockStatement: 'BlockStatement', // 'BLOCK'
+            Statement: 'Statement', // 'STATEMENT'
+            ObjectLiteral: 'ObjectLiteral', // 'OBJECT',
+            ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',
+            ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',
+            Conditional: 'Conditional', //'(COND-EXPRESSION)',
+            Expression: 'Expression' //'(EXPRESSION)'
+        };
+
+        handlers = {
+            'TK_START_EXPR': handle_start_expr,
+            'TK_END_EXPR': handle_end_expr,
+            'TK_START_BLOCK': handle_start_block,
+            'TK_END_BLOCK': handle_end_block,
+            'TK_WORD': handle_word,
+            'TK_SEMICOLON': handle_semicolon,
+            'TK_STRING': handle_string,
+            'TK_EQUALS': handle_equals,
+            'TK_OPERATOR': handle_operator,
+            'TK_COMMA': handle_comma,
+            'TK_BLOCK_COMMENT': handle_block_comment,
+            'TK_INLINE_COMMENT': handle_inline_comment,
+            'TK_COMMENT': handle_comment,
+            'TK_DOT': handle_dot,
+            'TK_UNKNOWN': handle_unknown
+        };
+
+        function create_flags(flags_base, mode) {
+            var next_indent_level = 0;
+            if (flags_base) {
+                next_indent_level = flags_base.indentation_level;
+                next_indent_level += (flags_base.var_line && flags_base.var_line_reindented) ? 1 : 0;
+                if (!just_added_newline() &&
+                    flags_base.line_indent_level > next_indent_level) {
+                    next_indent_level = flags_base.line_indent_level;
+                }
+            }
+
+            var next_flags = {
+                mode: mode,
+                parent: flags_base,
+                last_text: flags_base ? flags_base.last_text : '', // last token text
+                last_word: flags_base ? flags_base.last_word : '', // last 'TK_WORD' passed
+                var_line: false,
+                var_line_tainted: false,
+                var_line_reindented: false,
+                in_html_comment: false,
+                multiline_frame: false,
+                if_block: false,
+                do_block: false,
+                do_while: false,
+                in_case_statement: false, // switch(..){ INSIDE HERE }
+                in_case: false, // we're on the exact line with "case 0:"
+                case_body: false, // the indented case-action block
+                indentation_level: next_indent_level,
+                line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,
+                start_line_index: output_lines.length,
+                had_comment: false,
+                ternary_depth: 0
+            }
+            return next_flags;
+        }
+
+        // Using object instead of string to allow for later expansion of info about each line
+
+        function create_output_line() {
+            return {
+                text: []
+            };
+        }
+
+        // Some interpreters have unexpected results with foo = baz || bar;
+        options = options ? options : {};
+        opt = {};
+
+        // compatibility
+        if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {
+            options.jslint_happy = options.space_after_anon_function;
+        }
+        if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
+            opt.brace_style = options.braces_on_own_line ? "expand" : "collapse";
+        }
+        opt.brace_style = options.brace_style ? options.brace_style : (opt.brace_style ? opt.brace_style : "collapse");
+
+        // graceful handling of deprecated option
+        if (opt.brace_style === "expand-strict") {
+            opt.brace_style = "expand";
+        }
+
+
+        opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;
+        opt.indent_char = options.indent_char ? options.indent_char : ' ';
+        opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
+        opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;
+        opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);
+        opt.space_in_paren = (options.space_in_paren === undefined) ? false : options.space_in_paren;
+        opt.jslint_happy = (options.jslint_happy === undefined) ? false : options.jslint_happy;
+        opt.keep_array_indentation = (options.keep_array_indentation === undefined) ? false : options.keep_array_indentation;
+        opt.space_before_conditional = (options.space_before_conditional === undefined) ? true : options.space_before_conditional;
+        opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;
+        opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);
+        opt.e4x = (options.e4x === undefined) ? false : options.e4x;
+
+        if(options.indent_with_tabs){
+            opt.indent_char = '\t';
+            opt.indent_size = 1;
+        }
+
+        //----------------------------------
+        indent_string = '';
+        while (opt.indent_size > 0) {
+            indent_string += opt.indent_char;
+            opt.indent_size -= 1;
+        }
+
+        while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) {
+            preindent_string += js_source_text.charAt(0);
+            js_source_text = js_source_text.substring(1);
+        }
+        input = js_source_text;
+        // cache the source's length.
+        input_length = js_source_text.length;
+
+        last_type = 'TK_START_BLOCK'; // last token type
+        last_last_text = ''; // pre-last token text
+        output_lines = [create_output_line()];
+        output_wrapped = false;
+        output_space_before_token = false;
+        whitespace_before_token = [];
+
+        // Stack of parsing/formatting states, including MODE.
+        // We tokenize, parse, and output in an almost purely a forward-only stream of token input
+        // and formatted output.  This makes the beautifier less accurate than full parsers
+        // but also far more tolerant of syntax errors.
+        //
+        // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type
+        // MODE.BlockStatement on the the stack, even though it could be object literal.  If we later
+        // encounter a ":", we'll switch to to MODE.ObjectLiteral.  If we then see a ";",
+        // most full parsers would die, but the beautifier gracefully falls back to
+        // MODE.BlockStatement and continues on.
+        flag_store = [];
+        set_mode(MODE.BlockStatement);
+
+        parser_pos = 0;
+
+        this.beautify = function() {
+            /*jshint onevar:true */
+            var t, i, keep_whitespace, sweet_code;
+
+            while (true) {
+                t = get_next_token();
+                token_text = t[0];
+                token_type = t[1];
+
+                if (token_type === 'TK_EOF') {
+                    break;
+                }
+
+                keep_whitespace = opt.keep_array_indentation && is_array(flags.mode);
+                input_wanted_newline = n_newlines > 0;
+
+                if (keep_whitespace) {
+                    for (i = 0; i < n_newlines; i += 1) {
+                        print_newline(i > 0);
+                    }
+                } else {
+                    if (opt.max_preserve_newlines && n_newlines > opt.max_preserve_newlines) {
+                        n_newlines = opt.max_preserve_newlines;
+                    }
+
+                    if (opt.preserve_newlines) {
+                        if (n_newlines > 1) {
+                            print_newline();
+                            for (i = 1; i < n_newlines; i += 1) {
+                                print_newline(true);
+                            }
+                        }
+                    }
+                }
+
+                handlers[token_type]();
+
+                // The cleanest handling of inline comments is to treat them as though they aren't there.
+                // Just continue formatting and the behavior should be logical.
+                // Also ignore unknown tokens.  Again, this should result in better behavior.
+                if (token_type !== 'TK_INLINE_COMMENT' && token_type !== 'TK_COMMENT' &&
+                    token_type !== 'TK_BLOCK_COMMENT' && token_type !== 'TK_UNKNOWN') {
+                    last_last_text = flags.last_text;
+                    last_type = token_type;
+                    flags.last_text = token_text;
+                }
+                flags.had_comment = (token_type === 'TK_INLINE_COMMENT' || token_type === 'TK_COMMENT'
+                    || token_type === 'TK_BLOCK_COMMENT');
+            }
+
+
+            sweet_code = output_lines[0].text.join('');
+            for (var line_index = 1; line_index < output_lines.length; line_index++) {
+                sweet_code += '\n' + output_lines[line_index].text.join('');
+            }
+            sweet_code = sweet_code.replace(/[\r\n ]+$/, '');
+            return sweet_code;
+        };
+
+        function trim_output(eat_newlines) {
+            eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
+
+            if (output_lines.length) {
+                trim_output_line(output_lines[output_lines.length - 1], eat_newlines);
+
+                while (eat_newlines && output_lines.length > 1 &&
+                    output_lines[output_lines.length - 1].text.length === 0) {
+                    output_lines.pop();
+                    trim_output_line(output_lines[output_lines.length - 1], eat_newlines);
+                }
+            }
+        }
+
+        function trim_output_line(line) {
+            while (line.text.length &&
+                (line.text[line.text.length - 1] === ' ' ||
+                    line.text[line.text.length - 1] === indent_string ||
+                    line.text[line.text.length - 1] === preindent_string)) {
+                line.text.pop();
+            }
+        }
+
+        function trim(s) {
+            return s.replace(/^\s+|\s+$/g, '');
+        }
+
+        // we could use just string.split, but
+        // IE doesn't like returning empty strings
+
+        function split_newlines(s) {
+            //return s.split(/\x0d\x0a|\x0a/);
+
+            s = s.replace(/\x0d/g, '');
+            var out = [],
+                idx = s.indexOf("\n");
+            while (idx !== -1) {
+                out.push(s.substring(0, idx));
+                s = s.substring(idx + 1);
+                idx = s.indexOf("\n");
+            }
+            if (s.length) {
+                out.push(s);
+            }
+            return out;
+        }
+
+        function just_added_newline() {
+            var line = output_lines[output_lines.length - 1];
+            return line.text.length === 0;
+        }
+
+        function just_added_blankline() {
+            if (just_added_newline()) {
+                if (output_lines.length === 1) {
+                    return true; // start of the file and newline = blank
+                }
+
+                var line = output_lines[output_lines.length - 2];
+                return line.text.length === 0;
+            }
+            return false;
+        }
+
+        function allow_wrap_or_preserved_newline(force_linewrap) {
+            force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;
+            if (opt.wrap_line_length && !force_linewrap) {
+                var line = output_lines[output_lines.length - 1];
+                var proposed_line_length = 0;
+                // never wrap the first token of a line.
+                if (line.text.length > 0) {
+                    proposed_line_length = line.text.join('').length + token_text.length +
+                        (output_space_before_token ? 1 : 0);
+                    if (proposed_line_length >= opt.wrap_line_length) {
+                        force_linewrap = true;
+                    }
+                }
+            }
+            if (((opt.preserve_newlines && input_wanted_newline) || force_linewrap) && !just_added_newline()) {
+                print_newline(false, true);
+
+                // Expressions and array literals already indent their contents.
+                if (!(is_array(flags.mode) || is_expression(flags.mode))) {
+                    output_wrapped = true;
+                }
+            }
+        }
+
+        function print_newline(force_newline, preserve_statement_flags) {
+            output_wrapped = false;
+            output_space_before_token = false;
+
+            if (!preserve_statement_flags) {
+                if (flags.last_text !== ';') {
+                    while (flags.mode === MODE.Statement && !flags.if_block && !flags.do_block) {
+                        restore_mode();
+                    }
+                }
+            }
+
+            if (output_lines.length === 1 && just_added_newline()) {
+                return; // no newline on start of file
+            }
+
+            if (force_newline || !just_added_newline()) {
+                flags.multiline_frame = true;
+                output_lines.push(create_output_line());
+            }
+        }
+
+        function print_token_line_indentation() {
+            if (just_added_newline()) {
+                var line = output_lines[output_lines.length - 1];
+                if (opt.keep_array_indentation && is_array(flags.mode) && input_wanted_newline) {
+                    // prevent removing of this whitespace as redundant
+                    line.text.push('');
+                    for (var i = 0; i < whitespace_before_token.length; i += 1) {
+                        line.text.push(whitespace_before_token[i]);
+                    }
+                } else {
+                    if (preindent_string) {
+                        line.text.push(preindent_string);
+                    }
+
+                    print_indent_string(flags.indentation_level +
+                        (flags.var_line && flags.var_line_reindented ? 1 : 0) +
+                        (output_wrapped ? 1 : 0));
+                }
+            }
+        }
+
+        function print_indent_string(level) {
+            // Never indent your first output indent at the start of the file
+            if (output_lines.length > 1) {
+                var line = output_lines[output_lines.length - 1];
+
+                flags.line_indent_level = level;
+                for (var i = 0; i < level; i += 1) {
+                    line.text.push(indent_string);
+                }
+            }
+        }
+
+        function print_token_space_before() {
+            var line = output_lines[output_lines.length - 1];
+            if (output_space_before_token && line.text.length) {
+                var last_output = line.text[line.text.length - 1];
+                if (last_output !== ' ' && last_output !== indent_string) { // prevent occassional duplicate space
+                    line.text.push(' ');
+                }
+            }
+        }
+
+        function print_token(printable_token) {
+            printable_token = printable_token || token_text;
+            print_token_line_indentation();
+            output_wrapped = false;
+            print_token_space_before();
+            output_space_before_token = false;
+            output_lines[output_lines.length - 1].text.push(printable_token);
+        }
+
+        function indent() {
+            flags.indentation_level += 1;
+        }
+
+        function deindent() {
+            if (flags.indentation_level > 0 &&
+                ((!flags.parent) || flags.indentation_level > flags.parent.indentation_level))
+                flags.indentation_level -= 1;
+        }
+
+        function remove_redundant_indentation(frame) {
+            // This implementation is effective but has some issues:
+            //     - less than great performance due to array splicing
+            //     - can cause line wrap to happen too soon due to indent removal
+            //           after wrap points are calculated
+            // These issues are minor compared to ugly indentation.
+
+            if (frame.multiline_frame) return;
+
+            // remove one indent from each line inside this section
+            var index = frame.start_line_index;
+            var splice_index = 0;
+            var line;
+
+            while (index < output_lines.length) {
+                line = output_lines[index];
+                index++;
+
+                // skip empty lines
+                if (line.text.length === 0) {
+                    continue;
+                }
+
+                // skip the preindent string if present
+                if (preindent_string && line.text[0] === preindent_string) {
+                    splice_index = 1;
+                } else {
+                    splice_index = 0;
+                }
+
+                // remove one indent, if present
+                if (line.text[splice_index] === indent_string) {
+                    line.text.splice(splice_index, 1);
+                }
+            }
+        }
+
+        function set_mode(mode) {
+            if (flags) {
+                flag_store.push(flags);
+                previous_flags = flags;
+            } else {
+                previous_flags = create_flags(null, mode);
+            }
+
+            flags = create_flags(previous_flags, mode);
+        }
+
+        function is_array(mode) {
+            return mode === MODE.ArrayLiteral;
+        }
+
+        function is_expression(mode) {
+            return in_array(mode, [MODE.Expression, MODE.ForInitializer, MODE.Conditional]);
+        }
+
+        function restore_mode() {
+            if (flag_store.length > 0) {
+                previous_flags = flags;
+                flags = flag_store.pop();
+            }
+        }
+
+        function start_of_object_property() {
+            return flags.mode === MODE.ObjectLiteral && flags.last_text === ':' &&
+                flags.ternary_depth === 0;
+        }
+
+        function start_of_statement() {
+            if (
+                (flags.last_text === 'do' ||
+                    (flags.last_text === 'else' && token_text !== 'if') ||
+                    (last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)))) {
+                // Issue #276:
+                // If starting a new statement with [if, for, while, do], push to a new line.
+                // if (a) if (b) if(c) d(); else e(); else f();
+                allow_wrap_or_preserved_newline(
+                    in_array(token_text, ['do', 'for', 'if', 'while']));
+
+                set_mode(MODE.Statement);
+                // Issue #275:
+                // If starting on a newline, all of a statement should be indented.
+                // if not, use line wrapping logic for indent.
+                if (just_added_newline()) {
+                    indent();
+                    output_wrapped = false;
+                }
+                return true;
+            }
+            return false;
+        }
+
+        function all_lines_start_with(lines, c) {
+            for (var i = 0; i < lines.length; i++) {
+                var line = trim(lines[i]);
+                if (line.charAt(0) !== c) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        function is_special_word(word) {
+            return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);
+        }
+
+        function in_array(what, arr) {
+            for (var i = 0; i < arr.length; i += 1) {
+                if (arr[i] === what) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function unescape_string(s) {
+            var esc = false,
+                out = '',
+                pos = 0,
+                s_hex = '',
+                escaped = 0,
+                c;
+
+            while (esc || pos < s.length) {
+
+                c = s.charAt(pos);
+                pos++;
+
+                if (esc) {
+                    esc = false;
+                    if (c === 'x') {
+                        // simple hex-escape \x24
+                        s_hex = s.substr(pos, 2);
+                        pos += 2;
+                    } else if (c === 'u') {
+                        // unicode-escape, \u2134
+                        s_hex = s.substr(pos, 4);
+                        pos += 4;
+                    } else {
+                        // some common escape, e.g \n
+                        out += '\\' + c;
+                        continue;
+                    }
+                    if (!s_hex.match(/^[0123456789abcdefABCDEF]+$/)) {
+                        // some weird escaping, bail out,
+                        // leaving whole string intact
+                        return s;
+                    }
+
+                    escaped = parseInt(s_hex, 16);
+
+                    if (escaped >= 0x00 && escaped < 0x20) {
+                        // leave 0x00...0x1f escaped
+                        if (c === 'x') {
+                            out += '\\x' + s_hex;
+                        } else {
+                            out += '\\u' + s_hex;
+                        }
+                        continue;
+                    } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {
+                        // single-quote, apostrophe, backslash - escape these
+                        out += '\\' + String.fromCharCode(escaped);
+                    } else if (c === 'x' && escaped > 0x7e && escaped <= 0xff) {
+                        // we bail out on \x7f..\xff,
+                        // leaving whole string escaped,
+                        // as it's probably completely binary
+                        return s;
+                    } else {
+                        out += String.fromCharCode(escaped);
+                    }
+                } else if (c === '\\') {
+                    esc = true;
+                } else {
+                    out += c;
+                }
+            }
+            return out;
+        }
+
+        function is_next(find) {
+            var local_pos = parser_pos;
+            var c = input.charAt(local_pos);
+            while (in_array(c, whitespace) && c !== find) {
+                local_pos++;
+                if (local_pos >= input_length) {
+                    return false;
+                }
+                c = input.charAt(local_pos);
+            }
+            return c === find;
+        }
+
+        function get_next_token() {
+            var i, resulting_string;
+
+            n_newlines = 0;
+
+            if (parser_pos >= input_length) {
+                return ['', 'TK_EOF'];
+            }
+
+            input_wanted_newline = false;
+            whitespace_before_token = [];
+
+            var c = input.charAt(parser_pos);
+            parser_pos += 1;
+
+            while (in_array(c, whitespace)) {
+
+                if (c === '\n') {
+                    n_newlines += 1;
+                    whitespace_before_token = [];
+                } else if (n_newlines) {
+                    if (c === indent_string) {
+                        whitespace_before_token.push(indent_string);
+                    } else if (c !== '\r') {
+                        whitespace_before_token.push(' ');
+                    }
+                }
+
+                if (parser_pos >= input_length) {
+                    return ['', 'TK_EOF'];
+                }
+
+                c = input.charAt(parser_pos);
+                parser_pos += 1;
+            }
+
+            if (in_array(c, wordchar)) {
+                if (parser_pos < input_length) {
+                    while (in_array(input.charAt(parser_pos), wordchar)) {
+                        c += input.charAt(parser_pos);
+                        parser_pos += 1;
+                        if (parser_pos === input_length) {
+                            break;
+                        }
+                    }
+                }
+
+                // small and surprisingly unugly hack for 1E-10 representation
+                if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {
+
+                    var sign = input.charAt(parser_pos);
+                    parser_pos += 1;
+
+                    var t = get_next_token();
+                    c += sign + t[0];
+                    return [c, 'TK_WORD'];
+                }
+
+                if (c === 'in') { // hack for 'in' operator
+                    return [c, 'TK_OPERATOR'];
+                }
+                return [c, 'TK_WORD'];
+            }
+
+            if (c === '(' || c === '[') {
+                return [c, 'TK_START_EXPR'];
+            }
+
+            if (c === ')' || c === ']') {
+                return [c, 'TK_END_EXPR'];
+            }
+
+            if (c === '{') {
+                return [c, 'TK_START_BLOCK'];
+            }
+
+            if (c === '}') {
+                return [c, 'TK_END_BLOCK'];
+            }
+
+            if (c === ';') {
+                return [c, 'TK_SEMICOLON'];
+            }
+
+            if (c === '/') {
+                var comment = '';
+                // peek for comment /* ... */
+                var inline_comment = true;
+                if (input.charAt(parser_pos) === '*') {
+                    parser_pos += 1;
+                    if (parser_pos < input_length) {
+                        while (parser_pos < input_length && !(input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {
+                            c = input.charAt(parser_pos);
+                            comment += c;
+                            if (c === "\n" || c === "\r") {
+                                inline_comment = false;
+                            }
+                            parser_pos += 1;
+                            if (parser_pos >= input_length) {
+                                break;
+                            }
+                        }
+                    }
+                    parser_pos += 2;
+                    if (inline_comment && n_newlines === 0) {
+                        return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
+                    } else {
+                        return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
+                    }
+                }
+                // peek for comment // ...
+                if (input.charAt(parser_pos) === '/') {
+                    comment = c;
+                    while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
+                        comment += input.charAt(parser_pos);
+                        parser_pos += 1;
+                        if (parser_pos >= input_length) {
+                            break;
+                        }
+                    }
+                    return [comment, 'TK_COMMENT'];
+                }
+
+            }
+
+
+            if (c === "'" || c === '"' || // string
+                (
+                    (c === '/') || // regexp
+                    (opt.e4x && c === "<" && input.slice(parser_pos - 1).match(/^<([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])\s*([-a-zA-Z:0-9_.]+=('[^']*'|"[^"]*"|{[^{}]*})\s*)*\/?\s*>/)) // xml
+                ) && ( // regex and xml can only appear in specific locations during parsing
+                    (last_type === 'TK_WORD' && is_special_word(flags.last_text)) ||
+                    (last_type === 'TK_END_EXPR' && in_array(previous_flags.mode, [MODE.Conditional, MODE.ForInitializer])) ||
+                    (in_array(last_type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',
+                        'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'
+                    ]))
+                )) {
+
+                var sep = c,
+                    esc = false,
+                    has_char_escapes = false;
+
+                resulting_string = c;
+
+                if (parser_pos < input_length) {
+                    if (sep === '/') {
+                        //
+                        // handle regexp
+                        //
+                        var in_char_class = false;
+                        while (esc || in_char_class || input.charAt(parser_pos) !== sep) {
+                            resulting_string += input.charAt(parser_pos);
+                            if (!esc) {
+                                esc = input.charAt(parser_pos) === '\\';
+                                if (input.charAt(parser_pos) === '[') {
+                                    in_char_class = true;
+                                } else if (input.charAt(parser_pos) === ']') {
+                                    in_char_class = false;
+                                }
+                            } else {
+                                esc = false;
+                            }
+                            parser_pos += 1;
+                            if (parser_pos >= input_length) {
+                                // incomplete string/rexp when end-of-file reached.
+                                // bail out with what had been received so far.
+                                return [resulting_string, 'TK_STRING'];
+                            }
+                        }
+                    } else if (opt.e4x && sep === '<') {
+                        //
+                        // handle e4x xml literals
+                        //
+                        var xmlRegExp = /<(\/?)([-a-zA-Z:0-9_.]+|{[^{}]*}|!\[CDATA\[[\s\S]*?\]\])\s*([-a-zA-Z:0-9_.]+=('[^']*'|"[^"]*"|{[^{}]*})\s*)*(\/?)\s*>/g;
+                        var xmlStr = input.slice(parser_pos - 1);
+                        var match = xmlRegExp.exec(xmlStr);
+                        if (match && match.index === 0) {
+                            var rootTag = match[2];
+                            var depth = 0;
+                            while (match) {
+                                var isEndTag = !! match[1];
+                                var tagName = match[2];
+                                var isSingletonTag = ( !! match[match.length - 1]) || (tagName.slice(0, 8) === "![CDATA[");
+                                if (tagName === rootTag && !isSingletonTag) {
+                                    if (isEndTag) {
+                                        --depth;
+                                    } else {
+                                        ++depth;
+                                    }
+                                }
+                                if (depth <= 0) {
+                                    break;
+                                }
+                                match = xmlRegExp.exec(xmlStr);
+                            }
+                            var xmlLength = match ? match.index + match[0].length : xmlStr.length;
+                            parser_pos += xmlLength - 1;
+                            return [xmlStr.slice(0, xmlLength), "TK_STRING"];
+                        }
+                    } else {
+                        //
+                        // handle string
+                        //
+                        while (esc || input.charAt(parser_pos) !== sep) {
+                            resulting_string += input.charAt(parser_pos);
+                            if (esc) {
+                                if (input.charAt(parser_pos) === 'x' || input.charAt(parser_pos) === 'u') {
+                                    has_char_escapes = true;
+                                }
+                                esc = false;
+                            } else {
+                                esc = input.charAt(parser_pos) === '\\';
+                            }
+                            parser_pos += 1;
+                            if (parser_pos >= input_length) {
+                                // incomplete string/rexp when end-of-file reached.
+                                // bail out with what had been received so far.
+                                return [resulting_string, 'TK_STRING'];
+                            }
+                        }
+
+                    }
+                }
+
+                parser_pos += 1;
+                resulting_string += sep;
+
+                if (has_char_escapes && opt.unescape_strings) {
+                    resulting_string = unescape_string(resulting_string);
+                }
+
+                if (sep === '/') {
+                    // regexps may have modifiers /regexp/MOD , so fetch those, too
+                    while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {
+                        resulting_string += input.charAt(parser_pos);
+                        parser_pos += 1;
+                    }
+                }
+                return [resulting_string, 'TK_STRING'];
+            }
+
+            if (c === '#') {
+
+
+                if (output_lines.length === 1 && output_lines[0].text.length === 0 &&
+                    input.charAt(parser_pos) === '!') {
+                    // shebang
+                    resulting_string = c;
+                    while (parser_pos < input_length && c !== '\n') {
+                        c = input.charAt(parser_pos);
+                        resulting_string += c;
+                        parser_pos += 1;
+                    }
+                    return [trim(resulting_string) + '\n', 'TK_UNKNOWN'];
+                }
+
+
+
+                // Spidermonkey-specific sharp variables for circular references
+                // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
+                // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
+                var sharp = '#';
+                if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {
+                    do {
+                        c = input.charAt(parser_pos);
+                        sharp += c;
+                        parser_pos += 1;
+                    } while (parser_pos < input_length && c !== '#' && c !== '=');
+                    if (c === '#') {
+                        //
+                    } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {
+                        sharp += '[]';
+                        parser_pos += 2;
+                    } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {
+                        sharp += '{}';
+                        parser_pos += 2;
+                    }
+                    return [sharp, 'TK_WORD'];
+                }
+            }
+
+            if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
+                parser_pos += 3;
+                c = '<!--';
+                while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
+                    c += input.charAt(parser_pos);
+                    parser_pos++;
+                }
+                flags.in_html_comment = true;
+                return [c, 'TK_COMMENT'];
+            }
+
+            if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {
+                flags.in_html_comment = false;
+                parser_pos += 2;
+                return ['-->', 'TK_COMMENT'];
+            }
+
+            if (c === '.') {
+                return [c, 'TK_DOT'];
+            }
+
+            if (in_array(c, punct)) {
+                while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {
+                    c += input.charAt(parser_pos);
+                    parser_pos += 1;
+                    if (parser_pos >= input_length) {
+                        break;
+                    }
+                }
+
+                if (c === ',') {
+                    return [c, 'TK_COMMA'];
+                } else if (c === '=') {
+                    return [c, 'TK_EQUALS'];
+                } else {
+                    return [c, 'TK_OPERATOR'];
+                }
+            }
+
+            return [c, 'TK_UNKNOWN'];
+        }
+
+        function handle_start_expr() {
+            if (start_of_statement()) {
+                // The conditional starts the statement if appropriate.
+            }
+
+            var next_mode = MODE.Expression;
+            if (token_text === '[') {
+
+                if (last_type === 'TK_WORD' || flags.last_text === ')') {
+                    // this is array index specifier, break immediately
+                    // a[x], fn()[x]
+                    if (in_array(flags.last_text, line_starters)) {
+                        output_space_before_token = true;
+                    }
+                    set_mode(next_mode);
+                    print_token();
+                    indent();
+                    if (opt.space_in_paren) {
+                        output_space_before_token = true;
+                    }
+                    return;
+                }
+
+                next_mode = MODE.ArrayLiteral;
+                if (is_array(flags.mode)) {
+                    if (flags.last_text === '[' ||
+                        (flags.last_text === ',' && (last_last_text === ']' || last_last_text === '}'))) {
+                        // ], [ goes to new line
+                        // }, [ goes to new line
+                        if (!opt.keep_array_indentation) {
+                            print_newline();
+                        }
+                    }
+                }
+
+            } else {
+                if (flags.last_text === 'for') {
+                    next_mode = MODE.ForInitializer;
+                } else if (in_array(flags.last_text, ['if', 'while'])) {
+                    next_mode = MODE.Conditional;
+                } else {
+                    // next_mode = MODE.Expression;
+                }
+            }
+
+            if (flags.last_text === ';' || last_type === 'TK_START_BLOCK') {
+                print_newline();
+            } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || flags.last_text === '.') {
+                // TODO: Consider whether forcing this is required.  Review failing tests when removed.
+                allow_wrap_or_preserved_newline(input_wanted_newline);
+                output_wrapped = false;
+                // do nothing on (( and )( and ][ and ]( and .(
+            } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
+                output_space_before_token = true;
+            } else if (flags.last_word === 'function' || flags.last_word === 'typeof') {
+                // function() vs function ()
+                if (opt.jslint_happy) {
+                    output_space_before_token = true;
+                }
+            } else if (in_array(flags.last_text, line_starters) || flags.last_text === 'catch') {
+                if (opt.space_before_conditional) {
+                    output_space_before_token = true;
+                }
+            }
+
+            // Support of this kind of newline preservation.
+            // a = (b &&
+            //     (c || d));
+            if (token_text === '(') {
+                if (last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                    if (!start_of_object_property()) {
+                        allow_wrap_or_preserved_newline();
+                    }
+                }
+            }
+
+            set_mode(next_mode);
+            print_token();
+            if (opt.space_in_paren) {
+                output_space_before_token = true;
+            }
+
+            // In all cases, if we newline while inside an expression it should be indented.
+            indent();
+        }
+
+        function handle_end_expr() {
+            // statements inside expressions are not valid syntax, but...
+            // statements must all be closed when their container closes
+            while (flags.mode === MODE.Statement) {
+                restore_mode();
+            }
+
+            if (token_text === ']' && is_array(flags.mode) && flags.multiline_frame && !opt.keep_array_indentation) {
+                print_newline();
+            }
+
+            if (flags.multiline_frame) {
+                allow_wrap_or_preserved_newline();
+            }
+            if (opt.space_in_paren) {
+                if (last_type === 'TK_START_EXPR') {
+                    // () [] no inner space in empty parens like these, ever, ref #320
+                    trim_output();
+                    output_space_before_token = false;
+                } else {
+                    output_space_before_token = true;
+                }
+            }
+            if (token_text === ']' && opt.keep_array_indentation) {
+                print_token();
+                restore_mode();
+            } else {
+                restore_mode();
+                print_token();
+            }
+            remove_redundant_indentation(previous_flags);
+
+            // do {} while () // no statement required after
+            if (flags.do_while && previous_flags.mode === MODE.Conditional) {
+                previous_flags.mode = MODE.Expression;
+                flags.do_block = false;
+                flags.do_while = false;
+
+            }
+        }
+
+        function handle_start_block() {
+            set_mode(MODE.BlockStatement);
+
+            var empty_braces = is_next('}');
+            var empty_anonymous_function = empty_braces && flags.last_word === 'function' &&
+                last_type === 'TK_END_EXPR';
+
+            if (opt.brace_style === "expand") {
+                if (last_type !== 'TK_OPERATOR' &&
+                    (empty_anonymous_function ||
+                        last_type === 'TK_EQUALS' ||
+                        (is_special_word(flags.last_text) && flags.last_text !== 'else'))) {
+                    output_space_before_token = true;
+                } else {
+                    print_newline();
+                }
+            } else { // collapse
+                if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
+                    if (last_type === 'TK_START_BLOCK') {
+                        print_newline();
+                    } else {
+                        output_space_before_token = true;
+                    }
+                } else {
+                    // if TK_OPERATOR or TK_START_EXPR
+                    if (is_array(previous_flags.mode) && flags.last_text === ',') {
+                        if (last_last_text === '}') {
+                            // }, { in array context
+                            output_space_before_token = true;
+                        } else {
+                            print_newline(); // [a, b, c, {
+                        }
+                    }
+                }
+            }
+            print_token();
+            indent();
+        }
+
+        function handle_end_block() {
+            // statements must all be closed when their container closes
+            while (flags.mode === MODE.Statement) {
+                restore_mode();
+            }
+            var empty_braces = last_type === 'TK_START_BLOCK';
+
+            if (opt.brace_style === "expand") {
+                if (!empty_braces) {
+                    print_newline();
+                }
+            } else {
+                // skip {}
+                if (!empty_braces) {
+                    if (is_array(flags.mode) && opt.keep_array_indentation) {
+                        // we REALLY need a newline here, but newliner would skip that
+                        opt.keep_array_indentation = false;
+                        print_newline();
+                        opt.keep_array_indentation = true;
+
+                    } else {
+                        print_newline();
+                    }
+                }
+            }
+            restore_mode();
+            print_token();
+        }
+
+        function handle_word() {
+            if (start_of_statement()) {
+                // The conditional starts the statement if appropriate.
+            } else if (input_wanted_newline && !is_expression(flags.mode) &&
+                (last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&
+                last_type !== 'TK_EQUALS' &&
+                (opt.preserve_newlines || flags.last_text !== 'var')) {
+
+                print_newline();
+            }
+
+            if (flags.do_block && !flags.do_while) {
+                if (token_text === 'while') {
+                    // do {} ## while ()
+                    output_space_before_token = true;
+                    print_token();
+                    output_space_before_token = true;
+                    flags.do_while = true;
+                    return;
+                } else {
+                    // do {} should always have while as the next word.
+                    // if we don't see the expected while, recover
+                    print_newline();
+                    flags.do_block = false;
+                }
+            }
+
+            // if may be followed by else, or not
+            // Bare/inline ifs are tricky
+            // Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();
+            if (flags.if_block) {
+                if (token_text !== 'else') {
+                    while (flags.mode === MODE.Statement) {
+                        restore_mode();
+                    }
+                    flags.if_block = false;
+                }
+            }
+
+            if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {
+                print_newline();
+                if (flags.case_body || opt.jslint_happy) {
+                    // switch cases following one another
+                    deindent();
+                    flags.case_body = false;
+                }
+                print_token();
+                flags.in_case = true;
+                flags.in_case_statement = true;
+                return;
+            }
+
+            if (token_text === 'function') {
+                if (flags.var_line && last_type !== 'TK_EQUALS') {
+                    flags.var_line_reindented = true;
+                }
+                if (in_array(flags.last_text, ['}', ';']) || (just_added_newline() && ! in_array(flags.last_text, ['{', ':', '=', ',']))) {
+                    // make sure there is a nice clean space of at least one blank line
+                    // before a new function definition
+                    if ( ! just_added_blankline() && ! flags.had_comment) {
+                        print_newline();
+                        print_newline(true);
+                    }
+                }
+                if (last_type === 'TK_WORD') {
+                    if (flags.last_text === 'get' || flags.last_text === 'set' || flags.last_text === 'new' || flags.last_text === 'return') {
+                        output_space_before_token = true;
+                    } else {
+                        print_newline();
+                    }
+                } else if (last_type === 'TK_OPERATOR' || flags.last_text === '=') {
+                    // foo = function
+                    output_space_before_token = true;
+                } else if (is_expression(flags.mode)) {
+                    // (function
+                } else {
+                    print_newline();
+                }
+            }
+
+            if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                if (!start_of_object_property()) {
+                    allow_wrap_or_preserved_newline();
+                }
+            }
+
+            if (token_text === 'function') {
+                print_token();
+                flags.last_word = token_text;
+                return;
+            }
+
+            prefix = 'NONE';
+
+            if (last_type === 'TK_END_BLOCK') {
+                if (!in_array(token_text, ['else', 'catch', 'finally'])) {
+                    prefix = 'NEWLINE';
+                } else {
+                    if (opt.brace_style === "expand" || opt.brace_style === "end-expand") {
+                        prefix = 'NEWLINE';
+                    } else {
+                        prefix = 'SPACE';
+                        output_space_before_token = true;
+                    }
+                }
+            } else if (last_type === 'TK_SEMICOLON' && flags.mode === MODE.BlockStatement) {
+                // TODO: Should this be for STATEMENT as well?
+                prefix = 'NEWLINE';
+            } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
+                prefix = 'SPACE';
+            } else if (last_type === 'TK_STRING') {
+                prefix = 'NEWLINE';
+            } else if (last_type === 'TK_WORD') {
+                prefix = 'SPACE';
+            } else if (last_type === 'TK_START_BLOCK') {
+                prefix = 'NEWLINE';
+            } else if (last_type === 'TK_END_EXPR') {
+                output_space_before_token = true;
+                prefix = 'NEWLINE';
+            }
+
+            if (in_array(token_text, line_starters) && flags.last_text !== ')') {
+                if (flags.last_text === 'else') {
+                    prefix = 'SPACE';
+                } else {
+                    prefix = 'NEWLINE';
+                }
+
+            }
+
+            if (in_array(token_text, ['else', 'catch', 'finally'])) {
+                if (last_type !== 'TK_END_BLOCK' || opt.brace_style === "expand" || opt.brace_style === "end-expand") {
+                    print_newline();
+                } else {
+                    trim_output(true);
+                    var line = output_lines[output_lines.length - 1];
+                    // If we trimmed and there's something other than a close block before us
+                    // put a newline back in.  Handles '} // comment' scenario.
+                    if (line.text[line.text.length - 1] !== '}') {
+                        print_newline();
+                    }
+                    output_space_before_token = true;
+                }
+            } else if (prefix === 'NEWLINE') {
+                if (is_special_word(flags.last_text)) {
+                    // no newline between 'return nnn'
+                    output_space_before_token = true;
+                } else if (last_type !== 'TK_END_EXPR') {
+                    if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && flags.last_text !== ':') {
+                        // no need to force newline on 'var': for (var x = 0...)
+                        if (token_text === 'if' && flags.last_word === 'else' && flags.last_text !== '{') {
+                            // no newline for } else if {
+                            output_space_before_token = true;
+                        } else {
+                            flags.var_line = false;
+                            flags.var_line_reindented = false;
+                            print_newline();
+                        }
+                    }
+                } else if (in_array(token_text, line_starters) && flags.last_text !== ')') {
+                    flags.var_line = false;
+                    flags.var_line_reindented = false;
+                    print_newline();
+                }
+            } else if (is_array(flags.mode) && flags.last_text === ',' && last_last_text === '}') {
+                print_newline(); // }, in lists get a newline treatment
+            } else if (prefix === 'SPACE') {
+                output_space_before_token = true;
+            }
+            print_token();
+            flags.last_word = token_text;
+
+            if (token_text === 'var') {
+                flags.var_line = true;
+                flags.var_line_reindented = false;
+                flags.var_line_tainted = false;
+            }
+
+            if (token_text === 'do') {
+                flags.do_block = true;
+            }
+
+            if (token_text === 'if') {
+                flags.if_block = true;
+            }
+        }
+
+        function handle_semicolon() {
+            if (start_of_statement()) {
+                // The conditional starts the statement if appropriate.
+                // Semicolon can be the start (and end) of a statement
+                output_space_before_token = false;
+            }
+            while (flags.mode === MODE.Statement && !flags.if_block && !flags.do_block) {
+                restore_mode();
+            }
+            print_token();
+            flags.var_line = false;
+            flags.var_line_reindented = false;
+            if (flags.mode === MODE.ObjectLiteral) {
+                // if we're in OBJECT mode and see a semicolon, its invalid syntax
+                // recover back to treating this as a BLOCK
+                flags.mode = MODE.BlockStatement;
+            }
+        }
+
+        function handle_string() {
+            if (start_of_statement()) {
+                // The conditional starts the statement if appropriate.
+                // One difference - strings want at least a space before
+                output_space_before_token = true;
+            } else if (last_type === 'TK_WORD') {
+                output_space_before_token = true;
+            } else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
+                if (!start_of_object_property()) {
+                    allow_wrap_or_preserved_newline();
+                }
+            } else {
+                print_newline();
+            }
+            print_token();
+        }
+
+        function handle_equals() {
+            if (flags.var_line) {
+                // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
+                flags.var_line_tainted = true;
+            }
+            output_space_before_token = true;
+            print_token();
+            output_space_before_token = true;
+        }
+
+        function handle_comma() {
+            if (flags.var_line) {
+                if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK') {
+                    // do not break on comma, for(var a = 1, b = 2)
+                    flags.var_line_tainted = false;
+                }
+
+                if (flags.var_line) {
+                    flags.var_line_reindented = true;
+                }
+
+                print_token();
+
+                if (flags.var_line_tainted) {
+                    flags.var_line_tainted = false;
+                    print_newline();
+                } else {
+                    output_space_before_token = true;
+                }
+                return;
+            }
+
+            if (last_type === 'TK_END_BLOCK' && flags.mode !== MODE.Expression) {
+                print_token();
+                if (flags.mode === MODE.ObjectLiteral && flags.last_text === '}') {
+                    print_newline();
+                } else {
+                    output_space_before_token = true;
+                }
+            } else {
+                if (flags.mode === MODE.ObjectLiteral) {
+                    print_token();
+                    print_newline();
+                } else {
+                    // EXPR or DO_BLOCK
+                    print_token();
+                    output_space_before_token = true;
+                }
+            }
+        }
+
+        function handle_operator() {
+            var space_before = true;
+            var space_after = true;
+            if (is_special_word(flags.last_text)) {
+                // "return" had a special handling in TK_WORD. Now we need to return the favor
+                output_space_before_token = true;
+                print_token();
+                return;
+            }
+
+            // hack for actionscript's import .*;
+            if (token_text === '*' && last_type === 'TK_DOT' && !last_last_text.match(/^\d+$/)) {
+                print_token();
+                return;
+            }
+
+            if (token_text === ':' && flags.in_case) {
+                flags.case_body = true;
+                indent();
+                print_token();
+                print_newline();
+                flags.in_case = false;
+                return;
+            }
+
+            if (token_text === '::') {
+                // no spaces around exotic namespacing syntax operator
+                print_token();
+                return;
+            }
+
+            // http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1
+            // if there is a newline between -- or ++ and anything else we should preserve it.
+            if (input_wanted_newline && (token_text === '--' || token_text === '++')) {
+                print_newline();
+            }
+
+            if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(flags.last_text, line_starters) || flags.last_text === ','))) {
+                // unary operators (and binary +/- pretending to be unary) special cases
+
+                space_before = false;
+                space_after = false;
+
+                if (flags.last_text === ';' && is_expression(flags.mode)) {
+                    // for (;; ++i)
+                    //        ^^^
+                    space_before = true;
+                }
+
+                if (last_type === 'TK_WORD' && in_array(flags.last_text, line_starters)) {
+                    space_before = true;
+                }
+
+                if ((flags.mode === MODE.BlockStatement || flags.mode === MODE.Statement) && (flags.last_text === '{' || flags.last_text === ';')) {
+                    // { foo; --i }
+                    // foo(); --bar;
+                    print_newline();
+                }
+            } else if (token_text === ':') {
+                if (flags.ternary_depth === 0) {
+                    if (flags.mode === MODE.BlockStatement) {
+                        flags.mode = MODE.ObjectLiteral;
+                    }
+                    space_before = false;
+                } else {
+                    flags.ternary_depth -= 1;
+                }
+            } else if (token_text === '?') {
+                flags.ternary_depth += 1;
+            }
+            output_space_before_token = output_space_before_token || space_before;
+            print_token();
+            output_space_before_token = space_after;
+        }
+
+        function handle_block_comment() {
+            var lines = split_newlines(token_text);
+            var j; // iterator for this case
+            var javadoc = false;
+
+            // block comment starts with a new line
+            print_newline(false, true);
+            if (lines.length > 1) {
+                if (all_lines_start_with(lines.slice(1), '*')) {
+                    javadoc = true;
+                }
+            }
+
+            // first line always indented
+            print_token(lines[0]);
+            for (j = 1; j < lines.length; j++) {
+                print_newline(false, true);
+                if (javadoc) {
+                    // javadoc: reformat and re-indent
+                    print_token(' ' + trim(lines[j]));
+                } else {
+                    // normal comments output raw
+                    output_lines[output_lines.length - 1].text.push(lines[j]);
+                }
+            }
+
+            // for comments of more than one line, make sure there's a new line after
+            print_newline(false, true);
+        }
+
+        function handle_inline_comment() {
+            output_space_before_token = true;
+            print_token();
+            output_space_before_token = true;
+        }
+
+        function handle_comment() {
+            if (input_wanted_newline) {
+                print_newline(false, true);
+            } else {
+                trim_output(true);
+            }
+
+            output_space_before_token = true;
+            print_token();
+            print_newline(false, true);
+        }
+
+        function handle_dot() {
+            if (is_special_word(flags.last_text)) {
+                output_space_before_token = true;
+            } else {
+                // allow preserved newlines before dots in general
+                // force newlines on dots after close paren when break_chained - for bar().baz()
+                allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods);
+            }
+
+            print_token();
+        }
+
+        function handle_unknown() {
+            print_token();
+
+            if (token_text[token_text.length - 1] === '\n') {
+                print_newline();
+            }
+        }
+    }
+
+
+    if (typeof define === "function") {
+        // Add support for require.js
+        if (typeof define.amd === "undefined") {
+            define(function(require, exports, module) {
+                exports.js_beautify = js_beautify;
+            });
+        } else {
+            // if is AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
+            define([], function() {
+                return js_beautify;
+            });
+        }
+
+    } else if (typeof exports !== "undefined") {
+        // Add support for CommonJS. Just put this file somewhere on your require.paths
+        // and you will be able to `var js_beautify = require("beautify").js_beautify`.
+        exports.js_beautify = js_beautify;
+    } else if (typeof window !== "undefined") {
+        // If we're running a web page and don't have either of the above, add our one global
+        window.js_beautify = js_beautify;
+    } else if (typeof global !== "undefined") {
+        // If we don't even have window, try global.
+        global.js_beautify = js_beautify;
+    }
+
+}());


[12/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
kill off app/templates for docs & dbs

They live under app/addons/databases &
app/addons/documents now (as with the
other addons).


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/404c6916
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/404c6916
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/404c6916

Branch: refs/heads/import-master
Commit: 404c69163ee4cf39f328ae0e70e9f71df109014c
Parents: 58f9e07
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Mon Jan 13 13:53:57 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 15:09:15 2014 -0500

----------------------------------------------------------------------
 app/addons/databases/views.js                   |  8 +-
 app/addons/documents/views.js                   | 40 ++++----
 app/templates/databases/item.html               | 24 -----
 app/templates/databases/list.html               | 35 -------
 app/templates/databases/newdatabase.html        | 17 ----
 app/templates/documents/advanced_options.html   | 98 --------------------
 app/templates/documents/all_docs_item.html      | 26 ------
 app/templates/documents/all_docs_layout.html    | 20 ----
 app/templates/documents/all_docs_list.html      | 43 ---------
 app/templates/documents/all_docs_number.html    | 23 -----
 app/templates/documents/changes.html            | 38 --------
 app/templates/documents/ddoc_info.html          | 28 ------
 .../documents/design_doc_selector.html          | 35 -------
 app/templates/documents/doc.html                | 55 -----------
 app/templates/documents/doc_field_editor.html   | 74 ---------------
 .../documents/doc_field_editor_tabs.html        | 19 ----
 .../documents/duplicate_doc_modal.html          | 36 -------
 app/templates/documents/edit_tools.html         | 44 ---------
 app/templates/documents/index_menu_item.html    | 17 ----
 app/templates/documents/index_row_docular.html  | 27 ------
 app/templates/documents/index_row_tabular.html  | 25 -----
 app/templates/documents/jumpdoc.html            | 19 ----
 app/templates/documents/search.html             | 15 ---
 app/templates/documents/sidebar.html            | 67 -------------
 app/templates/documents/tabs.html               | 18 ----
 app/templates/documents/upload_modal.html       | 42 ---------
 app/templates/documents/view_editor.html        | 87 -----------------
 27 files changed, 24 insertions(+), 956 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
index 0068305..df663eb 100644
--- a/app/addons/databases/views.js
+++ b/app/addons/databases/views.js
@@ -22,7 +22,7 @@ function(app, Components, FauxtonAPI, Databases) {
   var Views = {};
 
   Views.Item = FauxtonAPI.View.extend({
-    template: "templates/databases/item",
+    template: "addons/databases/templates/item",
     tagName: "tr",
     establish: function(){
       return [this.model.fetch()];
@@ -39,7 +39,7 @@ function(app, Components, FauxtonAPI, Databases) {
   Views.List = FauxtonAPI.View.extend({
     dbLimit: 20,
     perPage: 20,
-    template: "templates/databases/list",
+    template: "addons/databases/templates/list",
     events: {
       "click button.all": "selectAll",
       "submit form#jump-to-db": "switchDatabase"
@@ -143,7 +143,7 @@ function(app, Components, FauxtonAPI, Databases) {
 
 
   Views.NewDatabaseButton = FauxtonAPI.View.extend({
-    template: "templates/databases/newdatabase",
+    template: "addons/databases/templates/newdatabase",
     events: {
       "click a#new": "newDatabase"
     },
@@ -189,7 +189,7 @@ function(app, Components, FauxtonAPI, Databases) {
   });
 
   Views.Sidebar = FauxtonAPI.View.extend({
-    template: "templates/databases/sidebar",
+    template: "addons/databases/templates/sidebar",
     events: {
       "click a#new": "newDatabase",
       "click a#owned": "showMine",

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 80c8251..0139eca 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -31,7 +31,7 @@ define([
 function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns) {
   var Views = {};
   Views.Tabs = FauxtonAPI.View.extend({
-    template: "templates/documents/tabs",
+    template: "addons/documents/templates/tabs",
     initialize: function(options){
       this.collection = options.collection;
       this.database = options.database;
@@ -81,7 +81,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.SearchBox = FauxtonAPI.View.extend({
-    template: "templates/documents/search",
+    template: "addons/documents/templates/search",
     tagName: "form",
     initialize: function(options){
       this.collection = options.collection;
@@ -131,7 +131,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.UploadModal = FauxtonAPI.View.extend({
-    template: "templates/documents/upload_modal",
+    template: "addons/documents/templates/upload_modal",
 
     disableLoader: true,
     
@@ -227,7 +227,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.DuplicateDocModal = FauxtonAPI.View.extend({
-    template: "templates/documents/duplicate_doc_modal",
+    template: "addons/documents/templates/duplicate_doc_modal",
 
     initialize: function () {
       _.bindAll(this);
@@ -299,7 +299,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.FieldEditorTabs = FauxtonAPI.View.extend({
-    template: "templates/documents/doc_field_editor_tabs",
+    template: "addons/documents/templates/doc_field_editor_tabs",
     disableLoader: true,
     initialize: function(options) {
       this.selected = options.selected;
@@ -330,7 +330,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.Document = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_item",
+    template: "addons/documents/templates/all_docs_item",
     tagName: "tr",
     className: "all-docs-item",
 
@@ -390,7 +390,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.Row = FauxtonAPI.View.extend({
-    template: "templates/documents/index_row_docular",
+    template: "addons/documents/templates/index_row_docular",
     tagName: "tr",
 
     events: {
@@ -411,7 +411,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.IndexItem = FauxtonAPI.View.extend({
-    template: "templates/documents/index_menu_item",
+    template: "addons/documents/templates/index_menu_item",
     tagName: "li",
 
     initialize: function(options){
@@ -444,7 +444,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.AllDocsNumber = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_number",
+    template: "addons/documents/templates/all_docs_number",
 
     initialize: function (options) {
       this.newView = options.newView || false;
@@ -487,7 +487,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.AllDocsLayout = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_layout",
+    template: "addons/documents/templates/all_docs_layout",
     className: "row",
 
     initialize: function (options) {
@@ -565,7 +565,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
   // TODO: Rename to reflect that this is a list of rows or documents
   Views.AllDocsList = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_list",
+    template: "addons/documents/templates/all_docs_list",
     events: {
       "click button.all": "selectAll",
       "click button.bulk-delete": "bulkDelete",
@@ -759,7 +759,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.Doc = FauxtonAPI.View.extend({
-    template: "templates/documents/doc",
+    template: "addons/documents/templates/doc",
     events: {
       "click button.save-doc": "saveDoc",
       "click button.delete": "destroy",
@@ -977,7 +977,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.DocFieldEditor = FauxtonAPI.View.extend({
-    template: "templates/documents/doc_field_editor",
+    template: "addons/documents/templates/doc_field_editor",
     disableLoader: true,
     events: {
       "click button.save": "saveDoc"
@@ -1024,7 +1024,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.AdvancedOptions = FauxtonAPI.View.extend({
-    template: "templates/documents/advanced_options",
+    template: "addons/documents/templates/advanced_options",
     className: "advanced-options well",
 
     initialize: function (options) {
@@ -1176,7 +1176,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.DesignDocSelector = FauxtonAPI.View.extend({
-    template: "templates/documents/design_doc_selector",
+    template: "addons/documents/templates/design_doc_selector",
 
     events: {
       "change select#ddoc": "updateDesignDoc"
@@ -1237,7 +1237,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.ViewEditor = FauxtonAPI.View.extend({
-    template: "templates/documents/view_editor",
+    template: "addons/documents/templates/view_editor",
     builtinReduces: ['_sum', '_count', '_stats'],
 
     events: {
@@ -1668,7 +1668,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.JumpToDoc = FauxtonAPI.View.extend({
-    template: "templates/documents/jumpdoc",
+    template: "addons/documents/templates/jumpdoc",
 
     initialize: function (options) {
       this.database = options.database;
@@ -1691,7 +1691,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.Sidebar = FauxtonAPI.View.extend({
-    template: "templates/documents/sidebar",
+    template: "addons/documents/templates/sidebar",
     events: {
       "click button#delete-database": "deleteDatabase"
     },
@@ -1800,7 +1800,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   Views.Indexed = FauxtonAPI.View.extend({});
 
   Views.Changes = FauxtonAPI.View.extend({
-    template: "templates/documents/changes",
+    template: "addons/documents/templates/changes",
 
     establish: function() {
       return [ this.model.changes.fetch()];
@@ -1819,7 +1819,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   });
 
   Views.DdocInfo = FauxtonAPI.View.extend({
-    template: "templates/documents/ddoc_info",
+    template: "addons/documents/templates/ddoc_info",
 
     initialize: function (options) {
       this.refreshTime = options.refreshTime || 5000;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/databases/item.html
----------------------------------------------------------------------
diff --git a/app/templates/databases/item.html b/app/templates/databases/item.html
deleted file mode 100644
index e2f8071..0000000
--- a/app/templates/databases/item.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<td>
-  <a href="#/database/<%=encoded%>/_all_docs?limit=<%=docLimit%>"><%= database.get("name") %></a>
-</td>
-<td><%= database.status.humanSize() %></td>
-<td><%= database.status.numDocs() %></td>
-<td><%= database.status.updateSeq() %></td>
-<td>
-  <a class="db-actions btn fonticon-replicate set-replication-start" title="Replicate <%= database.get("name") %>" href="#/replication/new/<%=encoded%>"></a>
-  <a class="db-actions btn icon-lock set-permissions" title="Set permissions for <%= database.get("name") %>" href="#/database/<%=encoded%>/permissions"></a>
-</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/databases/list.html
----------------------------------------------------------------------
diff --git a/app/templates/databases/list.html b/app/templates/databases/list.html
deleted file mode 100644
index 31c0977..0000000
--- a/app/templates/databases/list.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div class="result-tools" style="">
-  <div id="newButton" class="pull-left"></div>
-  <form id="jump-to-db" class="navbar-form pull-right input-append database-search">
-    <input type="text" class="search-autocomplete" name="search-query" placeholder="Database name"></input>
-    <button class="fonticon-search btn button red " type="submit"></button>
-  </form>
-
-
-</div>
-<table class="databases table table-striped">
-  <thead>
-    <th>Name</th>
-    <th>Size</th>
-    <th># of Docs</th>
-    <th>Update Seq</th>
-    <th>Actions</th>
-  </thead>
-  <tbody>
-  </tbody>
-</table>
-<div id="database-pagination"></div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/databases/newdatabase.html
----------------------------------------------------------------------
diff --git a/app/templates/databases/newdatabase.html b/app/templates/databases/newdatabase.html
deleted file mode 100644
index b357e0b..0000000
--- a/app/templates/databases/newdatabase.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<a class="button new" id="new"><i class="icon fonticon-new-database"></i>Add New Database</a>
-
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/advanced_options.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/advanced_options.html b/app/templates/documents/advanced_options.html
deleted file mode 100644
index e256325..0000000
--- a/app/templates/documents/advanced_options.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="errors-container"></div>
-<form class="view-query-update custom-inputs">
-  <div class="controls-group">
-    <div class="row-fluid">
-      <div class="controls controls-row">
-        <input name="key" class="span6" type="text" placeholder="Key">
-        <input name="keys" class="span6" type="text" placeholder="Keys">
-      </div>
-    </div>
-    <div class="row-fluid">
-      <div class="controls controls-row">
-        <input name="startkey" class="span6" type="text" placeholder="Start Key">
-        <input name="endkey" class="span6" type="text" placeholder="End Key">
-      </div>
-    </div>
-  </div>
-  <div class="controls-group">
-    <div class="row-fluid">
-      <div class="controls controls-row">
-        <div class="checkbox inline">  
-          <input id="check1" type="checkbox" name="include_docs" value="true">  
-          <label name="include_docs" for="check1">Include Docs</label>  
-          <% if (hasReduce) { %>
-          <input id="check2" name="reduce" type="checkbox" value="true">
-          <label for="check2">Reduce</label>  
-        </div> 
-        <label id="select1" class="drop-down inline">
-          Group Level:
-          <select id="select1" disabled name="group_level" class="input-small">
-            <option value="0">None</option>
-            <option value="1">1</option>
-            <option value="2">2</option>
-            <option value="3">3</option>
-            <option value="4">4</option>
-            <option value="5">5</option>
-            <option value="6">6</option>
-            <option value="7">7</option>
-            <option value="8">8</option>
-            <option value="9">9</option>
-            <option value="999" selected="selected">exact</option>
-          </select>
-        </label>
-        <% } else{ %>
-        </div>
-        <% } %>
-
-        <div class="checkbox inline">  
-          <input id="check3" name="stale" type="checkbox" value="ok">
-          <label for="check3">Stale</label>
-          <input id="check4" name="descending" type="checkbox" value="true">  
-          <label for="check4">Descending</label>  
-        </div> 
-        <label class="drop-down inline">
-          Limit:
-          <select name="limit" class="input-small">
-            <option>5</option>
-            <option>10</option>
-            <option selected="selected">20</option>
-            <option>30</option>
-            <option>50</option>
-            <option>100</option>
-          </select>
-        </label>
-        <div class="checkbox inline">  
-          <input id="check5" name="inclusive_end" type="checkbox" value="false">
-          <label for="check5">Disable Inclusive End</label>
-          <input id="check6" name="update_seq" type="checkbox" value="true">  
-          <label for="check6">Update Sequence</label>  
-        </div>
-      </div>
-    </div>
-  </div>
-  <div class="controls-group">
-    <div class="row-fluid">
-      <div id="button-options" class="controls controls-row">
-        <button type="submit" class="button green">Query</button>
-        <% if (showPreview) { %>
-        <button class="button btn-info preview">Browser Preview</button>
-        <% } %>
-      </div>
-    </div>
-  </div>
-</form>
-</div>
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/all_docs_item.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/all_docs_item.html b/app/templates/documents/all_docs_item.html
deleted file mode 100644
index bfedaaa..0000000
--- a/app/templates/documents/all_docs_item.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<td class="select"><input type="checkbox" class="row-select"></td>
-<td>
-  <div>
-    <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
-    <% if (doc.isEditable()) { %>
-      <div class="btn-group">
-        <a href="#<%= doc.url('web-index') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
-        <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
-      </div>
-    <% } %>
-  </div>
-</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/all_docs_layout.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/all_docs_layout.html b/app/templates/documents/all_docs_layout.html
deleted file mode 100644
index 6b4a31b..0000000
--- a/app/templates/documents/all_docs_layout.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<ul class="nav nav-tabs window-resizeable" id="db-views-tabs-nav">
-  <li><a id="toggle-query" class="fonticon-plus fonticon" href="#query" data-bypass="true" data-toggle="tab">Query Options</a></li>
-</ul>
-<div class="tab-content">
-  <div class="tab-pane" id="query">
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/all_docs_list.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/all_docs_list.html b/app/templates/documents/all_docs_list.html
deleted file mode 100644
index 335b040..0000000
--- a/app/templates/documents/all_docs_list.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div class="view show">
-  <% if (!viewList) { %>
-    <div class="row">
-      <div class="btn-toolbar span6">
-        <button type="button" class="btn all" data-toggle="button">✓ All</button>
-        <button class="btn btn-small disabled bulk-delete"><i class="icon-trash"></i></button>
-        <% if (expandDocs) { %>
-        <button id="collapse" class="btn"><i class="icon-minus"></i> Collapse</button>
-        <% } else { %>
-        <button id="collapse" class="btn"><i class="icon-plus"></i> Expand</button>
-        <% } %>
-      </div>
-    </div>
-  <% } %>
-  <p>
-
-  <div id="item-numbers"> </div>
-
-  <% if (requestDuration) { %>
-    <span class="view-request-duration">
-    View request duration: <strong> <%= requestDuration %> </strong> 
-    </span>
-  <% } %>
-  </p>
-  <table class="all-docs table table-striped table-condensed">
-    <tbody></tbody>
-  </table>
-  <div id="documents-pagination"></div>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/all_docs_number.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/all_docs_number.html b/app/templates/documents/all_docs_number.html
deleted file mode 100644
index df8fe07..0000000
--- a/app/templates/documents/all_docs_number.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<% if (totalRows === "unknown"){ %>
-  Showing 0 documents. <a href="#/database/<%=database%>/new"> Create your first document.</a>
-<% } else if (showNumbers) { %>
-  Showing <%=offset%> - <%= numModels %> of <%= totalRows %> rows
-<% } else { %>
-  Showing <%=pageStart%> - <%= pageEnd %>
-<%}%>
-<% if (updateSeq) { %>
-  -- Update Sequence: <%= updateSeq %>
-<% } %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/changes.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/changes.html b/app/templates/documents/changes.html
deleted file mode 100644
index 9408979..0000000
--- a/app/templates/documents/changes.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<table id="changes-table" class="table">
-  <thead>
-    <th id="seq"> seq </th>
-    <th> id </th>
-    <th id="changes"> changes </th>
-    <th id="deleted"> deleted? </th>
-  </thead>
-  <tbody>
-  <% _.each(changes, function (change) { %>
-    <tr>
-      <td> <%= change.seq %> </td>
-      <% if (change.deleted) { %>
-        <td> <%= change.id %> </td>
-      <% } else { %>
-        <td> <a href="#<%= database.url('app') %>/<%= change.id %>"><%= change.id %></a> </td>
-      <% } %>
-        <td> 
-          <pre class="prettyprint">  <%- JSON.stringify({changes: change.changes, doc: change.doc}, null, " ") %> </pre>
-      </td>
-      <td><%= change.deleted ? "true" : "false" %></td>
-    </tr>
-  <% }); %>
-  </tbody>
-</table>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/ddoc_info.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/ddoc_info.html b/app/templates/documents/ddoc_info.html
deleted file mode 100644
index ed0aed6..0000000
--- a/app/templates/documents/ddoc_info.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div>
-  <h2> Design Doc MetaData </h2>
-  <div class="row-fluid">
-	<% i=0; _.map(view_index, function (val, key) { %>
-		<% if(i%2==0){%>
-			<div class="row-fluid">
-		<% }; %>
-	    <div class="span6 well-item"><strong> <%= key %></strong> : <%= val %>  </div>
-	    <% if(i%2==1){%>
-			</div>
-		<% }; %>
-	  	<% ++i;
-	}); %>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/design_doc_selector.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/design_doc_selector.html b/app/templates/documents/design_doc_selector.html
deleted file mode 100644
index 7bbe310..0000000
--- a/app/templates/documents/design_doc_selector.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="span3">
-  <label for="ddoc">Save to Design Document <a href="<%=getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-  <select id="ddoc">
-    <optgroup label="Select a document">
-      <option value="new-doc">New document</option>
-      <% ddocs.each(function(ddoc) { %>
-      <% if (ddoc.id === ddocName) { %>
-      <option selected="selected" value="<%= ddoc.id %>"><%= ddoc.id %></option>
-      <% } else { %>
-      <option value="<%= ddoc.id %>"><%= ddoc.id %></option>
-      <% } %>
-      <% }); %>
-    </optgroup>
-  </select>
-</div>
-
-<div id="new-ddoc-section" class="span5" style="display:none">
-  <label class="control-label" for="new-ddoc"> _design/ </label>
-  <div class="controls">
-    <input type="text" id="new-ddoc" placeholder="newDesignDoc">
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/doc.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/doc.html b/app/templates/documents/doc.html
deleted file mode 100644
index 10bbf8b..0000000
--- a/app/templates/documents/doc.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div id="doc">
-  <div class="errors-container"></div>
-   
-<div class="row doc-editor-buttons"> 
-  <div class="span3">
-    <button class="save-doc button green btn-medium save fonticon-circle-check" type="button">Save</button>
-    <button class="button cancel-button gray btn-medium">Back to _all_docs</button>
-  </div>
-
-  <div class="span7">
-    <% if (attachments) { %>
-    <div class="btn-group">
-      <a class="button gray btn-medium dropdown-toggle btn" data-bypass="true" data-toggle="dropdown" href="#">
-        View Attachments
-        <span class="caret"></span>
-      </a>
-      <ul class="dropdown-menu">
-        <%_.each(attachments, function (att) { %>
-        <li>
-        <a href="<%= att.url %>" target="_blank"> <strong> <%= att.fileName %> </strong> -
-          <span> <%= att.contentType %>, <%= formatSize(att.size)%> </span>
-        </a>
-        </li>
-        <% }) %>
-      </ul>
-    </div>
-    <% } %> 
-    <button class="button gray btn-medium  upload"><i class="icon-circle-arrow-up"></i> Upload Attachment</button>
-    <button class="button gray btn-medium duplicate"><i class="icon-repeat"></i> Duplicate document</button>
-  </div>
-
-  <button class="button red btn-medium delete"><i class="icon-trash"></i></button>
-  </ul>
-
-<div id="upload-modal"> </div>
-<div id="duplicate-modal"> </div> 
-</div>
-
-  <div id="editor-container" class="doc-code"><%- JSON.stringify(doc.attributes, null, "  ") %></div>
-
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/doc_field_editor.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/doc_field_editor.html b/app/templates/documents/doc_field_editor.html
deleted file mode 100644
index 77d9278..0000000
--- a/app/templates/documents/doc_field_editor.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div id="doc-field-editor">
-  <div class="tools">
-
-    <div class="btn-toolbar pull-left">
-      <button class="btn btn-small all">&#x2713; All</button>
-      <button class="btn btn-small disabled delete"><i class="icon-trash"></i> Delete field</button>
-      <button class="btn btn-small new" style="margin-left: 64px"><i class="icon-plus"></i> New field</button>
-    </div>
-    <div class="btn-toolbar pull-right">
-      <button class="btn btn-small cancel button cancel-button outlineGray fonticon-circle-x">Cancel</button>
-      <button class="btn btn-small save button green fonticon-circle-check">Save</button>
-    </div>
-  </div>
-
-  <div class="clearfix"></div>
-  <!-- <hr style="margin-top: 0"/> -->
-
-  <table class="table table-striped  table-condensed">
-    <thead>
-      <tr>
-        <th class="select">
-        </th>
-        <th>Key</th>
-        <th>Value</th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr style="display:none">
-        <td class="select"><input type="checkbox" /></td>
-        <td class="key"><input type="text" class="input-large" value='' /></td>
-        <td class="value"><input type="text" class="input-xxlarge" value='' /></td>
-      </tr>
-      <% _.each(doc, function(value, key) { %>
-        <tr>
-          <td class="select"><input type="checkbox" /></td>
-          <td class="key">
-            <input type="text" class="input-large" name="doc[<%= key %>]" value="<%= key %>" />
-          </td>
-          <td class="value"><input type="text" class="input-xxlarge" value='<%= JSON.stringify(value) %>' /></td>
-        </tr>
-      <% }); %>
-        <tr>
-          <th colspan="3">
-            Attachments
-          </th>
-        </tr>
-      <%_.each(attachments, function (att) { %>
-        <tr>
-          <td class="select"><input type="checkbox" /></td>
-          <td colspan="2">
-            <a href="<%= att.url %>" target="_blank"> <%= att.fileName %> </a>
-            <span> <%= att.contentType %>, <%= formatSize(att.size)%> </span>
-          </td>
-        </tr>
-      <% }) %>
-    </tbody>
-  </table>
-  <a class="btn btn-small new" style="margin-left: 64px"><i class="icon-plus"></i> New field</a>
-
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/doc_field_editor_tabs.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/doc_field_editor_tabs.html b/app/templates/documents/doc_field_editor_tabs.html
deleted file mode 100644
index 766647c..0000000
--- a/app/templates/documents/doc_field_editor_tabs.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<!--<ul class="nav nav-tabs">
-  <li id="field_editor" class="<%= isSelectedClass('field_editor') %>"><a href="#<%= doc.url('app') %>/field_editor">Doc fields</a></li>
-  <li id="code_editor" class="<%= isSelectedClass('code_editor') %>"><a href="#<%= doc.url('app') %>/code_editor"><i class="icon-pencil"> </i> Code editor</a>
-  </li>
-</ul>-->

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/duplicate_doc_modal.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/duplicate_doc_modal.html b/app/templates/documents/duplicate_doc_modal.html
deleted file mode 100644
index dbb25bc..0000000
--- a/app/templates/documents/duplicate_doc_modal.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div class="modal hide fade">
-  <div class="modal-header">
-    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-    <h3>Duplicate Document</h3>
-  </div>
-  <div class="modal-body">
-    <div id="modal-error" class="hide alert alert-error"/>
-    <form id="doc-duplicate" class="form" method="post">
-      <p class="help-block">
-      Set new documents ID:
-      </p>
-      <input id="dup-id" type="text" class="input-xlarge">
-    </form>
-
-  </div>
-  <div class="modal-footer">
-    <a href="#" data-dismiss="modal" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
-    <a href="#" id="duplicate-btn" class="btn btn-primary button green save fonticon-circle-check">Duplicate</a>
-  </div>
-</div>
-
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/edit_tools.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/edit_tools.html b/app/templates/documents/edit_tools.html
deleted file mode 100644
index 40c884d..0000000
--- a/app/templates/documents/edit_tools.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div class="view show">
-  <p>
-    Showing 1-<%= numModels %> of <%= totalRows %> rows
-    <% if (updateSeq) { %>
-      -- Update Sequence: <%= updateSeq %>
-    <% } %>
-    <% if (requestDuration) { %>
-  <span class="view-request-duration">
-    View request duration: <strong> <%= requestDuration %> </strong> 
-   </span>
-   <% } %>
-  </p>
-  <table class="all-docs table table-striped table-condensed">
-    <tbody></tbody>
-  </table>
-  <!--
-  <div class="pagination pagination-centered">
-    <ul>
-      <li class="disabled"><a href="#">&laquo;</a></li>
-      <li class="active"><a href="#">1</a></li>
-      <li><a href="#">2</a></li>
-      <li><a href="#">3</a></li>
-      <li><a href="#">4</a></li>
-      <li><a href="#">5</a></li>
-      <li><a href="#">&raquo;</a></li>
-    </ul>
-  </div>
-  -->
-
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/index_menu_item.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/index_menu_item.html b/app/templates/documents/index_menu_item.html
deleted file mode 100644
index 7ca9012..0000000
--- a/app/templates/documents/index_menu_item.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<a id="<%= ddoc_clean %>_<%= index_clean %>" href="#database/<%= database_encoded %>/_design/<%= ddoc_encoded %>/_view/<%= index_encoded %>" class="toggle-view">
-  <%= ddoc %><span class="divider">/</span><%= index %>
-</a>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/index_row_docular.html b/app/templates/documents/index_row_docular.html
deleted file mode 100644
index f1b2217..0000000
--- a/app/templates/documents/index_row_docular.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<% if (doc.isEditable()) { %>
-  <td class="select"><input type="checkbox"></td>
-<% } %>
-<td>
-  <div>
-    <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
-    <% if (doc.isEditable()) { %>
-      <div class="btn-group">
-        <a href="#<%= doc.url('app') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
-        <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
-      </div>
-    <% } %>
-  </div>
-</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/index_row_tabular.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/index_row_tabular.html b/app/templates/documents/index_row_tabular.html
deleted file mode 100644
index f5f68fa..0000000
--- a/app/templates/documents/index_row_tabular.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<td class="select"><input type="checkbox"></td>
-<td>
-  <div>
-    <pre class="prettyprint"><%- JSON.stringify(doc.get("key")) %></pre>
-  </div>
-</td>
-<td>
-  <div>
-    <pre class="prettyprint"><%- JSON.stringify(doc.get("value")) %></pre>
-  </div>
-</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/jumpdoc.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/jumpdoc.html b/app/templates/documents/jumpdoc.html
deleted file mode 100644
index 43fdb9c..0000000
--- a/app/templates/documents/jumpdoc.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<form id="jump-to-doc" class="form-inline input-append" >
-  <input type="text" id="jump-to-doc-id" class="input-large" placeholder="Document ID"></input>
-
-  <button class="fonticon-search btn button red " type="submit"></button>
-</form>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/search.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/search.html b/app/templates/documents/search.html
deleted file mode 100644
index bb84891..0000000
--- a/app/templates/documents/search.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<input id="searchbox" type="text" class="span12" placeholder="Search by doc id, view key or search index">
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/sidebar.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/sidebar.html b/app/templates/documents/sidebar.html
deleted file mode 100644
index 8a73ae9..0000000
--- a/app/templates/documents/sidebar.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div id="sidenav">
-  <header class="row-fluid">
-    <div class="span12">
-      <div class="btn-group">
-        <button class="btn dropdown-toggle dropdown-toggle-btn" data-toggle="dropdown">
-          Docs
-          <span class="caret"></span>
-        </button>
-        <ul class="dropdown-menu">
-          <!-- dropdown menu links -->
-          <li><a class="icon-file" href="<%= db_url %>">Docs</a></li>
-          <li><a class="icon-lock" href="<%= permissions_url %>">Permissions</a></li>
-          <li><a class="icon-forward" href="<%= changes_url %>">Changes</a></li>
-          <% _.each(docLinks, function (link) { %>
-          <li><a class="<%= link.icon %>" href="<%= database_url + '/' + link.url %>"><%= link.title %></a></li>
-          <% }); %>
-        </ul>
-      </div>
-
-      <div class="btn-group">
-        <button class="btn dropdown-toggle dropdown-toggle-btn" data-toggle="dropdown">
-          New
-          <span class="caret"></span>
-        </button>
-        <ul class="dropdown-menu">
-          <!-- dropdown menu links -->
-          <li>
-          <a id="doc" href="#<%= database.url('app') %>/new">Document</a>
-          </li>
-          <li>
-          <a href="#<%= database.url('app') %>/new_view">Secondary Index</a>
-           <% _.each(newLinks, function (item) { %>
-           <a href="#<%= database.url('app') %>/<%=item.url%>"> <%= item.name %></a>
-           <% }); %>
-          </li>
-        </ul>
-      </div>
-        <button id="delete-database" class="btn"><i class="icon-trash"></i> Database</button>
-    </div>
-  </header>
-
-  <nav>
-    <ul class="nav nav-list">
-      <li class="active"><a id="all-docs" href="#<%= database.url('index') %>?limit=<%= docLimit %>" class="toggle-view"> All documents</a></li>
-      <li><a id="design-docs" href='#<%= database.url("index") %>?limit=<%= docLimit %>&startkey="_design"&endkey="_e"'  class="toggle-view"> All design docs</a></li>
-    </ul>
-    <ul class="nav nav-list views">
-      <li class="nav-header">Secondary Indexes</li>
-      <li><a id="new-view" href="#<%= database.url('app') %>/new_view" class="new"><i class="icon-plus"></i> New</a></li>
-    </ul>
-    <div id="extension-navs"></div>
-  </nav>
-</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/tabs.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/tabs.html b/app/templates/documents/tabs.html
deleted file mode 100644
index f8b0c4b..0000000
--- a/app/templates/documents/tabs.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<ul class="nav nav-tabs">
-  <li class="active"><a href="<%= db_url %>">Docs</a></li>
-  <li id="changes"><a  href="<%= changes_url %>">Changes</a></li>
-</ul>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/upload_modal.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/upload_modal.html b/app/templates/documents/upload_modal.html
deleted file mode 100644
index 9a5c5cd..0000000
--- a/app/templates/documents/upload_modal.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div class="modal hide fade">
-  <div class="modal-header">
-    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-    <h3>Upload an Attachment</h3>
-  </div>
-  <div class="modal-body">
-    <div id="modal-error" class="alert alert-error hide" style="font-size: 16px;"> </div>
-    <form id="file-upload" class="form" method="post">
-      <p class="help-block">
-      Please select the file you want to upload as an attachment to this document. 
-      Please note that this will result in the immediate creation of a new revision of the document, 
-      so it's not necessary to save the document after the upload.
-      </p>
-      <input id="_attachments" type="file" name="_attachments">
-      <input id="_rev" type="hidden" name="_rev" value="" >
-      <br/>
-    </form>
-
-    <div class="progress progress-info">
-      <div class="bar" style="width: 0%"></div>
-    </div>
-  </div>
-  <div class="modal-footer">
-    <a href="#" data-dismiss="modal" data-bypass="true" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
-    <a href="#" id="upload-btn" data-bypass="true" class="btn btn-primary button green save fonticon-circle-check">Upload</a>
-  </div>
-</div>
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/404c6916/app/templates/documents/view_editor.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/view_editor.html b/app/templates/documents/view_editor.html
deleted file mode 100644
index ddb5a0c..0000000
--- a/app/templates/documents/view_editor.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="row">
-  <ul class="nav nav-tabs" id="db-views-tabs-nav">
-    <li class="active"> <a data-bypass="true" id="index-nav" class="fonticon-wrench fonticon" data-toggle="tab" href="#index"><% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a></li>
-    <% if (!newView) { %>
-    <li><a data-bypass="true" id="query-nav" class="fonticon-plus fonticon" href="#query" data-toggle="tab">Query Options</a></li>
-    <li><a data-bypass="true" id="meta-nav" href="#metadata" data-toggle="tab">Design Doc Metadata</a></li>
-    <% } %>
-  </ul>
-  <div class="all-docs-list errors-container"></div>
-  <div class="tab-content">
-    <div class="tab-pane active" id="index">
-      <div id="define-view" class="ddoc-alert well">
-        <div class="errors-container"></div>
-        <form class="form-horizontal view-query-save">
-
-          <div class="control-group design-doc-group">
-          </div>
-
-          <div class="control-group">
-            <label for="index-name">Index name <a href="<%=getDocUrl('view_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-            <input type="text" id="index-name" value="<%= viewName %>" placeholder="Index name" />
-          </div>
-
-
-          <div class="control-group">
-            <label for="map-function">Map function <a href="<%=getDocUrl('map_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-            <% if (newView) { %>
-            <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
-            <% } else { %>
-            <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
-            <% } %>
-          </div>
-
-
-          <div class="control-group">
-            <label for="reduce-function-selector">Reduce (optional) <a href="<%=getDocUrl('reduce_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
-
-            <select id="reduce-function-selector">
-              <option value="" <%= !reduceFunStr ? 'selected="selected"' : '' %>>None</option>
-              <% _.each(["_sum", "_count", "_stats"], function(reduce) { %>
-              <option value="<%= reduce %>" <% if (reduce == reduceFunStr) { %>selected<% } %>><%= reduce %></option>
-              <% }) %>
-              <option value="CUSTOM" <% if (isCustomReduce) { %>selected<% } %>>Custom Reduce function</option>
-            </select>
-          </div>
-
-          <div class="control-group reduce-function">
-            <label for="reduce-function">Custom Reduce function</label>
-            <% if (newView) { %>
-            <div class="js-editor" id="reduce-function"><%= langTemplates.reduce %></div>
-            <% } else { %>
-            <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
-            <% } %>
-          </div>
-
-          <div class="control-group">
-            <button class="button green save fonticon-circle-check">Save &amp; Build Index</button>
-            <button class="button btn-info preview">Preview</button>
-            <% if (!newView) { %>
-            <button class="button delete outlineGray fonticon-circle-x">Delete</button>
-            <% } %>
-          </div>
-          <div class="clearfix"></div>
-        </form>
-      </div>
-    </div>
-    <div class="tab-pane" id="metadata">
-      <div id="ddoc-info" class="well"> </div>
-    </div>
-    <div class="tab-pane" id="query">
-    </div>
-  </div>
-</div>
-


[29/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Update jQuery to v1.11


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/c67fc295
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/c67fc295
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/c67fc295

Branch: refs/heads/import-master
Commit: c67fc29511941a9ef3d984454fbcbe49a02ac5ad
Parents: 0480869
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Jan 27 08:36:46 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Jan 27 08:37:06 2014 +0200

----------------------------------------------------------------------
 assets/js/libs/jquery.js | 12586 +++++++++++++++++++++-------------------
 1 file changed, 6567 insertions(+), 6019 deletions(-)
----------------------------------------------------------------------



[51/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Improvements to xhr cancellations


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/be87767b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/be87767b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/be87767b

Branch: refs/heads/import-master
Commit: be87767b6819a82d0909efb8b334e8db1eefcd22
Parents: 3c17314
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Feb 10 15:53:10 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Feb 10 15:53:10 2014 +0200

----------------------------------------------------------------------
 app/core/base.js                          | 1 +
 app/core/couchdbSession.js                | 6 +++---
 app/core/routeObject.js                   | 4 +++-
 app/core/router.js                        | 6 +++---
 assets/js/plugins/backbone.fetch-cache.js | 8 ++++----
 5 files changed, 14 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be87767b/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 24b89cf..7cacf39 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -96,6 +96,7 @@ function(Backbone, LayoutManager, BackboneCache) {
 
       fetchPromise.progress(promise.resolveWith); // Fires when the cache hit happens
       fetchPromise.then(promise.resolveWith); // Fires after the AJAX call
+      promise.fail(fetchPromise.abort);
 
       return promise;
     }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be87767b/app/core/couchdbSession.js
----------------------------------------------------------------------
diff --git a/app/core/couchdbSession.js b/app/core/couchdbSession.js
index b70ddf3..c59a8fc 100644
--- a/app/core/couchdbSession.js
+++ b/app/core/couchdbSession.js
@@ -30,15 +30,15 @@ function (FauxtonAPI) {
       fetchUser: function (opt) {
         var that = this,
             options = opt || {},
-        currentUser = this.user(),
-        fetch = this.fetchOnce;
+            currentUser = this.user(),
+            fetch = _.bind(this.fetchOnce, this);
 
         if (options.forceFetch) {
           fetch = this.fetch;
           Backbone.fetchCache.clearItem(_.result(this.url));
         }
 
-        return this.fetch(opt).then(function () {
+        return fetch(opt).then(function () {
           var user = that.user();
 
           // Notify anyone listening on these events that either a user has changed

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be87767b/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
index f3b8672..9f1067f 100644
--- a/app/core/routeObject.js
+++ b/app/core/routeObject.js
@@ -223,6 +223,7 @@ function(FauxtonAPI, Backbone) {
       _.each(this.views, function (view, selector) {
         view.remove();
         delete this.views[selector];
+        view = null;
       }, this);
     },
 
@@ -230,6 +231,7 @@ function(FauxtonAPI, Backbone) {
       if (_.isEmpty(promise)) { return; }
 
       if (!_.isArray(promise)) {
+        if (!promise.abort && !promise.reject) {
         return this._promises.push(promise);
       }
 
@@ -250,7 +252,7 @@ function(FauxtonAPI, Backbone) {
           return promise.abort("Route change");
         } 
 
-        promise.reject();
+        promise.reject && promise.reject();
       }, this);
 
       this._promises = [];

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be87767b/app/core/router.js
----------------------------------------------------------------------
diff --git a/app/core/router.js b/app/core/router.js
index cc1ca4f..bef4ced 100644
--- a/app/core/router.js
+++ b/app/core/router.js
@@ -59,13 +59,13 @@ function(FauxtonAPI, Auth, Backbone) {
 
           authPromise.then(function () {
             if (!that.activeRouteObject || !that.activeRouteObject.hasRoute(route)) {
-              if (that.activeRouteObject) {
-                that.activeRouteObject.cleanup();
-              }
+              that.activeRouteObject && that.activeRouteObject.cleanup();
+
               that.activeRouteObject = new RouteObject(route, masterLayout, args);
             }
 
             var routeObject = that.activeRouteObject;
+            routeObject.rejectPromises();
             routeObject.routeCallback(route, args);
             routeObject.renderWith(route, masterLayout, args);
           }, function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be87767b/assets/js/plugins/backbone.fetch-cache.js
----------------------------------------------------------------------
diff --git a/assets/js/plugins/backbone.fetch-cache.js b/assets/js/plugins/backbone.fetch-cache.js
index c86a8b9..4aa7676 100644
--- a/assets/js/plugins/backbone.fetch-cache.js
+++ b/assets/js/plugins/backbone.fetch-cache.js
@@ -192,7 +192,7 @@
       }
 
       if (!opts.prefill) {
-        return deferred.promise();
+        return deferred;
       }
     }
 
@@ -206,7 +206,7 @@
       .fail( _.bind(deferred.reject, this, this) );
 
     // return a promise which provides the same methods as a jqXHR object
-    return deferred.promise();
+    return deferred;
   };
 
   // Override Model.prototype.sync and try to clear cache items if it looks
@@ -278,7 +278,7 @@
       }
 
       if (!opts.prefill) {
-        return deferred.promise();
+        return deferred;
       }
     }
 
@@ -292,7 +292,7 @@
       .fail( _.bind(deferred.reject, this, this) );
 
     // return a promise which provides the same methods as a jqXHR object
-    return deferred.promise();
+    return deferred;
   };
 
   // Prime the cache from localStorage on initialization


[34/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Split up api.js

Split up api to core/*. To seperate out the Framework from the UI.
Move tests to fit with this refactor.
Change addons/Fauxton with work with api extraction.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/61e34781
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/61e34781
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/61e34781

Branch: refs/heads/import-master
Commit: 61e34781617e9fb4f2b64e33b9ac71a36a45910b
Parents: 1be64cd
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Jan 8 15:26:12 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Jan 29 16:53:46 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js                              |   4 +-
 app/addons/activetasks/tests/viewsSpec.js |   3 -
 app/addons/auth/base.js                   |   1 +
 app/addons/auth/resources.js              |   7 +-
 app/addons/documents/views.js             |   8 +-
 app/addons/fauxton/base.js                | 109 ++++-
 app/addons/fauxton/components.js          | 100 ++++-
 app/addons/fauxton/layout.js              |  98 ----
 app/addons/fauxton/resizeColumns.js       |  87 ++++
 app/addons/fauxton/tests/baseSpec.js      |  79 ++++
 app/addons/fauxton/tests/navbarSpec.js    | 107 +++++
 app/addons/fauxton/tests/paginateSpec.js  | 105 +++++
 app/api.js                                | 593 -------------------------
 app/app.js                                |  85 ++--
 app/config.js                             |   5 +-
 app/core/api.js                           |  53 +++
 app/core/auth.js                          |  67 +++
 app/core/base.js                          | 137 ++++++
 app/core/couchdbSession.js                |  54 +++
 app/core/layout.js                        |  91 ++++
 app/core/routeObject.js                   | 296 ++++++++++++
 app/core/router.js                        | 113 +++++
 app/core/tests/layoutSpec.js              |  92 ++++
 app/core/tests/routeObjectSpec.js         |  96 ++++
 app/core/utils.js                         |  94 ++++
 app/main.js                               |  13 +-
 app/resizeColumns.js                      |  87 ----
 app/router.js                             | 142 ------
 app/utils.js                              |  66 ---
 settings.json.default                     |   1 +
 tasks/couchserver.js                      |   2 +-
 test/core/layoutSpec.js                   |  94 ----
 test/core/navbarSpec.js                   | 107 -----
 test/core/paginateSpec.js                 | 109 -----
 test/core/routeObjectSpec.js              | 105 -----
 test/mocha/testUtils.js                   |   3 +-
 test/test.config.underscore               |   1 +
 37 files changed, 1717 insertions(+), 1497 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index 32065b6..2c5a249 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -357,7 +357,7 @@ module.exports = function(grunt) {
 
     mochaSetup: {
       default: {
-        files: { src: helper.watchFiles(['[Ss]pec.js'], ['./test/core/**/*[Ss]pec.js', './app/**/*[Ss]pec.js'])},
+        files: { src: helper.watchFiles(['[Ss]pec.js'], ['./app/**/*[Ss]pec.js'])},
         template: 'test/test.config.underscore',
         config: './app/config.js'
       }
@@ -424,7 +424,7 @@ module.exports = function(grunt) {
   grunt.registerTask('lint', ['clean', 'jshint']);
   grunt.registerTask('test', ['lint', 'dependencies', 'test_inline']);
   // lighter weight test task for use inside dev/watch
-  grunt.registerTask('test_inline', ['mochaSetup','jst', 'concat:test_config_js', 'mocha_phantomjs']);
+  grunt.registerTask('test_inline', ['mochaSetup','jst', 'concat:test_config_js','mocha_phantomjs']);
   // Fetch dependencies (from git or local dir), lint them and make load_addons
   grunt.registerTask('dependencies', ['get_deps', 'gen_load_addons:default']);
   // build templates, js and css

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/activetasks/tests/viewsSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/tests/viewsSpec.js b/app/addons/activetasks/tests/viewsSpec.js
index 395b60a..13c9049 100644
--- a/app/addons/activetasks/tests/viewsSpec.js
+++ b/app/addons/activetasks/tests/viewsSpec.js
@@ -132,8 +132,5 @@ define([
       });
 
     });
-
-
-
   });
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/auth/base.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/base.js b/app/addons/auth/base.js
index 9f9a332..7f69a7f 100644
--- a/app/addons/auth/base.js
+++ b/app/addons/auth/base.js
@@ -20,6 +20,7 @@ function(app, FauxtonAPI, Auth) {
 
   Auth.session = new Auth.Session();
   FauxtonAPI.setSession(Auth.session);
+  app.session = Auth.session;
 
   Auth.initialize = function() {
     Auth.navLink = new Auth.NavLink({model: Auth.session});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/auth/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/resources.js b/app/addons/auth/resources.js
index 970d55b..321d302 100644
--- a/app/addons/auth/resources.js
+++ b/app/addons/auth/resources.js
@@ -12,10 +12,11 @@
 
 define([
        "app",
-       "api"
+       "api",
+       "core/CouchdbSession"
 ],
 
-function (app, FauxtonAPI) {
+function (app, FauxtonAPI, CouchdbSession) {
 
   var Auth = new FauxtonAPI.addon();
 
@@ -46,7 +47,7 @@ function (app, FauxtonAPI) {
     }
   });
 
-  Auth.Session = FauxtonAPI.Session.extend({
+  Auth.Session = CouchdbSession.Session.extend({
     url: app.host + '/_session',
 
     initialize: function (options) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 9516355..aeb5983 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -21,7 +21,7 @@ define([
        "addons/pouchdb/base",
 
        // Libs
-       "resizeColumns",
+       "addons/Fauxton/resizeColumns",
 
        // Plugins
        "plugins/beautify",
@@ -720,11 +720,11 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     },
     
     cleanup: function () {
-      //if (!this.pagination) { return; }
-      this.pagination.remove();
-      //this.pagination = null;
       this.allDocsNumber.remove();
       _.each(this.rows, function (row) {row.remove();});
+
+      if (!this.pagination) { return; }
+      this.pagination.remove();
     },
 
     beforeRender: function() {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js
index 1811e84..35babb5 100644
--- a/app/addons/fauxton/base.js
+++ b/app/addons/fauxton/base.js
@@ -12,18 +12,86 @@
 
 define([
   "app",
-  // Libs
-  "backbone",
-  "resizeColumns",
+  "api",
+  "addons/fauxton/resizeColumns"
 ],
 
-function(app, Backbone, resizeColumns) {
+function(app, FauxtonAPI, resizeColumns) {
 
-  //resizeAnimation
-  app.resizeColumns = new resizeColumns({});
-  app.resizeColumns.onResizeHandler();
+  var Fauxton = FauxtonAPI.addon();
+  FauxtonAPI.addNotification = function (options) {
+    options = _.extend({
+      msg: "Notification Event Triggered!",
+      type: "info",
+      selector: "#global-notifications"
+    }, options);
 
-  var Fauxton = {};
+    var view = new Fauxton.Notification(options);
+    return view.renderNotification();
+  };
+
+  FauxtonAPI.UUID = FauxtonAPI.Model.extend({
+    initialize: function(options) {
+      options = _.extend({count: 1}, options);
+      this.count = options.count;
+    },
+
+    url: function() {
+      return app.host + "/_uuids?count=" + this.count;
+    },
+
+    next: function() {
+      return this.get("uuids").pop();
+    }
+  });
+
+
+  Fauxton.initialize = function () {
+    app.footer = new Fauxton.Footer({el: "#footer-content"}),
+    app.navBar = new Fauxton.NavBar();
+    app.apiBar = new Fauxton.ApiBar();
+
+    FauxtonAPI.when.apply(null, app.footer.establish()).done(function() {
+      FauxtonAPI.masterLayout.setView("#primary-navbar", app.navBar, true);
+      FauxtonAPI.masterLayout.setView("#api-navbar", app.apiBar, true);
+      app.navBar.render();
+      app.apiBar.render();
+
+      app.footer.render();
+    });
+
+    FauxtonAPI.masterLayout.navBar = app.navBar;
+    FauxtonAPI.masterLayout.apiBar = app.apiBar;
+
+    FauxtonAPI.RouteObject.on('beforeFullRender', function (routeObject) {
+      $('#primary-navbar li').removeClass('active');
+
+      if (routeObject.selectedHeader) {
+        app.selectedHeader = routeObject.selectedHeader;
+        $('#primary-navbar li[data-nav-name="' + routeObject.selectedHeader + '"]').addClass('active');
+      }
+    });
+
+    FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
+      FauxtonAPI.masterLayout.removeView('#breadcrumbs');
+      var crumbs = routeObject.get('crumbs');
+
+      if (crumbs.length) {
+        FauxtonAPI.masterLayout.setView('#breadcrumbs', new Fauxton.Breadcrumbs({
+          crumbs: crumbs
+        }), true).render();
+      }
+    });
+
+    FauxtonAPI.RouteObject.on('renderComplete', function (routeObject) {
+      var masterLayout = FauxtonAPI.masterLayout;
+      if (routeObject.get('apiUrl')){
+        masterLayout.apiBar.update(routeObject.get('apiUrl'));
+      } else {
+        masterLayout.apiBar.hide();
+      }
+    });
+  };
 
   Fauxton.Breadcrumbs = Backbone.View.extend({
     template: "templates/fauxton/breadcrumbs",
@@ -41,7 +109,9 @@ function(app, Backbone, resizeColumns) {
   });
 
   Fauxton.VersionInfo = Backbone.Model.extend({
-    url: app.host
+    url: function () {
+      return app.host;
+    }
   });
 
   // TODO: this View should extend from FauxtonApi.View.
@@ -76,6 +146,16 @@ function(app, Backbone, resizeColumns) {
     bottomNavLinks: [],
     footerNavLinks: [],
 
+    initialize: function () {
+      _.bindAll(this);
+      //resizeAnimation
+      this.resizeColumns = new resizeColumns({});
+      this.resizeColumns.onResizeHandler();
+      
+      FauxtonAPI.extensions.on('add:navbar:addHeaderLink', this.addLink);
+      FauxtonAPI.extensions.on('removeItem:navbar:addHeaderLink', this.removeLink);
+    },
+
     serialize: function() {
       return {
         navLinks: this.navLinks,
@@ -124,7 +204,6 @@ function(app, Backbone, resizeColumns) {
     },
 
     afterRender: function(){
-
       $('#primary-navbar li[data-nav-name="' + app.selectedHeader + '"]').addClass('active');
 
       var menuOpen = true;
@@ -141,21 +220,22 @@ function(app, Backbone, resizeColumns) {
       function toggleMenu(){
         $selectorList.toggleClass('closeMenu');
         menuOpen = $selectorList.hasClass('closeMenu');
-        app.resizeColumns.onResizeHandler();
+        this.resizeColumns.onResizeHandler();
       }
-
+      
+      var that = this;
       $('#primary-navbar').on("click", ".nav a", function(){
         if (!($selectorList.hasClass('closeMenu'))){
           setTimeout(
             function(){
             $selectorList.addClass('closeMenu');
-            app.resizeColumns.onResizeHandler();
+            that.resizeColumns.onResizeHandler();
           },3000);
 
         }
       });
 
-      app.resizeColumns.initialize();
+      this.resizeColumns.initialize();
     },
 
     beforeRender: function () {
@@ -265,6 +345,5 @@ function(app, Backbone, resizeColumns) {
     }
   });
 
-
   return Fauxton;
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index edde428..c26fc96 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -25,10 +25,11 @@ define([
   // Libs
   "api",
   "ace_configuration",
+  "spin"
 ],
 
-function(app, FauxtonAPI, ace) {
-  var Components = app.module();
+function(app, FauxtonAPI, ace, spin) {
+  var Components = FauxtonAPI.addon();
 
   Components.Pagination = FauxtonAPI.View.extend({
     template: "templates/fauxton/pagination",
@@ -124,7 +125,7 @@ function(app, FauxtonAPI, ace) {
 
     pageEnd: function () {
       if (this.collection.length < this.pageLimit()) {
-        return this.collection.length;
+        return (this.previousParams.length * this.pageLimit()) + this.collection.length;
       }
 
       return (this.previousParams.length * this.pageLimit()) + this.pageLimit();
@@ -235,6 +236,8 @@ function(app, FauxtonAPI, ace) {
       this.theme = options.theme || 'crimson_editor';
       this.couchJSHINT = options.couchJSHINT;
       this.edited = false;
+
+      _.bindAll(this);
     },
 
     afterRender: function () {
@@ -295,13 +298,14 @@ function(app, FauxtonAPI, ace) {
     },
 
     removeIncorrectAnnotations: function () {
-      var editor = this.editor;
+      var editor = this.editor,
+          isIgnorableError = this.isIgnorableError;
 
-      this.editor.getSession().on("changeAnnotation", function(){
+      this.editor.getSession().on("changeAnnotation", function () {
         var annotations = editor.getSession().getAnnotations();
 
         var newAnnotations = _.reduce(annotations, function (annotations, error) {
-          if (!FauxtonAPI.isIgnorableError(error.raw)) {
+          if (!isIgnorableError(error.raw)) {
             annotations.push(error);
           }
           return annotations;
@@ -338,12 +342,94 @@ function(app, FauxtonAPI, ace) {
      var errors = this.getAnnotations();
      // By default CouchDB view functions don't pass lint
      return _.every(errors, function(error) {
-      return FauxtonAPI.isIgnorableError(error.raw);
+      return this.isIgnorableError(error.raw);
       },this);
+    },
+
+    // List of JSHINT errors to ignore
+    // Gets around problem of anonymous functions not being a valid statement
+    excludedViewErrors: [
+      "Missing name in function declaration.",
+      "['{a}'] is better written in dot notation."
+    ],
+
+    isIgnorableError: function(msg) {
+      return _.contains(this.excludedViewErrors, msg);
     }
 
   });
 
+  //need to make this into a backbone view...
+  var routeObjectSpinner;
+  FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
+    if (!routeObject.disableLoader){ 
+      var opts = {
+        lines: 16, // The number of lines to draw
+        length: 8, // The length of each line
+        width: 4, // The line thickness
+        radius: 12, // The radius of the inner circle
+        color: '#333', // #rbg or #rrggbb
+        speed: 1, // Rounds per second
+        trail: 10, // Afterglow percentage
+        shadow: false // Whether to render a shadow
+     };
+
+     if (!$('.spinner').length) {
+       $('<div class="spinner"></div>')
+        .appendTo('#app-container');
+     }
+
+     routeObjectSpinner = new Spinner(opts).spin();
+     $('.spinner').append(routeObjectSpinner.el);
+   }
+  });
+
+  var removeRouteObjectSpinner = function () {
+    if (routeObjectSpinner) {
+      routeObjectSpinner.stop();
+      $('.spinner').remove();
+    }
+  };
+
+  var removeViewSpinner = function () {
+    if (viewSpinner){
+      viewSpinner.stop();
+      $('.spinner').remove();
+    }
+  };
+
+  var viewSpinner;
+  FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
+    removeRouteObjectSpinner();
+
+    if (!view.disableLoader){ 
+      var opts = {
+        lines: 16, // The number of lines to draw
+        length: 8, // The length of each line
+        width: 4, // The line thickness
+        radius: 12, // The radius of the inner circle
+        color: '#333', // #rbg or #rrggbb
+        speed: 1, // Rounds per second
+        trail: 10, // Afterglow percentage
+        shadow: false // Whether to render a shadow
+      };
+
+      viewSpinner = new Spinner(opts).spin();
+      $('<div class="spinner"></div>')
+        .appendTo(selector)
+        .append(viewSpinner.el);
+    }
+  });
+
+  FauxtonAPI.RouteObject.on('afterRender', function (routeObject, view, selector) {
+    removeViewSpinner();
+  });
+
+  FauxtonAPI.RouteObject.on('viewHasRendered', function () {
+    removeViewSpinner();
+    removeRouteObjectSpinner();
+  });
+
   return Components;
 });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/layout.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/layout.js b/app/addons/fauxton/layout.js
deleted file mode 100644
index 1422241..0000000
--- a/app/addons/fauxton/layout.js
+++ /dev/null
@@ -1,98 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define(["backbone"],
-
-function(Backbone) {
-
-  // A wrapper of the main Backbone.layoutmanager
-  // Allows the main layout of the page to be changed by any plugin.
-  // Exposes the different views:
-  //    navBar -> the top navigation bar
-  //    dashboardContent -> Main display view
-  //    breadcrumbs -> Breadcrumbs navigation section
-  var Layout = function (navBar, apiBar) {
-    this.navBar = navBar;
-    this.apiBar = apiBar;
-
-    this.layout = new Backbone.Layout({
-      template: "templates/layouts/with_sidebar",
-
-      views: {
-        "#primary-navbar": this.navBar,
-        "#api-navbar": this.apiBar
-      },
-      afterRender: function(){
-
-      }
-    });
-
-    this.layoutViews = {};
-    //this.hooks = {};
-
-    this.el = this.layout.el;
-  };
-
-  // creatings the dashboard object same way backbone does
-  _.extend(Layout.prototype, {
-    render: function () {
-      return this.layout.render();
-    },
-
-    setTemplate: function(template) {
-      if (template.prefix){
-        this.layout.template = template.prefix + template.name;
-      } else{
-        this.layout.template = "templates/layouts/" + template;
-      }
-      // If we're changing layouts all bets are off, so kill off all the
-      // existing views in the layout.
-      _.each(this.layoutViews, function(view){view.remove();});
-      this.layoutViews = {};
-      this.render();
-    },
-
-    setTabs: function(view){
-      // TODO: Not sure I like this - seems fragile/repetitive
-      this.tabs = this.layout.setView("#tabs", view);
-      this.tabs.render();
-    },
-
-    setBreadcrumbs: function(view) {
-      this.breadcrumbs = this.layout.setView("#breadcrumbs", view);
-      this.breadcrumbs.render();
-    },
-
-    clearBreadcrumbs: function () {
-      if (!this.breadcrumbs) {return ;}
-
-      this.breadcrumbs.remove();
-    },
-
-    setView: function(selector, view) {
-      this.layoutViews[selector] = this.layout.setView(selector, view, false);
-    },
-
-    renderView: function(selector) {
-      var view = this.layoutViews[selector];
-      if (!view) {
-        return false;
-      } else {
-        return view.render();
-      }
-    }
-
-  });
-
-  return Layout;
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/resizeColumns.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/resizeColumns.js b/app/addons/fauxton/resizeColumns.js
new file mode 100644
index 0000000..abfcd2f
--- /dev/null
+++ b/app/addons/fauxton/resizeColumns.js
@@ -0,0 +1,87 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+
+// This file creates a set of helper functions that will be loaded for all html
+// templates. These functions should be self contained and not rely on any 
+// external dependencies as they are loaded prior to the application. We may
+// want to change this later, but for now this should be thought of as a
+// "purely functional" helper system.
+
+define([
+  "api"
+],
+
+function(FauxtonAPI) {
+
+  var Resize = function(options){
+    this.options = options;
+    this.options.selectorElements = options.selectorElements || ".window-resizeable";
+  };
+
+  Resize.prototype = {
+    getPrimaryNavWidth: function(){
+      var primaryNavWidth  = $('body').hasClass('closeMenu')? 64:224;
+      return primaryNavWidth;
+    },
+    getPanelWidth: function(){
+      var sidebarWidth = $('#sidebar-content').length > 0 ? $('#sidebar-content').width(): 0;
+      return (this.getPrimaryNavWidth() + sidebarWidth); 
+    },
+    initialize: function(){
+     // $(window).off('resize');
+      var that = this;
+      //add throttler :) 
+      this.lazyLayout = _.debounce(that.onResizeHandler, 300).bind(this);
+      FauxtonAPI.utils.addWindowResize(this.lazyLayout,"animation");
+      FauxtonAPI.utils.initWindowResize();
+      this.onResizeHandler();
+    },
+    updateOptions:function(options){
+      this.options = {};
+      this.options = options;
+      this.options.selectorElements = options.selectorElements || ".window-resizeable";
+    },
+    turnOff:function(){
+      FauxtonAPI.utils.removeWindowResize("animation");
+    },
+    cleanupCallback: function(){
+      this.callback = null;
+    },
+    onResizeHandler: function (){
+      //if there is an override, do that instead
+      if (this.options.onResizeHandler){
+        this.options.onResizeHandler();
+      } else {
+        var combinedWidth = window.innerWidth - this.getPanelWidth(),
+        smallWidthConstraint = ($('#sidebar-content').length > 0)? 470:800,
+        panelWidth; 
+
+        if( combinedWidth > smallWidthConstraint  && combinedWidth < 1400){
+          panelWidth = window.innerWidth - this.getPanelWidth();
+        } else if (combinedWidth < smallWidthConstraint){
+          panelWidth = smallWidthConstraint;
+        } else if(combinedWidth > 1400){
+          panelWidth = 1400;
+        }
+
+        $(this.options.selectorElements).innerWidth(panelWidth);
+      }
+      //if there is a callback, run that
+      if(this.options.callback) {
+        this.options.callback();
+      }
+    } 
+  };
+
+  return Resize;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/tests/baseSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/baseSpec.js b/app/addons/fauxton/tests/baseSpec.js
new file mode 100644
index 0000000..7df4dfc
--- /dev/null
+++ b/app/addons/fauxton/tests/baseSpec.js
@@ -0,0 +1,79 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+  'testUtils',
+  'api',
+  'addons/fauxton/base',
+  "backbone"
+], function (testUtils, FauxtonAPI, Base) {
+  var assert = testUtils.assert;
+
+
+  describe('Fauxton RouteObject:beforeEstablish', function () {
+    var TestRouteObject, testRouteObject, mockLayout, _layout;
+
+    before(function () {
+      Base.initialize();
+      _layout = FauxtonAPI.masterLayout;
+    });
+
+    beforeEach(function () {
+      TestRouteObject = FauxtonAPI.RouteObject.extend({
+        crumbs: ['mycrumbs']
+      });
+
+      testRouteObject = new TestRouteObject();
+      var apiBar = {};
+      apiBar.hide = sinon.spy();
+      var setViewSpy = sinon.stub();
+      setViewSpy.returns({
+        render: function () {}
+      });
+
+      // Need to find a better way of doing this
+      mockLayout = {
+        setTemplate: sinon.spy(),
+        clearBreadcrumbs: sinon.spy(),
+        setView: setViewSpy,
+        renderView: sinon.spy(),
+        removeView: sinon.spy(),
+        hooks: [],
+        setBreadcrumbs: sinon.spy(),
+        apiBar: apiBar,
+        layout: { 
+          setView: function () {}
+        }
+      };
+
+
+    });
+
+    after(function () {
+      FauxtonAPI.masterLayout = _layout;
+    });
+
+    it('Should clear breadcrumbs', function () {
+      FauxtonAPI.masterLayout = mockLayout;
+      testRouteObject.renderWith('the-route', mockLayout, 'args');
+      assert.ok(mockLayout.removeView.calledWith('#breadcrumbs'), 'Clear Breadcrumbs called');
+    });
+
+    it('Should set breadcrumbs when breadcrumbs exist', function () {
+      FauxtonAPI.masterLayout = mockLayout;
+      testRouteObject.renderWith('the-route', mockLayout, 'args');
+      assert.ok(mockLayout.setView.calledOnce, 'Set Breadcrumbs was called');
+    });
+
+  });
+
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/tests/navbarSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/navbarSpec.js b/app/addons/fauxton/tests/navbarSpec.js
new file mode 100644
index 0000000..3eca6f6
--- /dev/null
+++ b/app/addons/fauxton/tests/navbarSpec.js
@@ -0,0 +1,107 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+       'addons/fauxton/base',
+      'testUtils'
+], function (Fauxton, testUtils) {
+  var assert = testUtils.assert,
+      NavBar = Fauxton.NavBar;
+
+  describe('NavBar', function () {
+
+    describe('adding links', function () {
+      var navBar;
+
+      beforeEach(function () {
+        navBar = new NavBar();
+        navBar.navLinks = [];
+        navBar.bottomNavLinks = [];
+        navBar.footerNavLinks = [];
+      });
+
+      it('Should add link to navlinks', function () {
+        navBar.addLink({href: '#/test', title: 'Test Title'});
+
+        assert.equal(navBar.navLinks.length, 1);
+        assert.equal(navBar.footerNavLinks.length, 0);
+        assert.equal(navBar.bottomNavLinks.length, 0);
+      });
+
+      it('Should add link to bottom links', function () {
+        navBar.addLink({href: '#/test', bottomNav: true, title: 'Test Title'});
+
+        assert.equal(navBar.bottomNavLinks.length, 1);
+        assert.equal(navBar.navLinks.length, 0);
+        assert.equal(navBar.footerNavLinks.length, 0);
+      });
+
+      it('Should add link to footer links', function () {
+        navBar.addLink({href: '#/test', footerNav: true, title: 'Test Title'});
+
+        assert.equal(navBar.footerNavLinks.length, 1);
+        assert.equal(navBar.bottomNavLinks.length, 0);
+        assert.equal(navBar.navLinks.length, 0);
+      });
+    });
+
+    describe('removing links', function () {
+      var navBar;
+
+      beforeEach(function () {
+        navBar = new NavBar();
+        navBar.navLinks = [];
+        navBar.bottomNavLinks = [];
+        navBar.footerNavLinks = [];
+        navBar.addLink({
+          href: '#/test', 
+          footerNav: true, 
+          title: 'Test Title Footer'
+        });
+
+        navBar.addLink({
+          href: '#/test', 
+          bottomNav: true, 
+          title: 'Test Title Bottom'
+        });
+
+        navBar.addLink({
+          href: '#/test', 
+          title: 'Test Title'
+        });
+      });
+
+      it("should remove links from list", function () {
+        navBar.removeLink({
+          title: 'Test Title Footer',
+          footerNav: true
+        });
+
+        assert.equal(navBar.footerNavLinks.length, 0);
+        assert.equal(navBar.bottomNavLinks.length, 1);
+        assert.equal(navBar.navLinks.length, 1);
+      });
+
+      it("Should call render after removing links", function () {
+        var renderSpy = sinon.stub(navBar,'render');
+
+        navBar.removeLink({
+          title: 'Test Title Footer',
+          footerNav: true
+        });
+
+        assert.ok(renderSpy.calledOnce);
+      });
+
+    });
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/addons/fauxton/tests/paginateSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/paginateSpec.js b/app/addons/fauxton/tests/paginateSpec.js
new file mode 100644
index 0000000..535e26f
--- /dev/null
+++ b/app/addons/fauxton/tests/paginateSpec.js
@@ -0,0 +1,105 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+       'app',
+       'addons/fauxton/components',
+       'addons/documents/resources',
+       'testUtils',
+       'api'
+], function (app, Views, Models, testUtils, FauxtonAPI) {
+  var assert = testUtils.assert,
+  ViewSandbox = testUtils.ViewSandbox;
+
+
+  describe('IndexPaginate', function () {
+    var viewSandbox, paginate, collection, navigateMock;
+    beforeEach(function () {
+      collection = new Models.IndexCollection([{
+        id:'myId1',
+        doc: 'num1'
+      },
+      {
+        id:'myId2',
+        doc: 'num2'
+      }], {
+        database: {id: 'databaseId'},
+        design: '_design/myDoc'
+      });
+
+      paginate = new Views.IndexPagination({
+        collection: collection,
+        previousUrlfn: function () {},
+        nextUrlfn: function () {},
+        canShowPreviousfn: function () { return true; },
+        canShowNextfn: function () { return true;}
+      });
+      viewSandbox = new ViewSandbox();
+      viewSandbox.renderView(paginate); 
+    });
+
+    afterEach(function () {
+      viewSandbox.remove();
+    });
+
+    describe('#next', function () {
+      beforeEach(function () {
+        //do this so it doesn't throw an error on other unwired up components
+        FauxtonAPI.triggerRouteEvent = function () {};
+        //FauxtonAPI.triggerRouteEvent.restore && FauxtonAPI.triggerRouteEvent.restore();
+        //FauxtonAPI.navigate.restore && FauxtonAPI.navigate.restore(); 
+      });
+
+      it('Should navigate', function () {
+        var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
+
+        paginate.$('a#next').click();
+
+        assert.ok(navigateMock.calledOnce);
+        FauxtonAPI.navigate.restore();
+      });
+
+      it('Should trigger routeEvent', function () {
+        var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
+
+        paginate.$('a#next').click();
+
+        assert.ok(navigateMock.calledOnce);
+        FauxtonAPI.triggerRouteEvent.restore();
+      });
+
+    });
+
+
+    describe('#previous', function () {
+
+      it('Should navigate', function () {
+        var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
+
+        paginate.$('a#previous').click();
+
+        assert.ok(navigateMock.calledOnce);
+        FauxtonAPI.navigate.restore();
+      });
+
+      it('Should trigger routeEvent', function () {
+        var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
+
+        paginate.$('a#previous').click();
+
+        assert.ok(navigateMock.calledOnce);
+        FauxtonAPI.triggerRouteEvent.restore();
+      });
+
+    });
+
+  });
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/api.js
----------------------------------------------------------------------
diff --git a/app/api.js b/app/api.js
deleted file mode 100644
index 9ac895e..0000000
--- a/app/api.js
+++ /dev/null
@@ -1,593 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       // Modules
-       "addons/fauxton/base",
-       "spin"
-],
-
-function(app, Fauxton) {
-  var FauxtonAPI = app.module();
-
-  FauxtonAPI.moduleExtensions = {
-    Routes: {
-    }
-  };
-
-  FauxtonAPI.addonExtensions = {
-    initialize: function() {}
-  };
-
-  // List of JSHINT errors to ignore
-  // Gets around problem of anonymous functions not being a valid statement
-  FauxtonAPI.excludedViewErrors = [
-    "Missing name in function declaration.",
-    "['{a}'] is better written in dot notation."
-  ];
-
-  FauxtonAPI.isIgnorableError = function(msg) {
-    return _.contains(FauxtonAPI.excludedViewErrors, msg);
-  };
-
-  FauxtonAPI.View = Backbone.View.extend({
-    // This should return an array of promises, an empty array, or null
-    establish: function() {
-      return null;
-    },
-
-    loaderClassname: 'loader',
-
-    disableLoader: false,
-
-    forceRender: function () {
-      this.hasRendered = false;
-    }
-  });
-
-  FauxtonAPI.navigate = function(url, _opts) {
-    var options = _.extend({trigger: true}, _opts );
-    app.router.navigate(url,options);
-  };
-
-  FauxtonAPI.beforeUnload = function () {
-    app.router.beforeUnload.apply(app.router, arguments);
-  };
-
-  FauxtonAPI.removeBeforeUnload = function () {
-    app.router.removeBeforeUnload.apply(app.router, arguments);
-  };
-
-  FauxtonAPI.addHeaderLink = function(link) {
-    app.masterLayout.navBar.addLink(link);
-  };
-
-  FauxtonAPI.removeHeaderLink = function(link) {
-    app.masterLayout.navBar.removeLink(link);
-  };
-
-  FauxtonAPI.Deferred = function() {
-    return $.Deferred();
-  };
-
-  FauxtonAPI.when = function (deferreds) {
-    if (deferreds instanceof Array) {
-      return $.when.apply(null, deferreds);
-    }
-
-    return $.when(deferreds);
-  };
-
-  FauxtonAPI.addRoute = function(route) {
-    app.router.route(route.route, route.name, route.callback);
-  };
-
-  FauxtonAPI.triggerRouteEvent = function (routeEvent, args) {
-    app.router.triggerRouteEvent("route:"+routeEvent, args);
-  };
-
-  FauxtonAPI.module = function(extra) {
-    return app.module(_.extend(FauxtonAPI.moduleExtensions, extra));
-  };
-
-  FauxtonAPI.addon = function(extra) {
-    return FauxtonAPI.module(FauxtonAPI.addonExtensions, extra);
-  };
-
-  FauxtonAPI.addNotification = function(options) {
-    options = _.extend({
-      msg: "Notification Event Triggered!",
-      type: "info",
-      selector: "#global-notifications"
-    }, options);
-    var view = new Fauxton.Notification(options);
-
-    return view.renderNotification();
-  };
-
-  FauxtonAPI.UUID = Backbone.Model.extend({
-    initialize: function(options) {
-      options = _.extend({count: 1}, options);
-      this.count = options.count;
-    },
-
-    url: function() {
-      return app.host + "/_uuids?count=" + this.count;
-    },
-
-    next: function() {
-      return this.get("uuids").pop();
-    }
-  });
-
-  FauxtonAPI.Session = Backbone.Model.extend({
-    url: app.host + '/_session',
-
-    user: function () {
-      var userCtx = this.get('userCtx');
-
-      if (!userCtx || !userCtx.name) { return null; }
-
-      return {
-        name: userCtx.name,
-        roles: userCtx.roles
-      };
-    },
-
-    fetchOnce: function (opt) {
-      var options = _.extend({}, opt);
-
-      if (!this._deferred || this._deferred.state() === "rejected" || options.forceFetch ) {
-        this._deferred = this.fetch();
-      }
-
-      return this._deferred;
-    },
-
-    fetchUser: function (opt) {
-      var that = this,
-      currentUser = this.user();
-
-      return this.fetchOnce(opt).then(function () {
-        var user = that.user();
-
-        // Notify anyone listening on these events that either a user has changed
-        // or current user is the same
-        if (currentUser !== user) {
-          that.trigger('session:userChanged');
-        } else {
-          that.trigger('session:userFetched');
-        }
-
-        // this will return the user as a value to all function that calls done on this
-        // eg. session.fetchUser().done(user) { .. do something with user ..}
-        return user; 
-      });
-    }
-  });
-
-  FauxtonAPI.setSession = function (newSession) {
-    app.session = FauxtonAPI.session = newSession;
-    return FauxtonAPI.session.fetchUser();
-  };
-
-  FauxtonAPI.setSession(new FauxtonAPI.Session());
-
-  // This is not exposed externally as it should not need to be accessed or overridden
-  var Auth = function (options) {
-    this._options = options;
-    this.initialize.apply(this, arguments);
-  };
-
-  // Piggy-back on Backbone's self-propagating extend function,
-  Auth.extend = Backbone.Model.extend;
-
-  _.extend(Auth.prototype, Backbone.Events, {
-    authDeniedCb: function() {},
-
-    initialize: function() {
-      var that = this;
-    },
-
-    authHandlerCb : function (roles) {
-      var deferred = $.Deferred();
-      deferred.resolve();
-      return deferred;
-    },
-
-    registerAuth: function (authHandlerCb) {
-      this.authHandlerCb = authHandlerCb;
-    },
-
-    registerAuthDenied: function (authDeniedCb) {
-      this.authDeniedCb = authDeniedCb;
-    },
-
-    checkAccess: function (roles) {
-      var requiredRoles = roles || [],
-      that = this;
-
-      return FauxtonAPI.session.fetchUser().then(function (user) {
-        return FauxtonAPI.when(that.authHandlerCb(FauxtonAPI.session, requiredRoles));
-      });
-    }
-  });
-
-  FauxtonAPI.auth = new Auth();
-
-  FauxtonAPI.RouteObject = function(options) {
-    this._options = options;
-
-    this._configure(options || {});
-    this.initialize.apply(this, arguments);
-    this.addEvents();
-  };
-
-  var broadcaster = {};
-  _.extend(broadcaster, Backbone.Events);
-
-  FauxtonAPI.RouteObject.on = function (eventName, fn) {
-    broadcaster.on(eventName, fn); 
-  };
-  
-  /* How Route Object events work
-   To listen to a specific route objects events:
-
-   myRouteObject = FauxtonAPI.RouteObject.extend({
-    events: {
-      "beforeRender": "beforeRenderEvent"
-    },
-
-    beforeRenderEvent: function (view, selector) {
-      console.log('Hey, beforeRenderEvent triggered',arguments);
-    },
-   });
-
-    It is also possible to listen to events triggered from all Routeobjects. 
-    This is great for more general things like adding loaders, hooks.
-
-    FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
-      console.log('hey, this will trigger when any routeobject renders a view');
-    });
-
-   Current Events to subscribe to:
-    * beforeFullRender -- before a full render is being done
-    * beforeEstablish -- before the routeobject calls establish
-    * AfterEstablish -- after the routeobject has run establish
-    * beforeRender -- before a view is rendered
-    * afterRender -- a view is finished being rendered
-    * renderComplete -- all rendering is complete
-    
-  */
-
-  // Piggy-back on Backbone's self-propagating extend function
-  FauxtonAPI.RouteObject.extend = Backbone.Model.extend;
-
-  var routeObjectOptions = ["views", "routes", "events", "roles", "crumbs", "layout", "apiUrl", "establish"];
-
-  _.extend(FauxtonAPI.RouteObject.prototype, Backbone.Events, {
-    // Should these be default vals or empty funcs?
-    views: {},
-    routes: {},
-    events: {},
-    crumbs: [],
-    layout: "with_sidebar",
-    apiUrl: null,
-    disableLoader: false,
-    loaderClassname: 'loader',
-    renderedState: false,
-    establish: function() {},
-    route: function() {},
-    roles: [],
-    _promises: [],
-    initialize: function() {}
-  }, {
-
-    renderWith: function(route, masterLayout, args) {
-      var routeObject = this,
-          triggerBroadcast = _.bind(this.triggerBroadcast, this);
-
-      // Only want to redo the template if its a full render
-      if (!this.renderedState) {
-        masterLayout.setTemplate(this.layout);
-        triggerBroadcast('beforeFullRender');
-        $('#primary-navbar li').removeClass('active');
-
-        if (this.selectedHeader) {
-          app.selectedHeader = this.selectedHeader;
-          $('#primary-navbar li[data-nav-name="' + this.selectedHeader + '"]').addClass('active');
-        }
-      }
-
-      masterLayout.clearBreadcrumbs();
-      var crumbs = this.get('crumbs');
-
-      if (crumbs.length) {
-        masterLayout.setBreadcrumbs(new Fauxton.Breadcrumbs({
-          crumbs: crumbs
-        }));
-      }
-
-      triggerBroadcast('beforeEstablish');
-      var establishPromise = this.establish();
-      this.addPromise(establishPromise);
-      FauxtonAPI.when(establishPromise).then(function(resp) {
-        triggerBroadcast('afterEstablish');
-        _.each(routeObject.getViews(), function(view, selector) {
-          if(view.hasRendered) { 
-            triggerBroadcast('viewHasRendered', view, selector);
-            return;
-          }
-
-          triggerBroadcast('beforeRender', view, selector);
-          var viewPromise = view.establish();
-          routeObject.addPromise(viewPromise);
-          FauxtonAPI.when(viewPromise).then(function(resp) {
-            masterLayout.setView(selector, view);
-
-            masterLayout.renderView(selector);
-            triggerBroadcast('afterRender', view, selector);
-            }, function(resp) {
-              view.establishError = {
-                error: true,
-                reason: resp
-              };
-
-              if (resp && resp.responseText) { 
-                var errorText = JSON.parse(resp.responseText).reason;
-                FauxtonAPI.addNotification({
-                  msg: 'An Error occurred: ' + errorText,
-                  type: 'error',
-                  clear: true
-                });
-              }
-
-              masterLayout.renderView(selector);
-          });
-
-        });
-      }.bind(this), function (resp) {
-          if (!resp || !resp.responseText) { return; }
-          FauxtonAPI.addNotification({
-                msg: 'An Error occurred' + JSON.parse(resp.responseText).reason,
-                type: 'error',
-                clear: true
-          });
-      });
-
-      if (this.get('apiUrl')){
-        masterLayout.apiBar.update(this.get('apiUrl'));
-      } else {
-        masterLayout.apiBar.hide();
-      }
-
-      // Track that we've done a full initial render
-      this.renderedState = true;
-      triggerBroadcast('renderComplete');
-    },
-
-    triggerBroadcast: function (eventName) {
-      var args = Array.prototype.slice.call(arguments);
-      this.trigger.apply(this, args);
-
-      args.splice(0,1, eventName, this);
-      broadcaster.trigger.apply(broadcaster, args);
-    },
-
-    get: function(key) {
-      return _.isFunction(this[key]) ? this[key]() : this[key];
-    },
-
-    addEvents: function(events) {
-      events = events || this.get('events');
-      _.each(events, function(method, event) {
-        if (!_.isFunction(method) && !_.isFunction(this[method])) {
-          throw new Error("Invalid method: "+method);
-        }
-        method = _.isFunction(method) ? method : this[method];
-
-        this.on(event, method);
-      }, this);
-    },
-
-    _configure: function(options) {
-      _.each(_.intersection(_.keys(options), routeObjectOptions), function(key) {
-        this[key] = options[key];
-      }, this);
-    },
-
-    getView: function(selector) {
-      return this.views[selector];
-    },
-
-    setView: function(selector, view) {
-      this.views[selector] = view;
-      return view;
-    },
-
-    getViews: function() {
-      return this.views;
-    },
-
-    removeViews: function () {
-      _.each(this.views, function (view, selector) {
-        view.remove();
-        delete this.views[selector];
-      }, this);
-    },
-
-    addPromise: function (promise) {
-      if (_.isEmpty(promise)) { return; }
-
-      if (_.isArray(promise)) {
-        return _.each(promise, function (p) {
-          this._promises.push(p);
-        }, this);
-      }
-
-     this._promises.push(promise);
-    },
-
-    cleanup: function () {
-      this.removeViews();
-      this.rejectPromises();
-    },
-
-    rejectPromises: function () {
-      _.each(this._promises, function (promise) {
-        if (promise.state() === "resolved") { return; }
-        if (promise.abort) {
-          return promise.abort("Route change");
-        } 
-
-        promise.reject();
-      }, this);
-
-      this._promises = [];
-    },
-
-    getRouteUrls: function () {
-      return _.keys(this.get('routes'));
-    },
-
-    hasRoute: function (route) {
-      if (this.get('routes')[route]) {
-        return true;
-      }
-      return false;
-    },
-
-    routeCallback: function (route, args) {
-      var routes = this.get('routes'),
-      routeObj = routes[route],
-      routeCallback;
-
-      if (typeof routeObj === 'object') {
-        routeCallback = this[routeObj.route];
-      } else {
-        routeCallback = this[routeObj];
-      }
-
-      routeCallback.apply(this, args);
-    },
-
-    getRouteRoles: function (routeUrl) {
-      var route = this.get('routes')[routeUrl];
-
-      if ((typeof route === 'object') && route.roles) {
-        return route.roles; 
-      }
-
-      return this.roles;
-    }
-
-  });
-
-  // We could look at moving the spinner code out to its own module
-  var routeObjectSpinner;
-  FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
-    if (!routeObject.disableLoader){ 
-      var opts = {
-        lines: 16, // The number of lines to draw
-        length: 8, // The length of each line
-        width: 4, // The line thickness
-        radius: 12, // The radius of the inner circle
-        color: '#333', // #rbg or #rrggbb
-        speed: 1, // Rounds per second
-        trail: 10, // Afterglow percentage
-        shadow: false // Whether to render a shadow
-     };
-
-     if (!$('.spinner').length) {
-       $('<div class="spinner"></div>')
-        .appendTo('#app-container');
-     }
-
-     routeObjectSpinner = new Spinner(opts).spin();
-     $('.spinner').append(routeObjectSpinner.el);
-   }
-  });
-
-  var removeRouteObjectSpinner = function () {
-    if (routeObjectSpinner) {
-      routeObjectSpinner.stop();
-      $('.spinner').remove();
-    }
-  };
-
-  var removeViewSpinner = function () {
-    if (viewSpinner){
-      viewSpinner.stop();
-      $('.spinner').remove();
-    }
-  };
-
-  var viewSpinner;
-  FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
-    removeRouteObjectSpinner();
-
-    if (!view.disableLoader){ 
-      var opts = {
-        lines: 16, // The number of lines to draw
-        length: 8, // The length of each line
-        width: 4, // The line thickness
-        radius: 12, // The radius of the inner circle
-        color: '#333', // #rbg or #rrggbb
-        speed: 1, // Rounds per second
-        trail: 10, // Afterglow percentage
-        shadow: false // Whether to render a shadow
-      };
-
-      viewSpinner = new Spinner(opts).spin();
-      $('<div class="spinner"></div>')
-        .appendTo(selector)
-        .append(viewSpinner.el);
-    }
-  });
-
-  FauxtonAPI.RouteObject.on('afterRender', function (routeObject, view, selector) {
-    removeViewSpinner();
-  });
-
-  FauxtonAPI.RouteObject.on('viewHasRendered', function () {
-    removeViewSpinner();
-    removeRouteObjectSpinner();
-  });
-
-  var extensions = _.extend({}, Backbone.Events);
-  // Can look at a remove function later.
-  FauxtonAPI.registerExtension = function (name, view) {
-    if (!extensions[name]) {
-      extensions[name] = [];
-    }
-
-    extensions.trigger('add:' + name, view);
-    extensions[name].push(view);
-  };
-
-  FauxtonAPI.getExtensions = function (name) {
-    var views = extensions[name];
-
-    if (!views) {
-      views = [];
-    }
-
-    return views;
-  };
-
-  FauxtonAPI.extensions = extensions;
-
-  app.fauxtonAPI = FauxtonAPI;
-  return app.fauxtonAPI;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/app.js
----------------------------------------------------------------------
diff --git a/app/app.js b/app/app.js
index 5325f77..521ad6c 100644
--- a/app/app.js
+++ b/app/app.js
@@ -21,77 +21,38 @@ define([
   "bootstrap",
 
   "helpers",
-  "utils",
+  "core/utils",
   // Modules
-  "resizeColumns",
-
-   // Plugins.
+  "core/api",
+  "core/couchdbsession",
+  // Plugins.
   "plugins/backbone.layoutmanager",
   "plugins/jquery.form"
 
 ],
 
-function(app, $, _, Backbone, Bootstrap, Helpers, Utils, resizeColumns) {
-
-   // Make sure we have a console.log
+function(app, $, _, Backbone, Bootstrap, Helpers, Utils, FauxtonAPI, Couchdb) {
+  // Make sure we have a console.log
   if (typeof console == "undefined") {
     console = {
-      log: function(){}
+      log: function(){},
+      trace: function(){},
+      debug: function(){}
     };
   }
 
   // Provide a global location to place configuration settings and module
   // creation also mix in Backbone.Events
-  _.extend(app, Backbone.Events, {
+  _.extend(app, {
     utils: Utils,
-
-    renderView: function(baseView, selector, view, options, callback) {
-      baseView.setView(selector, new view(options)).render().then(callback);
-    },
-
-    // Create a custom object with a nested Views object.
-    module: function(additionalProps) {
-      return _.extend({ Views: {} }, additionalProps);
-    },
-
-    // Thanks to: http://stackoverflow.com/a/2880929
-    getParams: function(queryString) {
-      if (queryString) {
-        // I think this could be combined into one if
-        if (queryString.substring(0,1) === "?") {
-          queryString = queryString.substring(1);
-        } else if (queryString.indexOf('?') > -1) {
-          queryString = queryString.split('?')[1];
-        }
-      }
-      var hash = window.location.hash.split('?')[1];
-      queryString = queryString || hash || window.location.search.substring(1);
-      var match,
-      urlParams = {},
-      pl     = /\+/g,  // Regex for replacing addition symbol with a space
-      search = /([^&=]+)=?([^&]*)/g,
-      decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
-      query  = queryString;
-
-      if (queryString) {
-        while ((match = search.exec(query))) {
-          urlParams[decode(match[1])] = decode(match[2]);
-        }
-      }
-
-      return urlParams;
-    }
+    getParams: FauxtonAPI.utils.getParams
   });
 
-  //resizeAnimation
-  app.resizeColumns = new resizeColumns({});
-  app.resizeColumns.onResizeHandler();
-
   // Localize or create a new JavaScript Template object.
   var JST = window.JST = window.JST || {};
 
   // Configure LayoutManager with Backbone Boilerplate defaults.
-  Backbone.Layout.configure({
+  FauxtonAPI.Layout.configure({
     // Allow LayoutManager to augment Backbone.View.prototype.
     manage: true,
 
@@ -123,6 +84,28 @@ function(app, $, _, Backbone, Bootstrap, Helpers, Utils, resizeColumns) {
     }
   });
 
+  FauxtonAPI.setSession(new Couchdb.Session());
+
+  // Define your master router on the application namespace and trigger all
+  // navigation from this instance.
+  FauxtonAPI.config({
+    el: "#app-container",
+    masterLayout: new FauxtonAPI.Layout(),
+    
+    addHeaderLink: function(link) {
+      FauxtonAPI.registerExtension('navbar:addHeaderLink', link);
+    },
+
+    removeHeaderLink: function(link) {
+      FauxtonAPI.removeExtensionItem('navbar:addHeaderLink', link, function (item) {
+        if (item.title === link.title) {
+          return true;
+        }
+
+        return false;
+      });
+    }
+  });
 
   return app;
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/config.js
----------------------------------------------------------------------
diff --git a/app/config.js b/app/config.js
index 057523b..98be9c6 100644
--- a/app/config.js
+++ b/app/config.js
@@ -25,7 +25,7 @@ require.config({
     jquery: "../assets/js/libs/jquery",
     lodash: "../assets/js/libs/lodash",
     backbone: "../assets/js/libs/backbone",
-    "backbone.layoutmanger": "../assets/js/plugins/backbone.layoutmanager",
+    "backbone.layoutmanager": "../assets/js/plugins/backbone.layoutmanager",
     bootstrap: "../assets/js/libs/bootstrap",
     spin: "../assets/js/libs/spin.min",
     d3: "../assets/js/libs/d3",
@@ -37,7 +37,8 @@ require.config({
 
   map: {
     "*": {
-      'underscore': 'lodash'
+      'underscore': 'lodash',
+      'api':'core/api'
     }
   },
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/api.js
----------------------------------------------------------------------
diff --git a/app/core/api.js b/app/core/api.js
new file mode 100644
index 0000000..1b21dca
--- /dev/null
+++ b/app/core/api.js
@@ -0,0 +1,53 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "core/base",
+       "core/layout",
+       "core/router",
+       "core/routeObject",
+       "core/utils"
+],
+
+function(FauxtonAPI, Layout, Router, RouteObject, utils) {
+  FauxtonAPI = _.extend(FauxtonAPI, {
+    Layout: Layout,
+    Router: Router,
+    RouteObject: RouteObject,
+    utils: utils
+  });
+
+  FauxtonAPI.navigate = function(url, _opts) {
+    var options = _.extend({trigger: true}, _opts );
+    FauxtonAPI.router.navigate(url,options);
+  };
+
+  FauxtonAPI.beforeUnload = function () {
+    FauxtonAPI.router.beforeUnload.apply(FauxtonAPI.router, arguments);
+  };
+
+  FauxtonAPI.removeBeforeUnload = function () {
+    FauxtonAPI.router.removeBeforeUnload.apply(FauxtonAPI.router, arguments);
+  };
+
+  FauxtonAPI.addRoute = function(route) {
+    FauxtonAPI.router.route(route.route, route.name, route.callback);
+  };
+
+  FauxtonAPI.triggerRouteEvent = function (routeEvent, args) {
+    FauxtonAPI.router.triggerRouteEvent("route:"+routeEvent, args);
+  };
+
+  
+  return FauxtonAPI;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/auth.js
----------------------------------------------------------------------
diff --git a/app/core/auth.js b/app/core/auth.js
new file mode 100644
index 0000000..15cf566
--- /dev/null
+++ b/app/core/auth.js
@@ -0,0 +1,67 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "core/base",
+  "backbone"
+],
+function(FauxtonAPI, Backbone) {
+
+  // This is not exposed externally as it should not need to be accessed or overridden
+  var Auth = function (options) {
+    this._options = options;
+    this.initialize.apply(this, arguments);
+  };
+
+  // Piggy-back on Backbone's self-propagating extend function,
+  Auth.extend = Backbone.Model.extend;
+
+  _.extend(Auth.prototype, Backbone.Events, {
+    authDeniedCb: function() {},
+
+    initialize: function() {
+      var that = this;
+    },
+
+    authHandlerCb : function (roles) {
+      var deferred = $.Deferred();
+      deferred.resolve();
+      return deferred;
+    },
+
+    registerAuth: function (authHandlerCb) {
+      this.authHandlerCb = authHandlerCb;
+    },
+
+    registerAuthDenied: function (authDeniedCb) {
+      this.authDeniedCb = authDeniedCb;
+    },
+
+    checkAccess: function (roles) {
+      var requiredRoles = roles || [],
+      that = this;
+
+      if (!FauxtonAPI.session) {
+        throw new Error("Fauxton.session is not configured.");
+      }
+
+      return FauxtonAPI.session.fetchUser().then(function (user) {
+        return FauxtonAPI.when(that.authHandlerCb(FauxtonAPI.session, requiredRoles));
+      });
+    }
+  });
+
+//  FauxtonAPI.auth = new Auth();
+
+  return Auth;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
new file mode 100644
index 0000000..55a8d87
--- /dev/null
+++ b/app/core/base.js
@@ -0,0 +1,137 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "backbone"
+],
+
+function(Backbone) {
+  var FauxtonAPI = {
+    //add default objects
+    router: {
+      navigate: function () {}
+    },
+
+    masterLayout: {},
+
+    addNotification: function () {},
+
+    config: function (options) {
+      return _.extend(this, options);
+    }
+  };
+
+  FauxtonAPI.Deferred = function() {
+    return $.Deferred();
+  };
+
+  FauxtonAPI.when = function (deferreds) {
+    if (deferreds instanceof Array) {
+      return $.when.apply(null, deferreds);
+    }
+
+    return $.when(deferreds);
+  };
+
+  FauxtonAPI.addonExtensions = {
+    initialize: function() {},
+    RouteObjects: {},
+    Views: {}
+  };
+
+  FauxtonAPI.addon = function(extra) {
+    return _.extend(_.clone(FauxtonAPI.addonExtensions), extra);
+  };
+
+  FauxtonAPI.View = Backbone.View.extend({
+    // This should return an array of promises, an empty array, or null
+    establish: function() {
+      return null;
+    },
+
+    loaderClassname: 'loader',
+
+    disableLoader: false,
+
+    forceRender: function () {
+      this.hasRendered = false;
+    }
+  });
+
+  FauxtonAPI.Model = Backbone.Model.extend({
+    fetchOnce: function (opt) {
+      var options = _.extend({}, opt);
+
+      if (!this._deferred || this._deferred.state() === "rejected" || options.forceFetch ) {
+        this._deferred = this.fetch();
+      }
+
+      return this._deferred;
+    }
+  });
+
+  var extensions = _.extend({}, Backbone.Events);
+  // Can look at a remove function later.
+  FauxtonAPI.registerExtension = function (name, view) {
+    if (!extensions[name]) {
+      extensions[name] = [];
+    }
+
+    extensions.trigger('add:' + name, view);
+    extensions[name].push(view);
+  };
+
+  FauxtonAPI.unRegisterExtension = function (name) {
+    var views = extensions[name];
+    
+    if (!views) { return; }
+    extensions.trigger('remove:' + name, views);
+    delete extensions[name];
+  };
+
+  FauxtonAPI.getExtensions = function (name) {
+    var views = extensions[name];
+
+    if (!views) {
+      views = [];
+    }
+
+    return views;
+  };
+
+  FauxtonAPI.removeExtensionItem = function (name, view, cb) {
+    var views = extensions[name];
+    if (!views) { return; }
+
+    var _cb = arguments[arguments.length -1];
+    if (_.isObject(view) && !cb) {
+      _cb = function (item) { return _.isEqual(item, view);};
+    } 
+
+    views = _.filter(views, function (item) {
+      return !_cb(item);
+    });
+
+    extensions[name] = views;
+    extensions.trigger('removeItem:' + name, view);
+  };
+
+  FauxtonAPI.extensions = extensions;
+
+  FauxtonAPI.setSession = function (newSession) {
+    FauxtonAPI.session = newSession;
+    return FauxtonAPI.session.fetchUser();
+  };
+
+  return FauxtonAPI;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/couchdbSession.js
----------------------------------------------------------------------
diff --git a/app/core/couchdbSession.js b/app/core/couchdbSession.js
new file mode 100644
index 0000000..93bfd8a
--- /dev/null
+++ b/app/core/couchdbSession.js
@@ -0,0 +1,54 @@
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "core/base"
+],
+function (FauxtonAPI) {
+  var CouchdbSession = {
+    Session: FauxtonAPI.Model.extend({
+      url: '/_session',
+
+      user: function () {
+        var userCtx = this.get('userCtx');
+
+        if (!userCtx || !userCtx.name) { return null; }
+
+        return {
+          name: userCtx.name,
+          roles: userCtx.roles
+        };
+      },
+
+      fetchUser: function (opt) {
+        var that = this,
+        currentUser = this.user();
+
+        return this.fetchOnce(opt).then(function () {
+          var user = that.user();
+
+          // Notify anyone listening on these events that either a user has changed
+          // or current user is the same
+          if (currentUser !== user) {
+            that.trigger('session:userChanged');
+          } else {
+            that.trigger('session:userFetched');
+          }
+
+          // this will return the user as a value to all function that calls done on this
+          // eg. session.fetchUser().done(user) { .. do something with user ..}
+          return user; 
+        });
+      }
+    })
+  };
+
+  return CouchdbSession;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
new file mode 100644
index 0000000..ff339c7
--- /dev/null
+++ b/app/core/layout.js
@@ -0,0 +1,91 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "backbone", 
+  "plugins/backbone.layoutmanager"
+], function(Backbone) {
+
+  // A wrapper of the main Backbone.layoutmanager
+  // Allows the main layout of the page to be changed by any plugin.
+  var Layout = function () {
+    this.layout = new Backbone.Layout({
+      template: "templates/layouts/with_sidebar",
+    });
+
+    this.layoutViews = {};
+    this.el = this.layout.el;
+  };
+
+  Layout.configure = function (options) {
+    Backbone.Layout.configure(options);
+  };
+
+  // creatings the dashboard object same way backbone does
+  _.extend(Layout.prototype, {
+    render: function () {
+      return this.layout.render();
+    },
+
+    setTemplate: function(template) {
+      if (template.prefix){
+        this.layout.template = template.prefix + template.name;
+      } else{
+        this.layout.template = "templates/layouts/" + template;
+      }
+      // If we're changing layouts all bets are off, so kill off all the
+      // existing views in the layout.
+      _.each(this.layoutViews, function(view){view.remove();});
+      this.layoutViews = {};
+      this.render();
+    },
+
+    setView: function(selector, view, keep) {
+      this.layout.setView(selector, view, false);
+
+      if (!keep) {
+        this.layoutViews[selector] = view;
+      }
+
+      return view;
+    },
+
+    renderView: function(selector) {
+      var view = this.layoutViews[selector];
+      if (!view) {
+        return false;
+      } else {
+        return view.render();
+      }
+    },
+
+    removeView: function (selector) {
+      var view = this.layout.getView(selector);
+
+      if (!view) {
+        return false;
+      }
+
+      view.remove();
+      
+      if (this.layoutViews[selector]) {
+        delete this.layoutViews[selector];
+      }
+
+      return true;
+    }
+
+  });
+
+  return Layout;
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
new file mode 100644
index 0000000..f3b8672
--- /dev/null
+++ b/app/core/routeObject.js
@@ -0,0 +1,296 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "core/base",
+  "backbone"
+],
+function(FauxtonAPI, Backbone) {
+
+  var RouteObject = function(options) {
+    this._options = options;
+
+    this._configure(options || {});
+    this.initialize.apply(this, arguments);
+    this.addEvents();
+  };
+
+  var broadcaster = {};
+  _.extend(broadcaster, Backbone.Events);
+
+  RouteObject.on = function (eventName, fn) {
+    broadcaster.on(eventName, fn); 
+  };
+  
+  /* How Route Object events work
+   To listen to a specific route objects events:
+
+   myRouteObject = FauxtonAPI.RouteObject.extend({
+    events: {
+      "beforeRender": "beforeRenderEvent"
+    },
+
+    beforeRenderEvent: function (view, selector) {
+      console.log('Hey, beforeRenderEvent triggered',arguments);
+    },
+   });
+
+    It is also possible to listen to events triggered from all Routeobjects. 
+    This is great for more general things like adding loaders, hooks.
+
+    FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
+      console.log('hey, this will trigger when any routeobject renders a view');
+    });
+
+   Current Events to subscribe to:
+    * beforeFullRender -- before a full render is being done
+    * beforeEstablish -- before the routeobject calls establish
+    * AfterEstablish -- after the routeobject has run establish
+    * beforeRender -- before a view is rendered
+    * afterRender -- a view is finished being rendered
+    * renderComplete -- all rendering is complete
+    
+  */
+
+  // Piggy-back on Backbone's self-propagating extend function
+  RouteObject.extend = Backbone.Model.extend;
+
+  var routeObjectOptions = ["views", "routes", "events", "roles", "crumbs", "layout", "apiUrl", "establish"];
+
+  _.extend(RouteObject.prototype, Backbone.Events, {
+    // Should these be default vals or empty funcs?
+    views: {},
+    routes: {},
+    events: {},
+    crumbs: [],
+    layout: "with_sidebar",
+    apiUrl: null,
+    disableLoader: false,
+    loaderClassname: 'loader',
+    renderedState: false,
+    establish: function() {},
+    route: function() {},
+    roles: [],
+    _promises: [],
+    initialize: function() {}
+  }, {
+
+    renderWith: function(route, masterLayout, args) {
+      //set the options for this render
+      var options = {
+        masterLayout: masterLayout,
+        route: route,
+        args: args
+      };
+
+      this.setTemplateOnFullRender(masterLayout);
+
+      this.triggerBroadcast('beforeEstablish');
+
+      var renderAllViews = _.bind(this.renderAllViews, this, options),
+          establishError = _.bind(this.establishError, this),
+          renderComplete = _.bind(this.renderComplete, this),
+          promise = this.establish();
+
+      this.callEstablish(promise)
+        .then(renderAllViews, establishError)
+        .then(renderComplete);
+    },
+
+    setTemplateOnFullRender: function(masterLayout){
+      // Only want to redo the template if its a full render
+      if (!this.renderedState) {
+        masterLayout.setTemplate(this.layout);
+        this.triggerBroadcast('beforeFullRender');
+      }
+    },
+
+    callEstablish: function(establishPromise) {
+      this.addPromise(establishPromise);
+      return FauxtonAPI.when(establishPromise);
+    },
+
+    renderAllViews: function(options, resp){
+      var routeObject = this,
+          renderView = _.bind(this.renderView, this, routeObject, options);
+
+      this.triggerBroadcast('afterEstablish');
+
+      var promises = _.map(routeObject.getViews(), renderView, this);
+      return FauxtonAPI.when(promises);
+    },
+    
+    renderView: function(routeObject, options, view, selector) {
+      var viewInfo = {
+        view: view, 
+        selector: selector,
+        masterLayout: options.masterLayout
+      };
+
+      var renderViewOnLayout = _.bind(this.renderViewOnLayout, this, viewInfo);
+
+      if(view.hasRendered) { 
+        this.triggerBroadcast('viewHasRendered', view, selector);
+        return;
+      }
+
+      this.triggerBroadcast('beforeRender', view, selector);
+      
+      return this.callEstablish(view.establish()).then(renderViewOnLayout, this.establishError);
+    },
+
+    renderViewOnLayout: function(viewInfo, resp, xhr){
+      var masterLayout = viewInfo.masterLayout;
+
+      masterLayout.setView(viewInfo.selector, viewInfo.view);
+      masterLayout.renderView(viewInfo.selector);
+
+      this.triggerBroadcast('afterRender', viewInfo.view, viewInfo.selector);
+    },
+
+    establishError: function(resp){
+      if (!resp || !resp.responseText) { return; }
+      FauxtonAPI.addNotification({
+            msg: 'An Error occurred' + JSON.parse(resp.responseText).reason,
+            type: 'error',
+            clear: true
+      });
+    },
+
+    renderComplete: function () {
+      // Track that we've done a full initial render
+      this.setRenderedState(true);
+      this.triggerBroadcast('renderComplete');
+    },
+
+    setRenderedState: function(bool){
+      this.renderedState = bool;
+    },
+    
+    triggerBroadcast: function (eventName) {
+      var args = Array.prototype.slice.call(arguments);
+      this.trigger.apply(this, args);
+
+      args.splice(0,1, eventName, this);
+      broadcaster.trigger.apply(broadcaster, args);
+    },
+
+    get: function(key) {
+      return _.isFunction(this[key]) ? this[key]() : this[key];
+    },
+
+    addEvents: function(events) {
+      events = events || this.get('events');
+      _.each(events, function(method, event) {
+        if (!_.isFunction(method) && !_.isFunction(this[method])) {
+          throw new Error("Invalid method: "+method);
+        }
+        method = _.isFunction(method) ? method : this[method];
+
+        this.on(event, method);
+      }, this);
+    },
+
+    _configure: function(options) {
+      _.each(_.intersection(_.keys(options), routeObjectOptions), function(key) {
+        this[key] = options[key];
+      }, this);
+    },
+
+    getView: function(selector) {
+      return this.views[selector];
+    },
+
+    setView: function(selector, view) {
+      this.views[selector] = view;
+      return view;
+    },
+
+    getViews: function() {
+      return this.views;
+    },
+
+    removeViews: function () {
+      _.each(this.views, function (view, selector) {
+        view.remove();
+        delete this.views[selector];
+      }, this);
+    },
+
+    addPromise: function (promise) {
+      if (_.isEmpty(promise)) { return; }
+
+      if (!_.isArray(promise)) {
+        return this._promises.push(promise);
+      }
+
+      _.each(promise, function (p) {
+          this._promises.push(p);
+      }, this);
+    },
+
+    cleanup: function () {
+      this.removeViews();
+      this.rejectPromises();
+    },
+
+    rejectPromises: function () {
+      _.each(this._promises, function (promise) {
+        if (promise.state() === "resolved") { return; }
+        if (promise.abort) {
+          return promise.abort("Route change");
+        } 
+
+        promise.reject();
+      }, this);
+
+      this._promises = [];
+    },
+
+    getRouteUrls: function () {
+      return _.keys(this.get('routes'));
+    },
+
+    hasRoute: function (route) {
+      if (this.get('routes')[route]) {
+        return true;
+      }
+      return false;
+    },
+
+    routeCallback: function (route, args) {
+      var routes = this.get('routes'),
+      routeObj = routes[route],
+      routeCallback;
+
+      if (typeof routeObj === 'object') {
+        routeCallback = this[routeObj.route];
+      } else {
+        routeCallback = this[routeObj];
+      }
+
+      routeCallback.apply(this, args);
+    },
+
+    getRouteRoles: function (routeUrl) {
+      var route = this.get('routes')[routeUrl];
+
+      if ((typeof route === 'object') && route.roles) {
+        return route.roles; 
+      }
+
+      return this.roles;
+    }
+
+  });
+  return RouteObject;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/router.js
----------------------------------------------------------------------
diff --git a/app/core/router.js b/app/core/router.js
new file mode 100644
index 0000000..cc1ca4f
--- /dev/null
+++ b/app/core/router.js
@@ -0,0 +1,113 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "core/base",
+       "core/auth",
+       "backbone"
+],
+
+function(FauxtonAPI, Auth, Backbone) {
+
+  var beforeUnloads = {};
+
+  var Router = Backbone.Router.extend({
+    routes: {},
+
+    beforeUnload: function (name, fn) {
+      beforeUnloads[name] = fn;
+    },
+
+    removeBeforeUnload: function (name) {
+      delete beforeUnloads[name];
+    },
+
+    navigate: function (fragment, trigger) {
+      var continueNav  = true,
+          msg = _.find(_.map(beforeUnloads, function (fn) { return fn(); }), function (beforeReturn) {
+            if (beforeReturn) { return true; }
+          });
+
+      if (msg) {
+        continueNav = window.confirm(msg);
+      }
+
+      if (continueNav) {
+        Backbone.Router.prototype.navigate(fragment, trigger);
+      }
+    },
+
+    addModuleRouteObject: function(RouteObject) {
+      var that = this;
+      var masterLayout = FauxtonAPI.masterLayout,
+      routeUrls = RouteObject.prototype.getRouteUrls();
+
+      _.each(routeUrls, function(route) {
+        this.route(route, route.toString(), function() {
+          var args = Array.prototype.slice.call(arguments),
+          roles = RouteObject.prototype.getRouteRoles(route),
+          authPromise = FauxtonAPI.auth.checkAccess(roles);
+
+          authPromise.then(function () {
+            if (!that.activeRouteObject || !that.activeRouteObject.hasRoute(route)) {
+              if (that.activeRouteObject) {
+                that.activeRouteObject.cleanup();
+              }
+              that.activeRouteObject = new RouteObject(route, masterLayout, args);
+            }
+
+            var routeObject = that.activeRouteObject;
+            routeObject.routeCallback(route, args);
+            routeObject.renderWith(route, masterLayout, args);
+          }, function () {
+            FauxtonAPI.auth.authDeniedCb();
+          });
+
+        }); 
+      }, this);
+    },
+
+    setModuleRoutes: function(addons) {
+      _.each(addons, function(module) {
+        if (module){
+          module.initialize();
+          // This is pure routes the addon provides
+          if (module.RouteObjects) {
+            _.each(module.RouteObjects, this.addModuleRouteObject, this);
+          }
+        }
+      }, this);
+    },
+
+    initialize: function(addons) {
+      this.addons = addons;
+      this.auth = FauxtonAPI.auth = new Auth();
+      // NOTE: This must be below creation of the layout
+      // FauxtonAPI header links and others depend on existence of the layout
+      this.setModuleRoutes(addons);
+
+      $(FauxtonAPI.el).html(FauxtonAPI.masterLayout.el);
+      FauxtonAPI.masterLayout.render();
+    },
+
+    triggerRouteEvent: function(event, args) {
+      if (this.activeRouteObject) {
+        var eventArgs = [event].concat(args);
+        this.activeRouteObject.trigger.apply(this.activeRouteObject, eventArgs );
+        this.activeRouteObject.renderWith(eventArgs, FauxtonAPI.masterLayout, args);
+      }
+    }
+  });
+
+  return Router;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/tests/layoutSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/layoutSpec.js b/app/core/tests/layoutSpec.js
new file mode 100644
index 0000000..b58966b
--- /dev/null
+++ b/app/core/tests/layoutSpec.js
@@ -0,0 +1,92 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+  'api',
+  'testUtils'
+], function (FauxtonAPI, testUtils) {
+  var assert = testUtils.assert;
+
+  describe("Faxuton Layout", function () {
+    var layout;
+
+    beforeEach(function () {
+      layout = new FauxtonAPI.Layout();
+    });
+
+    describe('#setTemplate', function () {
+
+      it("Should set template without prefix", function () {
+        layout.setTemplate('myTemplate');
+
+        assert.equal(layout.layout.template, 'templates/layouts/myTemplate');
+
+      });
+
+      it("Should set template with prefix", function () {
+        layout.setTemplate({name: 'myTemplate', prefix: 'myPrefix/'});
+
+        assert.equal(layout.layout.template, 'myPrefix/myTemplate');
+      });
+
+      it("Should remove old views", function () {
+        var view = {
+          remove: function () {}
+        };
+
+        layout.layoutViews = {
+          'selector': view
+        };
+
+        var mockRemove = sinon.spy(view, 'remove');
+        layout.setTemplate('myTemplate');
+        assert.ok(mockRemove.calledOnce);
+
+      });
+
+      it("Should render", function () {
+        var mockRender = sinon.spy(layout, 'render');
+
+        layout.setTemplate('myTemplate');
+
+        assert.ok(mockRender.calledOnce);
+
+      });
+
+    });
+
+    describe('#renderView', function () {
+
+      it('Should render existing view', function () {
+        var view = new Backbone.View();
+        var mockRender = sinon.spy(view, 'render');
+        layout.layoutViews = {
+          '#selector': view
+        };
+
+        var out = layout.renderView('#selector');
+
+        assert.ok(mockRender.calledOnce);
+      });
+
+      it('Should return false for non-existing view', function () {
+        var view = new Backbone.View();
+        layout.layoutViews = {
+          'selector': view
+        };
+
+        var out = layout.renderView('wrongSelector');
+        assert.notOk(out, 'No view found');
+      });
+    });
+
+  });
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/tests/routeObjectSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/routeObjectSpec.js b/app/core/tests/routeObjectSpec.js
new file mode 100644
index 0000000..2fca94d
--- /dev/null
+++ b/app/core/tests/routeObjectSpec.js
@@ -0,0 +1,96 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+       'api',
+      'testUtils'
+], function (FauxtonAPI, testUtils) {
+  var assert = testUtils.assert,
+      RouteObject = FauxtonAPI.RouteObject;
+
+  describe('RouteObjects', function () {
+
+    describe('renderWith', function () {
+      var TestRouteObject, testRouteObject, mockLayout;
+
+      beforeEach(function () {
+        TestRouteObject = RouteObject.extend({
+          crumbs: ['mycrumbs']
+        });
+
+        testRouteObject = new TestRouteObject();
+        var apiBar = {};
+        apiBar.hide = sinon.spy();
+
+        // Need to find a better way of doing this
+        mockLayout = {
+          setTemplate: sinon.spy(),
+          clearBreadcrumbs: sinon.spy(),
+          setView: sinon.spy(),
+          renderView: sinon.spy(),
+          hooks: [],
+          setBreadcrumbs: sinon.spy(),
+          apiBar: apiBar
+        };
+
+      });
+
+      it('Should set template for first render ', function () {
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+
+        assert.ok(mockLayout.setTemplate.calledOnce, 'setTempalte was called');
+      });
+
+      it('Should not set template after first render', function () {
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+
+        assert.ok(mockLayout.setTemplate.calledOnce, 'SetTemplate not meant to be called');
+      });
+
+      
+      it("Should call establish of routeObject", function () {
+        var establishSpy = sinon.spy(testRouteObject,"establish");
+
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+        assert.ok(establishSpy.calledOnce, 'Calls establish');
+      });
+
+      it("Should render views", function () {
+        var view = new FauxtonAPI.View(),
+            getViewsSpy = sinon.stub(testRouteObject,"getViews"),
+            viewSpy = sinon.stub(view, "establish");
+        
+        view.hasRendered = false;
+        getViewsSpy.returns({'#view': view});
+
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+        assert.ok(viewSpy.calledOnce, 'Should render view');
+      });
+
+      it("Should not re-render a view", function () {
+        var view = new FauxtonAPI.View(),
+            getViewsSpy = sinon.stub(testRouteObject,"getViews"),
+            viewSpy = sinon.stub(view, "establish");
+        
+        view.hasRendered = true;
+        getViewsSpy.returns({'#view': view});
+
+        testRouteObject.renderWith('the-route', mockLayout, 'args');
+        assert.notOk(viewSpy.calledOnce, 'Should render view');
+      });
+    });
+
+  });
+
+
+});


[22/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix for running preview on indexes  (I think this got accidentally commented out?)


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/733c71e1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/733c71e1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/733c71e1

Branch: refs/heads/import-master
Commit: 733c71e12b4dbbc0c23a1b47d5a22a33335e1283
Parents: a210c87
Author: suelockwood <de...@apache.org>
Authored: Wed Jan 15 16:22:52 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Wed Jan 15 16:22:52 2014 -0500

----------------------------------------------------------------------
 app/addons/pouchdb/pouch.collate.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/733c71e1/app/addons/pouchdb/pouch.collate.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/pouch.collate.js b/app/addons/pouchdb/pouch.collate.js
index 6c64410..31e5650 100644
--- a/app/addons/pouchdb/pouch.collate.js
+++ b/app/addons/pouchdb/pouch.collate.js
@@ -110,6 +110,6 @@ function(app, FauxtonAPI, Collate) {
 
   return Pouch;
 
-//}).call(this);
+}).call(this);
+
 
-});


[06/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Rename mixins to utils, add app.host to urls


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/5ba0f8ee
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/5ba0f8ee
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/5ba0f8ee

Branch: refs/heads/import-master
Commit: 5ba0f8eef3b14ba15900903d61f9ba0fef96006c
Parents: 5f9a88f
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Jan 13 11:09:19 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Jan 13 11:09:19 2014 +0200

----------------------------------------------------------------------
 app/addons/auth/resources.js                    |   6 +-
 app/addons/config/assets/less/config.less       |  44 ++++
 app/addons/config/templates/item.html           |   2 +-
 app/addons/databases/assets/less/databases.less | 247 +++++++++++++++++++
 app/addons/databases/base.js                    |   2 +-
 app/addons/databases/resources.js               |   6 +-
 app/addons/databases/views.js                   |   8 +-
 app/addons/documents/resources.js               |  14 +-
 app/addons/documents/routes.js                  |   4 +-
 app/addons/documents/views.js                   |  20 +-
 app/addons/logs/assets/less/logs.less           |  24 ++
 app/addons/permissions/resources.js             |   2 +-
 app/addons/verifyinstall/resources.js           |   7 +-
 app/api.js                                      |   2 +-
 app/app.js                                      |   6 +-
 app/helpers.js                                  |   3 +-
 app/mixins.js                                   |  66 -----
 app/resizeColumns.js                            |  10 +-
 app/utils.js                                    |  66 +++++
 assets/less/config.less                         |  46 ----
 assets/less/database.less                       | 245 ------------------
 assets/less/fauxton.less                        |   3 -
 assets/less/logs.less                           |  24 --
 23 files changed, 425 insertions(+), 432 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/auth/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/resources.js b/app/addons/auth/resources.js
index b1d40cc..970d55b 100644
--- a/app/addons/auth/resources.js
+++ b/app/addons/auth/resources.js
@@ -47,7 +47,7 @@ function (app, FauxtonAPI) {
   });
 
   Auth.Session = FauxtonAPI.Session.extend({
-    url: '/_session',
+    url: app.host + '/_session',
 
     initialize: function (options) {
       if (!options) { options = {}; }
@@ -155,7 +155,7 @@ function (app, FauxtonAPI) {
       return $.ajax({
         cache: false,
         type: "POST", 
-        url: "/_session", 
+        url: app.host + "/_session", 
         dataType: "json",
         data: {name: username, password: password}
       }).then(function () {
@@ -168,7 +168,7 @@ function (app, FauxtonAPI) {
 
       return $.ajax({
         type: "DELETE", 
-        url: "/_session", 
+        url: app.host + "/_session", 
         dataType: "json",
         username : "_", 
         password : "_"

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/config/assets/less/config.less
----------------------------------------------------------------------
diff --git a/app/addons/config/assets/less/config.less b/app/addons/config/assets/less/config.less
index 86d9bf1..8495b69 100644
--- a/app/addons/config/assets/less/config.less
+++ b/app/addons/config/assets/less/config.less
@@ -1,3 +1,47 @@
+/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ *  use this file except in compliance with the License. You may obtain a copy of
+ *  the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations under
+ *  the License.
+ */
+
+.config-item {
+  height: 41px;
+
+  .edit-button {
+    float: right;
+    .btn;
+    .btn-mini;
+    display:none;
+  }
+
+  td:hover .edit-button {
+    display: block;
+  }
+
+  .value-input {
+    width: 98%;
+  }
+
+  #delete-value {
+    cursor: pointer;
+  }
+}
+
+.button-margin {
+  margin-bottom: 15px;
+}
+
+#add-section-modal {
+  width: 400px;
+}
+
 table.config {
   #config-trash {
     width: 5%;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/config/templates/item.html
----------------------------------------------------------------------
diff --git a/app/addons/config/templates/item.html b/app/addons/config/templates/item.html
index 3e6e4ee..1c808b9 100644
--- a/app/addons/config/templates/item.html
+++ b/app/addons/config/templates/item.html
@@ -20,7 +20,7 @@ the License.
 <td> <%= option.name %> </td>
 <td>
   <div id="show-value">
-    <%= option.value %> <button class="edit-button"> Edit </button>
+    <%= option.value %> <button class="edit-button btn-mini btn"> Edit </button>
   </div>
   <div id="edit-value-form" style="display:none">
     <input class="value-input" type="text" value="<%= option.value %>" />

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/databases/assets/less/databases.less
----------------------------------------------------------------------
diff --git a/app/addons/databases/assets/less/databases.less b/app/addons/databases/assets/less/databases.less
new file mode 100644
index 0000000..3d86d81
--- /dev/null
+++ b/app/addons/databases/assets/less/databases.less
@@ -0,0 +1,247 @@
+/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ *  use this file except in compliance with the License. You may obtain a copy of
+ *  the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations under
+ *  the License.
+ */
+
+/* =database
+   ---------------------------------------------------------------------- */
+@import "../../../../../assets/less/bootstrap/variables.less";  
+@import "../../../../../assets/less/bootstrap/mixins.less";   
+#db-tools {
+    position: absolute;
+    top: -7px;
+    right: 0;
+    width: 390px;
+
+    .btn-group {
+        position: absolute;
+        left: 0;
+        top: 6px;
+    }
+
+    form {
+        position: absolute;
+        right: 0;
+        top: 0;
+    }
+}
+
+.tools .nav {
+    margin-bottom: 10px;
+}
+
+#sidenav {
+    padding-top: 10px;
+
+    h3 {
+        margin: 10px 0;
+    }
+
+    li a span.divider {
+        background: none;
+        color: #ccc;
+        padding: 0 2px;
+    }
+
+    li.nav-header a {
+        display: inline
+    }
+
+    div.btn-group {
+        display: inline-block;
+    }
+
+    li.nav-header, #sidenav li a {
+        padding-left: 4px;
+    }
+
+    li.active a {
+        background-color: #ddd;
+        color: #333;
+        text-shadow: none;
+    }
+}
+
+.edit {
+    display: none;
+
+    form {
+        margin-bottom: 0;
+    }
+
+    h3 {
+        border-bottom: 1px solid #ccc;
+        font-size: 100%;
+        line-height: 1;
+        margin-bottom: 18px;
+    }
+
+    textarea {
+        height: 100px;
+        width: 95%;
+    }
+
+    .btn-toolbar {
+        margin-bottom: 0;
+    }
+
+    .preview {
+        width: 100px;
+    }
+
+    .save {
+    }
+}
+
+#new-view-index {
+    .confirm {
+        display: none;
+    }
+
+    .confirm .progress {
+        display: none;
+        margin: 20px;
+    }
+
+    textarea {
+        height: 100px;
+        width: 95%;
+    }
+}
+
+.view {
+    display: none;
+
+    .result-tools {
+        float: left;
+        width: 100%;
+        margin-bottom: 10px;
+    }
+
+    table td div  {
+        position: relative;
+    }
+
+    table td div div {
+        display: none;
+        line-height: 1;
+        position: absolute;
+        right: 4px;
+        top: 4px;
+    }
+
+    table td div:hover div a.edits {
+        padding-left: 16px;
+        padding-right: 16px;
+    }
+
+    table td div:hover div {
+        display: block;
+    }
+
+}
+.view.show {
+    display: block;
+}
+.view.show.hidden-by-params {
+    display: none;
+}
+#database .view table tr td {
+    padding: 0;
+}
+
+.loading {display: none;}
+
+.view-request-duration {
+  padding-right: 10px;
+  float: right;
+}
+
+table.active-tasks{
+    th {
+        cursor: pointer;
+    }
+}
+
+.well{
+    .row-fluid{
+        margin: 0;
+    }
+    .row-fluid .row-fluid:last-child .well-item {
+        border: none;
+    }
+    .well-item{
+        color: #666;
+        font-size: 12px;
+        border-bottom: 1px solid #e5e5e5;
+        padding: 8px 4px;
+        strong {
+            font-size: 16px;
+        }  
+    } 
+}
+
+
+#doc {
+    .dropdown-menu{
+        width: auto;
+    }
+}
+// #tabs {
+//     height: 40px;
+// }
+
+.databases{
+    a.db-actions,
+    a.db-actions:visited{
+        color: @red; 
+        border: 1px solid #e3e3e3;
+        padding: 5px 7px;
+        .border-radius(6px);
+        text-decoration: none;
+        font-size: 19px;
+    }
+}
+.btn-group{
+    ul.dropdown-menu li a:before{
+        margin-right: 10px;
+    }
+}
+
+.design-doc-group{
+    .span3 { margin: 0;}
+    #new-ddoc-section {
+        margin-top: 10px;
+        label{ width: 100px}
+        .controls{
+            margin-left: 100px;
+        }
+    }
+}
+table#changes-table {
+
+  #changes {
+    width: 50%;
+  }
+
+  #seq, #deleted {
+    width: 5%;
+  }
+
+}
+
+.doc-editor-buttons {
+    margin-bottom: 15px;
+    a.button.btn-large.gray {
+        padding: 9px 10px;
+        vertical-align: middle;
+    }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/databases/base.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/base.js b/app/addons/databases/base.js
index 1a3dc66..ea1719c 100644
--- a/app/addons/databases/base.js
+++ b/app/addons/databases/base.js
@@ -28,7 +28,7 @@ function(app, FauxtonAPI, Databases, Views) {
   // Utility functions
   Databases.databaseUrl = function(database) {
     var name = _.isObject(database) ? database.id : database,
-        dbname = app.mixins.safeURLName(name);
+        dbname = app.utils.safeURLName(name);
 
     return ["/database/", dbname, "/_all_docs?limit=" + Databases.DocLimit].join('');
   };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index b6d6536..3510154 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -67,10 +67,10 @@ function(app, FauxtonAPI, Documents) {
       }
     },
     safeName: function(){
-      return app.mixins.safeURLName(this.get("name"));
+      return app.utils.safeURLName(this.get("name"));
     },
     safeID: function() {
-      return app.mixins.safeURLName(this.id);
+      return app.utils.safeURLName(this.id);
     },
     buildChanges: function (params) {
       this.changes = new Databases.Changes({
@@ -182,7 +182,7 @@ function(app, FauxtonAPI, Documents) {
       // TODO: pagination!
       return _.map(resp, function(database) {
         return {
-          id: app.mixins.safeURLName(database),
+          id: app.utils.safeURLName(database),
           name: database
         };
       });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
index 80d64ed..0068305 100644
--- a/app/addons/databases/views.js
+++ b/app/addons/databases/views.js
@@ -29,7 +29,7 @@ function(app, Components, FauxtonAPI, Databases) {
     },
     serialize: function() {
       return {
-        encoded: app.mixins.safeURLName(this.model.get("name")),
+        encoded: app.utils.safeURLName(this.model.get("name")),
         database: this.model,
         docLimit: Databases.DocLimit
       };
@@ -77,11 +77,11 @@ function(app, Components, FauxtonAPI, Databases) {
         dbname = selectedName;
       }
 
-      if (dbname && this.collection.where({"id":app.mixins.safeURLName(dbname)}).length > 0){
+      if (dbname && this.collection.where({"id":app.utils.safeURLName(dbname)}).length > 0){
           // TODO: switch to using a model, or Databases.databaseUrl()
           // Neither of which are in scope right now
           // var db = new Database.Model({id: dbname});
-          var url = ["/database/", app.mixins.safeURLName(dbname), "/_all_docs?limit=" + Databases.DocLimit].join('');
+          var url = ["/database/", app.utils.safeURLName(dbname), "/_all_docs?limit=" + Databases.DocLimit].join('');
           FauxtonAPI.navigate(url);
       } else {
         FauxtonAPI.addNotification({
@@ -173,7 +173,7 @@ function(app, Components, FauxtonAPI, Databases) {
           type: "success",
           clear: true
         });
-        var route = "#/database/" +  app.mixins.safeURLName(name) + "/_all_docs?limit=" + Databases.DocLimit;
+        var route = "#/database/" +  app.utils.safeURLName(name) + "/_all_docs?limit=" + Databases.DocLimit;
         app.router.navigate(route, { trigger: true });
       }
       ).error(function(xhr) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 5254302..5e10ded 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -27,7 +27,7 @@ function(app, FauxtonAPI) {
       if (context === "app") {
         return this.getDatabase().url("app") + "/" + this.safeID();
       } else if (context === "web-index") {
-        return this.getDatabase().url("app") + "/" + app.mixins.safeURLName(this.id);
+        return this.getDatabase().url("app") + "/" + app.utils.safeURLName(this.id);
       } else if (context === "apiurl"){
         return window.location.origin + "/" + this.getDatabase().safeID() + "/" + this.safeID();
       } else {
@@ -143,9 +143,9 @@ function(app, FauxtonAPI) {
     safeID: function() {
       if (this.isDdoc()){
         var ddoc = this.id.replace(/^_design\//,"");
-        return "_design/"+app.mixins.safeURLName(ddoc);
+        return "_design/"+app.utils.safeURLName(ddoc);
       }else{
-        return app.mixins.safeURLName(this.id);
+        return app.utils.safeURLName(this.id);
       }
     },
 
@@ -219,7 +219,7 @@ function(app, FauxtonAPI) {
     // json editor for docs, or into a ddoc specific page.
     safeID: function() {
       var ddoc = this.id.replace(/^_design\//,"");
-      return "_design/"+app.mixins.safeURLName(ddoc);
+      return "_design/"+app.utils.safeURLName(ddoc);
     }
 
   });
@@ -247,7 +247,7 @@ function(app, FauxtonAPI) {
       return this.docType() != "reduction";
     },
     safeID: function() {
-      return app.mixins.safeURLName(this.id);
+      return app.utils.safeURLName(this.id);
     },
 
     prettyJSON: function() {
@@ -423,8 +423,8 @@ function(app, FauxtonAPI) {
       } else if (context === "apiurl"){
         startOfUrl = window.location.origin;
       }
-      var design = app.mixins.safeURLName(this.design),
-          view = app.mixins.safeURLName(this.view);
+      var design = app.utils.safeURLName(this.design),
+          view = app.utils.safeURLName(this.view);
 
       var url = [startOfUrl, this.database.safeID(), "_design", design, this.idxType, view];
       return url.join("/") + query;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index d120feb..6786edf 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -92,7 +92,7 @@ function(app, FauxtonAPI, Documents, Databases) {
       doc.copy(newId).then(function () {
         doc.set({_id: newId}); 
         docView.forceRender();
-        FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.mixins.safeURLName(newId), {trigger: true});
+        FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.utils.safeURLName(newId), {trigger: true});
         FauxtonAPI.addNotification({
           msg: "Document has been duplicated."
         });
@@ -259,7 +259,7 @@ function(app, FauxtonAPI, Documents, Databases) {
         ddocInfo: ddocInfo
       }));
 
-      this.sidebar.setSelectedTab(app.mixins.removeSpecialCharacters(ddoc) + '_' + app.mixins.removeSpecialCharacters(view));
+      this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view));
 
       this.crumbs = function () {
         return [

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 97d58e3..80c0d87 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -241,7 +241,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     duplicate: function (event) {
       event.preventDefault();
       var newId = this.$('#dup-id').val(),
-          encodedID = app.mixins.safeURLName(newId);
+          encodedID = app.utils.safeURLName(newId);
 
       this.hideModal();
       FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
@@ -423,11 +423,11 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         index: this.index,
         ddoc: this.ddoc,
         database: this.database,
-        index_clean: app.mixins.removeSpecialCharacters(this.index),
-        ddoc_clean: app.mixins.removeSpecialCharacters(this.ddoc), 
-        index_encoded: app.mixins.safeURLName(this.index),
-        ddoc_encoded: app.mixins.safeURLName(this.ddoc),
-        database_encoded: app.mixins.safeURLName(this.database),
+        index_clean: app.utils.removeSpecialCharacters(this.index),
+        ddoc_clean: app.utils.removeSpecialCharacters(this.ddoc), 
+        index_encoded: app.utils.safeURLName(this.index),
+        ddoc_encoded: app.utils.safeURLName(this.ddoc),
+        database_encoded: app.utils.safeURLName(this.database),
         selected: this.selected
       };
     },
@@ -470,7 +470,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       }
 
       return {
-        database: app.mixins.safeURLName(this.collection.database.id),
+        database: app.utils.safeURLName(this.collection.database.id),
         updateSeq: updateSeq,
         offset: recordStart,
         totalRows: totalRows,
@@ -1365,7 +1365,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
           });
 
           if (that.newView) {
-            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.mixins.safeURLName(viewName); 
+            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName); 
 
             FauxtonAPI.navigate(fragment, {trigger: false});
             that.newView = false;
@@ -1375,7 +1375,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
             that.showIndex = true;
             that.render();
             FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
-              selectedTab: app.mixins.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.mixins.removeSpecialCharacters(viewName)
+              selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName)
             });
           }
 
@@ -1675,7 +1675,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     jumpToDoc: function (event) {
       event.preventDefault();
       var docId = this.$('#jump-to-doc-id').val().trim();
-      FauxtonAPI.navigate('/database/' + app.mixins.safeURLName(this.database.id) +'/' + app.mixins.safeURLName(docId), {trigger: true});
+      FauxtonAPI.navigate('/database/' + app.utils.safeURLName(this.database.id) +'/' + app.utils.safeURLName(docId), {trigger: true});
     },
 
     afterRender: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/logs/assets/less/logs.less
----------------------------------------------------------------------
diff --git a/app/addons/logs/assets/less/logs.less b/app/addons/logs/assets/less/logs.less
new file mode 100644
index 0000000..e50f903
--- /dev/null
+++ b/app/addons/logs/assets/less/logs.less
@@ -0,0 +1,24 @@
+/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ *  use this file except in compliance with the License. You may obtain a copy of
+ *  the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations under
+ *  the License.
+ */
+
+#log-sidebar {
+  
+  ul {
+    margin-left: 0px;
+    list-style: none;
+  }
+
+  .remove-filter {
+     opacity: 0.2;
+  }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/permissions/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/permissions/resources.js b/app/addons/permissions/resources.js
index 66eaffd..8acaddd 100644
--- a/app/addons/permissions/resources.js
+++ b/app/addons/permissions/resources.js
@@ -39,7 +39,7 @@ function (app, FauxtonAPI ) {
     },
 
     url: function () {
-      return this.database.id + '/_security';
+      return app.host + this.database.id + '/_security';
     },
 
     addItem: function (value, type, section) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/addons/verifyinstall/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/verifyinstall/resources.js b/app/addons/verifyinstall/resources.js
index 8a98883..aa08997 100644
--- a/app/addons/verifyinstall/resources.js
+++ b/app/addons/verifyinstall/resources.js
@@ -130,7 +130,7 @@ function (app, FauxtonAPI, Databases, Documents) {
 
     setupReplicate: function () {
       return $.ajax({
-        url: '/_replicate',
+        url: app.host + '/_replicate',
         contentType: 'application/json',
         type: 'POST',
         dataType: 'json',
@@ -145,11 +145,6 @@ function (app, FauxtonAPI, Databases, Documents) {
 
     testReplicate: function () {
       var deferred = FauxtonAPI.Deferred();
-      /*var dbReplicate = new Databases.Model({
-          id: 'verifytestdb_replicate',
-          name: 'verifytestdb_replicate'
-        });*/
-
       var promise = dbReplicate.fetch();
 
       promise.then(function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/api.js
----------------------------------------------------------------------
diff --git a/app/api.js b/app/api.js
index c9d08bf..f423ef5 100644
--- a/app/api.js
+++ b/app/api.js
@@ -132,7 +132,7 @@ function(app, Fauxton) {
   });
 
   FauxtonAPI.Session = Backbone.Model.extend({
-    url: '/_session',
+    url: app.host + '/_session',
 
     user: function () {
       var userCtx = this.get('userCtx');

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/app.js
----------------------------------------------------------------------
diff --git a/app/app.js b/app/app.js
index 9ac5bc2..5325f77 100644
--- a/app/app.js
+++ b/app/app.js
@@ -21,7 +21,7 @@ define([
   "bootstrap",
 
   "helpers",
-  "mixins",
+  "utils",
   // Modules
   "resizeColumns",
 
@@ -31,7 +31,7 @@ define([
 
 ],
 
-function(app, $, _, Backbone, Bootstrap, Helpers, Mixins, resizeColumns) {
+function(app, $, _, Backbone, Bootstrap, Helpers, Utils, resizeColumns) {
 
    // Make sure we have a console.log
   if (typeof console == "undefined") {
@@ -43,7 +43,7 @@ function(app, $, _, Backbone, Bootstrap, Helpers, Mixins, resizeColumns) {
   // Provide a global location to place configuration settings and module
   // creation also mix in Backbone.Events
   _.extend(app, Backbone.Events, {
-    mixins: Mixins,
+    utils: Utils,
 
     renderView: function(baseView, selector, view, options, callback) {
       baseView.setView(selector, new view(options)).render().then(callback);

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/helpers.js
----------------------------------------------------------------------
diff --git a/app/helpers.js b/app/helpers.js
index 73a37ca..d4836b9 100644
--- a/app/helpers.js
+++ b/app/helpers.js
@@ -48,7 +48,8 @@ function() {
     "_active_tasks": "http://docs.couchdb.org/en/latest/api/server/common.html?highlight=stats#active-tasks",
     "log": "http://docs.couchdb.org/en/latest/api/server/common.html?highlight=stats#log",
     "config": "http://docs.couchdb.org/en/latest/config/index.html",
-    "views": "http://docs.couchdb.org/en/latest/intro/overview.html#views"
+    "views": "http://docs.couchdb.org/en/latest/intro/overview.html#views",
+    "changes": "http://docs.couchdb.org/en/latest/api/database/changes.html?highlight=changes#post--db-_changes"
   }; 
   
   Helpers.getDocUrl = function(docKey){

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/mixins.js
----------------------------------------------------------------------
diff --git a/app/mixins.js b/app/mixins.js
deleted file mode 100644
index 3679ec1..0000000
--- a/app/mixins.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-// This file creates a set of helper functions that will be loaded for all html
-// templates. These functions should be self contained and not rely on any 
-// external dependencies as they are loaded prior to the application. We may
-// want to change this later, but for now this should be thought of as a
-// "purely functional" helper system.
-
-
-define([
-  "jquery",
-  "lodash"
-],
-
-function($, _ ) {
-
-  var mixins = {};
-
-  var onWindowResize = {};
-   
-  mixins.addWindowResize = function(fun, key){
-    onWindowResize[key]=fun;
-    // You shouldn't need to call it here. Just define it at startup and each time it will loop 
-    // through all the functions in the hash.
-    //app.initWindowResize();
-  };
-   
-  mixins.removeWindowResize = function(key){
-    delete onWindowResize[key];
-    mixins.initWindowResize();
-  };
-   
-  mixins.initWindowResize = function(){
-  //when calling this it should be overriding what was called previously
-    window.onresize = function(e) {
-       // could do this instead of the above for loop
-      _.each(onWindowResize, function (fn) {
-        fn();
-      });
-    };
-  };
-
-  mixins.removeSpecialCharacters = function(name){
-    return name.replace(/[^\w\s]/gi,"");
-  };
-
-  mixins.safeURLName = function(name){
-    var testName = name || "";
-    var checkforBad = testName.match(/[\$\-/_,+-]/g);
-    return (checkforBad !== null)?encodeURIComponent(name):name;
-  };
-
-  return mixins;
-});
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/resizeColumns.js
----------------------------------------------------------------------
diff --git a/app/resizeColumns.js b/app/resizeColumns.js
index 9cf7115..bb50767 100644
--- a/app/resizeColumns.js
+++ b/app/resizeColumns.js
@@ -18,10 +18,10 @@
 // "purely functional" helper system.
 
 define([
-  "mixins"
+  "utils"
 ],
 
-function(mixins) {
+function(utils) {
 
   var Resize = function(options){
     this.options = options;
@@ -42,8 +42,8 @@ function(mixins) {
       var that = this;
       //add throttler :) 
       this.lazyLayout = _.debounce(that.onResizeHandler, 300).bind(this);
-      mixins.addWindowResize(this.lazyLayout,"animation");
-      mixins.initWindowResize();
+      utils.addWindowResize(this.lazyLayout,"animation");
+      utils.initWindowResize();
       this.onResizeHandler();
     },
     updateOptions:function(options){
@@ -52,7 +52,7 @@ function(mixins) {
       this.options.selectorElements = options.selectorElements || ".window-resizeable";
     },
     turnOff:function(){
-      mixins.removeWindowResize("animation");
+      utils.removeWindowResize("animation");
     },
     cleanupCallback: function(){
       this.callback = null;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/app/utils.js
----------------------------------------------------------------------
diff --git a/app/utils.js b/app/utils.js
new file mode 100644
index 0000000..ded7dac
--- /dev/null
+++ b/app/utils.js
@@ -0,0 +1,66 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+
+// This file creates a set of helper functions that will be loaded for all html
+// templates. These functions should be self contained and not rely on any 
+// external dependencies as they are loaded prior to the application. We may
+// want to change this later, but for now this should be thought of as a
+// "purely functional" helper system.
+
+
+define([
+  "jquery",
+  "lodash"
+],
+
+function($, _ ) {
+
+  var utils = {};
+
+  var onWindowResize = {};
+   
+  utils.addWindowResize = function(fun, key){
+    onWindowResize[key]=fun;
+    // You shouldn't need to call it here. Just define it at startup and each time it will loop 
+    // through all the functions in the hash.
+    //app.initWindowResize();
+  };
+   
+  utils.removeWindowResize = function(key){
+    delete onWindowResize[key];
+    utils.initWindowResize();
+  };
+   
+  utils.initWindowResize = function(){
+  //when calling this it should be overriding what was called previously
+    window.onresize = function(e) {
+       // could do this instead of the above for loop
+      _.each(onWindowResize, function (fn) {
+        fn();
+      });
+    };
+  };
+
+  utils.removeSpecialCharacters = function(name){
+    return name.replace(/[^\w\s]/gi,"");
+  };
+
+  utils.safeURLName = function(name){
+    var testName = name || "";
+    var checkforBad = testName.match(/[\$\-/_,+-]/g);
+    return (checkforBad !== null)?encodeURIComponent(name):name;
+  };
+
+  return utils;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/assets/less/config.less
----------------------------------------------------------------------
diff --git a/assets/less/config.less b/assets/less/config.less
deleted file mode 100644
index fe03796..0000000
--- a/assets/less/config.less
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
- *  use this file except in compliance with the License. You may obtain a copy of
- *  the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *  License for the specific language governing permissions and limitations under
- *  the License.
- */
-
-.config-item {
-  height: 41px;
-
-  .edit-button {
-    float: right;
-    .btn;
-    .btn-mini;
-    display:none;
-  }
-
-  td:hover .edit-button {
-    display: block;
-  }
-
-  .value-input {
-    width: 98%;
-  }
-
-  #delete-value {
-    cursor: pointer;
-  }
-}
-
-.button-margin {
-  margin-bottom: 15px;
-}
-
-#add-section-modal {
-  width: 400px;
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/assets/less/database.less
----------------------------------------------------------------------
diff --git a/assets/less/database.less b/assets/less/database.less
deleted file mode 100644
index 377b136..0000000
--- a/assets/less/database.less
+++ /dev/null
@@ -1,245 +0,0 @@
-/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
- *  use this file except in compliance with the License. You may obtain a copy of
- *  the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *  License for the specific language governing permissions and limitations under
- *  the License.
- */
-
-/* =database
-   ---------------------------------------------------------------------- */
-#db-tools {
-    position: absolute;
-    top: -7px;
-    right: 0;
-    width: 390px;
-
-    .btn-group {
-        position: absolute;
-        left: 0;
-        top: 6px;
-    }
-
-    form {
-        position: absolute;
-        right: 0;
-        top: 0;
-    }
-}
-
-.tools .nav {
-    margin-bottom: 10px;
-}
-
-#sidenav {
-    padding-top: 10px;
-
-    h3 {
-        margin: 10px 0;
-    }
-
-    li a span.divider {
-        background: none;
-        color: #ccc;
-        padding: 0 2px;
-    }
-
-    li.nav-header a {
-        display: inline
-    }
-
-    div.btn-group {
-        display: inline-block;
-    }
-
-    li.nav-header, #sidenav li a {
-        padding-left: 4px;
-    }
-
-    li.active a {
-        background-color: #ddd;
-        color: #333;
-        text-shadow: none;
-    }
-}
-
-.edit {
-    display: none;
-
-    form {
-        margin-bottom: 0;
-    }
-
-    h3 {
-        border-bottom: 1px solid #ccc;
-        font-size: 100%;
-        line-height: 1;
-        margin-bottom: 18px;
-    }
-
-    textarea {
-        height: 100px;
-        width: 95%;
-    }
-
-    .btn-toolbar {
-        margin-bottom: 0;
-    }
-
-    .preview {
-        width: 100px;
-    }
-
-    .save {
-    }
-}
-
-#new-view-index {
-    .confirm {
-        display: none;
-    }
-
-    .confirm .progress {
-        display: none;
-        margin: 20px;
-    }
-
-    textarea {
-        height: 100px;
-        width: 95%;
-    }
-}
-
-.view {
-    display: none;
-
-    .result-tools {
-        float: left;
-        width: 100%;
-        margin-bottom: 10px;
-    }
-
-    table td div  {
-        position: relative;
-    }
-
-    table td div div {
-        display: none;
-        line-height: 1;
-        position: absolute;
-        right: 4px;
-        top: 4px;
-    }
-
-    table td div:hover div a.edits {
-        padding-left: 16px;
-        padding-right: 16px;
-    }
-
-    table td div:hover div {
-        display: block;
-    }
-
-}
-.view.show {
-    display: block;
-}
-.view.show.hidden-by-params {
-    display: none;
-}
-#database .view table tr td {
-    padding: 0;
-}
-
-.loading {display: none;}
-
-.view-request-duration {
-  padding-right: 10px;
-  float: right;
-}
-
-table.active-tasks{
-    th {
-        cursor: pointer;
-    }
-}
-
-.well{
-    .row-fluid{
-        margin: 0;
-    }
-    .row-fluid .row-fluid:last-child .well-item {
-        border: none;
-    }
-    .well-item{
-        color: #666;
-        font-size: 12px;
-        border-bottom: 1px solid #e5e5e5;
-        padding: 8px 4px;
-        strong {
-            font-size: 16px;
-        }  
-    } 
-}
-
-
-#doc {
-    .dropdown-menu{
-        width: auto;
-    }
-}
-// #tabs {
-//     height: 40px;
-// }
-
-.databases{
-    a.db-actions,
-    a.db-actions:visited{
-        color: @red; 
-        border: 1px solid #e3e3e3;
-        padding: 5px 7px;
-        .border-radius(6px);
-        text-decoration: none;
-        font-size: 19px;
-    }
-}
-.btn-group{
-    ul.dropdown-menu li a:before{
-        margin-right: 10px;
-    }
-}
-
-.design-doc-group{
-    .span3 { margin: 0;}
-    #new-ddoc-section {
-        margin-top: 10px;
-        label{ width: 100px}
-        .controls{
-            margin-left: 100px;
-        }
-    }
-}
-table#changes-table {
-
-  #changes {
-    width: 50%;
-  }
-
-  #seq, #deleted {
-    width: 5%;
-  }
-
-}
-
-.doc-editor-buttons {
-    margin-bottom: 15px;
-    a.button.btn-large.gray {
-        padding: 9px 10px;
-        vertical-align: middle;
-    }
-}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/assets/less/fauxton.less
----------------------------------------------------------------------
diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less
index 510c3c1..d41780a 100644
--- a/assets/less/fauxton.less
+++ b/assets/less/fauxton.less
@@ -19,10 +19,7 @@
 @import "bootstrap/bootstrap.less";
 @import "bootstrap/mixins.less";
 @import "variables.less";
-@import "config.less";
-@import "logs.less";
 @import "prettyprint.less";
-@import "database.less";
 @import "icons.less";
 
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5ba0f8ee/assets/less/logs.less
----------------------------------------------------------------------
diff --git a/assets/less/logs.less b/assets/less/logs.less
deleted file mode 100644
index e50f903..0000000
--- a/assets/less/logs.less
+++ /dev/null
@@ -1,24 +0,0 @@
-/*  Licensed under the Apache License, Version 2.0 (the "License"); you may not
- *  use this file except in compliance with the License. You may obtain a copy of
- *  the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *  License for the specific language governing permissions and limitations under
- *  the License.
- */
-
-#log-sidebar {
-  
-  ul {
-    margin-left: 0px;
-    list-style: none;
-  }
-
-  .remove-filter {
-     opacity: 0.2;
-  }
-}


[37/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
dry out delete events


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/24ce023e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/24ce023e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/24ce023e

Branch: refs/heads/import-master
Commit: 24ce023ef78a7a8319e9e6a67022d033b29fc398
Parents: ab1b2c1
Author: Simon Metson <si...@cloudant.com>
Authored: Sun Jan 26 19:04:57 2014 +0000
Committer: suelockwood <de...@apache.org>
Committed: Wed Jan 29 10:34:29 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/24ce023e/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 93fd0d4..fd7d034 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -40,10 +40,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.active_id = options.active_id;
     },
 
-    events: {
-      "click #delete-database": "delete_database"
-    },
-
     serialize: function () {
       return {
         // TODO make this not hard coded here
@@ -64,21 +60,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         this.$('.active').removeClass('active');
         this.$('#'+this.active_id).addClass('active');
       }
-    },
-
-    delete_database: function (event) {
-      event.preventDefault();
-
-      var result = confirm("Are you sure you want to delete this database?");
-
-      if (!result) { return; }
-      FauxtonAPI.addNotification({
-        msg: "Deleting your database...",
-        type: "error"
-      });
-      return this.database.destroy().done(function () {
-        app.router.navigate('#/_all_dbs', {trigger: true});
-      });
     }
   });
 
@@ -1778,7 +1759,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.database.destroy().then(function () {
         FauxtonAPI.navigate('#/_all_dbs');
         FauxtonAPI.addNotification({
-          msg: 'The database ' + databaseName + ' has been deleted.',
+          msg: 'The database <code>' + databaseName + '</code> has been deleted.',
           clear: true
         });
       }).fail(function (rsp, error, msg) {


[50/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix Beautify button css


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/3c173142
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/3c173142
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/3c173142

Branch: refs/heads/import-master
Commit: 3c17314247a3359a20ddacbeb2b9b0904a47d3c9
Parents: a668f21
Author: suelockwood <de...@apache.org>
Authored: Fri Feb 7 14:46:43 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Fri Feb 7 14:47:05 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/templates/view_editor.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/3c173142/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
index be60090..b4addad 100644
--- a/app/addons/documents/templates/view_editor.html
+++ b/app/addons/documents/templates/view_editor.html
@@ -44,7 +44,7 @@ the License.
             <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
             <% } else { %>
             <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
-            <button class="beautify beautify_map button hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+            <button class="beautify beautify_map btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 
@@ -67,7 +67,7 @@ the License.
             <div class="js-editor" id="reduce-function"><%= langTemplates.reduce %></div>
             <% } else { %>
             <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
-            <button class="beautify beautify_reduce button hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+            <button class="beautify beautify_reduce btn btn-primary btn-large hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 


[35/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Whitespace


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/ab1b2c1e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/ab1b2c1e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/ab1b2c1e

Branch: refs/heads/import-master
Commit: ab1b2c1e3d3ed5a467b5bfac0d0d8b7b68ce2077
Parents: 61e3478
Author: Simon Metson <si...@cloudant.com>
Authored: Sun Jan 26 19:05:22 2014 +0000
Committer: suelockwood <de...@apache.org>
Committed: Wed Jan 29 10:34:28 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js | 52 +++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ab1b2c1e/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index aeb5983..93fd0d4 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -136,7 +136,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     template: "addons/documents/templates/upload_modal",
 
     disableLoader: true,
-    
+
     initialize: function (options) {
       _.bindAll(this);
     },
@@ -201,7 +201,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.$('.progress').addClass('hide');
       this.clear_error_msg();
       this.$('.modal').modal();
-      // hack to get modal visible 
+      // hack to get modal visible
       $('.modal-backdrop').css('z-index',1025);
     },
 
@@ -257,7 +257,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.$('.progress').addClass('hide');
       this.clear_error_msg();
       this.$('.modal').modal();
-      // hack to get modal visible 
+      // hack to get modal visible
       $('.modal-backdrop').css('z-index',1025);
     },
 
@@ -400,8 +400,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     },
 
     destroy: function (event) {
-      event.preventDefault(); 
-      
+      event.preventDefault();
+
       window.alert('Cannot delete a document generated from a view.');
     },
 
@@ -453,7 +453,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.newView = options.newView || false;
       this.showNumbers = options.showNumbers;
       this.pagination = options.pagination;
-      
+
       this.listenTo(this.collection, 'totalRows:decrement', this.render);
     },
 
@@ -667,7 +667,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
           });
 
           model.collection.remove(model.id);
-          if (!!model.id.match('_design')) { 
+          if (!!model.id.match('_design')) {
             FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
           }
           that.$('.bulk-delete').addClass('disabled');
@@ -712,13 +712,13 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
           return true;
         },
-        
+
         nextUrlfn: function () {
           return collection.urlNextPage(perPage());
         }
       });
     },
-    
+
     cleanup: function () {
       this.allDocsNumber.remove();
       _.each(this.rows, function (row) {row.remove();});
@@ -869,12 +869,12 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         }
         deferred.reject();
      });
-      
+
       return deferred;
     },
 
     saveDoc: function(event) {
-      var json, notification, 
+      var json, notification,
       that = this,
       editor = this.editor,
       validDoc = this.getDocFromEditor();
@@ -1357,7 +1357,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       ddoc.removeDdocView(viewName);
 
       if (ddoc.hasViews()) {
-        promise = ddoc.save(); 
+        promise = ddoc.save();
       } else {
         promise = ddoc.destroy();
       }
@@ -1377,7 +1377,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       $('#dashboard-content').scrollTop(0); //scroll up
 
       if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
-        var mapVal = this.mapEditor.getValue(), 
+        var mapVal = this.mapEditor.getValue(),
         reduceVal = this.reduceVal(),
         viewName = this.$('#index-name').val(),
         ddoc = this.getCurrentDesignDoc(),
@@ -1428,7 +1428,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
           if (that.reduceFunStr !== reduceVal) {
             that.reduceFunStr = reduceVal;
-            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce()); 
+            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce());
           }
 
           FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
@@ -1454,15 +1454,15 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
     updateView: function(event, paramInfo) {
        event.preventDefault();
- 
+
        if (this.newView) { return alert('Please save this new view before querying it.'); }
- 
+
        var errorParams = paramInfo.errorParams,
            params = paramInfo.params;
- 
+
        if (_.any(errorParams)) {
          _.map(errorParams, function(param) {
- 
+
            // TODO: Where to add this error?
            // bootstrap wants the error on a control-group div, but we're not using that
            //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
@@ -1479,14 +1479,14 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
            selector: ".advanced-options .errors-container",
            clear: true
          });
- 
+
          return false;
       }
- 
+
        var fragment = window.location.hash.replace(/\?.*$/, '');
        fragment = fragment + '?' + $.param(params);
        FauxtonAPI.navigate(fragment, {trigger: false});
- 
+
        FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
     },
 
@@ -1537,7 +1537,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     getCurrentDesignDoc: function () {
       return this.designDocSelector.getCurrentDesignDoc();
     },
-    
+
     isCustomReduceEnabled: function() {
       return $("#reduce-function-selector").val() == "CUSTOM";
     },
@@ -1570,7 +1570,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         var editor = this[editorName];
         if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
           return true;
-        } 
+        }
         return editor.hadValidCode();
       }, this);
     },
@@ -1657,7 +1657,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         ddocName: this.model.id,
         database: this.database
       }));
-      
+
       this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
         updateViewFn: this.updateView,
         previewFn: this.previewView,
@@ -1703,7 +1703,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
         //Use a built in view by default
         //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
-      } 
+      }
 
       this.mapEditor.editSaved();
       this.reduceEditor && this.reduceEditor.editSaved();
@@ -1800,7 +1800,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         permissions_url: '#' + this.database.url('app') + '/permissions',
         db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
         database: this.collection.database,
-        database_url: '#' + this.database.url('app'), 
+        database_url: '#' + this.database.url('app'),
         docLinks: docLinks,
         docLimit: Databases.DocLimit,
         addLinks: addLinks,


[39/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: update dataSize


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/b526f00e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b526f00e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b526f00e

Branch: refs/heads/import-master
Commit: b526f00ed2d87783596ed7c1605234b7f5dfa635
Parents: 895cf6d
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Jan 29 18:28:44 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Jan 29 18:29:03 2014 +0200

----------------------------------------------------------------------
 app/addons/databases/resources.js | 11 ++++++-----
 app/addons/databases/views.js     |  1 +
 2 files changed, 7 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b526f00e/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index 3510154..1b55f88 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -151,16 +151,17 @@ function(app, FauxtonAPI, Documents) {
 
       return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
     },
-    diskSize: function () {
-      return this.get("disk_size");
-    },
 
     dataSize: function () {
       if (this.get("other")){
         return this.get("other").data_size;
-      }else{
+      } else if (this.get('data_size')) {
+        return this.get('data_size');
+      } else if (this.get('disk_size')) {
+        return this.get('disk_size');
+      } else {
         return 0;
-      }  
+      } 
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b526f00e/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
index df663eb..56001db 100644
--- a/app/addons/databases/views.js
+++ b/app/addons/databases/views.js
@@ -28,6 +28,7 @@ function(app, Components, FauxtonAPI, Databases) {
       return [this.model.fetch()];
     },
     serialize: function() {
+      console.log('db', this.model);
       return {
         encoded: app.utils.safeURLName(this.model.get("name")),
         database: this.model,


[02/52] [abbrv] Fauxton: move modules to addons

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/modules/documents/routes.js b/app/modules/documents/routes.js
deleted file mode 100644
index 435ed5e..0000000
--- a/app/modules/documents/routes.js
+++ /dev/null
@@ -1,409 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       "api",
-
-       // Modules
-       "modules/documents/views",
-       "modules/databases/base"
-],
-
-function(app, FauxtonAPI, Documents, Databases) {
-
-  var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({
-    layout: "one_pane",
-    disableLoader: true,
-    selectedHeader: "Databases",
-    initialize: function(route, masterLayout, options) {
-      var databaseName = options[0];
-      this.docID = options[1]||'new';
-
-      this.database = this.database || new Databases.Model({id: databaseName});
-      this.doc = new Documents.Doc({
-        _id: this.docID
-      }, {
-        database: this.database
-      });
-
-      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
-        disableLoader: true,
-        selected: "code_editor",
-        model: this.doc
-      }));
-
-    },
-
-    routes: {
-      // We are hiding the field_editor for this first release
-      // "database/:database/:doc/field_editor": "field_editor",
-      "database/:database/:doc/code_editor": "code_editor",
-      "database/:database/:doc": "code_editor"
-    },
-
-    events: {
-      "route:reRenderDoc": "reRenderDoc",
-      "route:duplicateDoc": "duplicateDoc"
-    },
-
-    crumbs: function() {
-      return [
-        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
-        {"name": this.docID, "link": "#"}
-      ];
-    },
-
-    code_editor: function (database, doc) {
-      this.tabsView.updateSelected('code_editor');
-
-      this.docView = this.setView("#dashboard-content", new Documents.Views.Doc({
-        model: this.doc,
-        database: this.database
-      }));
-    },
-
-    reRenderDoc: function () {
-      this.docView.forceRender();
-    },
-
-    field_editor: function(events) {
-      this.tabsView.updateSelected('field_editor');
-      this.docView = this.setView("#dashboard-content", new Documents.Views.DocFieldEditor({
-        model: this.doc
-      }));
-    },
-
-    duplicateDoc: function (newId) {
-      var doc = this.doc,
-      docView = this.docView,
-      database = this.database;
-
-      doc.copy(newId).then(function () {
-        doc.set({_id: newId}); 
-        docView.forceRender();
-        FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.mixins.safeURLName(newId), {trigger: true});
-        FauxtonAPI.addNotification({
-          msg: "Document has been duplicated."
-        });
-
-      }, function (error) {
-        var errorMsg = "Could not duplicate document, reason: " + error.responseText + ".";
-        FauxtonAPI.addNotification({
-          msg: errorMsg,
-          type: "error"
-        });
-      });
-    },
-
-    apiUrl: function() {
-      return [this.doc.url("apiurl"), this.doc.documentation()];
-    }
-  });
-
-  var NewDocEditorRouteObject = DocEditorRouteObject.extend({
-    initialize: function (route, masterLayout, options) {
-      var databaseName = options[0];
-
-      this.database = this.database || new Databases.Model({id: databaseName});
-      this.doc = new Documents.NewDoc(null,{
-        database: this.database
-      });
-
-      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
-        selected: "code_editor",
-        model: this.doc
-      }));
-
-    },
-    crumbs: function() {
-      return [
-        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
-        {"name": "New", "link": "#"}
-      ];
-    },
-    routes: {
-      "database/:database/new": "code_editor"
-    },
-    selectedHeader: "Databases",
-
-  });
-
-  var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({
-    layout: "with_tabs_sidebar",
-    selectedHeader: "Databases",
-    routes: {
-      "database/:database/_all_docs(:extra)": "allDocs", 
-      "database/:database/_design/:ddoc/_view/:view": {
-        route: "viewFn",
-        roles: ['_admin']
-      },
-      "database/:database/new_view": "newViewEditor"
-    },
-
-    events: {
-      "route:updateAllDocs": "updateAllDocsFromView",
-      "route:updatePreviewDocs": "updateAllDocsFromPreview",
-      "route:reloadDesignDocs": "reloadDesignDocs",
-      "route:paginate": "paginate"
-    },
-
-    initialize: function (route, masterLayout, options) {
-      var docOptions = app.getParams();
-      docOptions.include_docs = true;
-
-      this.databaseName = options[0];
-
-      this.data = {
-        database: new Databases.Model({id:this.databaseName})
-      };
-
-      this.data.designDocs = new Documents.AllDocs(null, {
-        database: this.data.database,
-        params: {startkey: '"_design"',
-          endkey: '"_design1"',
-          include_docs: true}
-      });
-
-      this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar({
-        collection: this.data.designDocs,
-        database: this.data.database
-      }));
-    },
-
-    establish: function () {
-      return this.data.designDocs.fetch();
-    },
-
-    allDocs: function(databaseName, options) {
-      var docOptions = app.getParams(options);
-
-      this.data.database.buildAllDocs(docOptions);
-
-      if (docOptions.startkey && docOptions.startkey.indexOf('_design') > -1) {
-        this.sidebar.setSelectedTab('design-docs');
-      } else {
-        this.sidebar.setSelectedTab('all-docs');
-      }
-
-      if (this.viewEditor) { this.viewEditor.remove(); }
-
-      this.toolsView = this.setView("#dashboard-upper-menu", new Documents.Views.JumpToDoc({
-        database: this.data.database,
-        collection: this.data.database.allDocs
-      }));
-
-      this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({
-        database: this.data.database,
-        collection: this.data.database.allDocs,
-        params: docOptions
-      }));
-
-      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-        collection: this.data.database.allDocs
-      }));
-
-      this.crumbs = [
-        {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}
-      ];
-
-      this.apiUrl = [this.data.database.allDocs.url("apiurl"), this.data.database.allDocs.documentation() ];
-    },
-
-    viewFn: function (databaseName, ddoc, view) {
-      var params = app.getParams(),
-          decodeDdoc = decodeURIComponent(ddoc);
-
-      view = view.replace(/\?.*$/,'');
-
-      this.data.indexedDocs = new Documents.IndexCollection(null, {
-        database: this.data.database,
-        design: decodeDdoc,
-        view: view,
-        params: params
-      });
-
-      var ddocInfo = {
-        id: "_design/" + decodeDdoc,
-        currView: view,
-        designDocs: this.data.designDocs
-      };
-
-      this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.ViewEditor({
-        model: this.data.database,
-        ddocs: this.data.designDocs,
-        viewName: view,
-        params: params,
-        newView: false,
-        database: this.data.database,
-        ddocInfo: ddocInfo
-      }));
-
-      if (this.toolsView) { this.toolsView.remove(); }
-
-      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-        database: this.data.database,
-        collection: this.data.indexedDocs,
-        nestedView: Documents.Views.Row,
-        viewList: true,
-        ddocInfo: ddocInfo
-      }));
-
-      this.sidebar.setSelectedTab(app.mixins.removeSpecialCharacters(ddoc) + '_' + app.mixins.removeSpecialCharacters(view));
-
-      this.crumbs = function () {
-        return [
-          {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
-        ];
-      };
-
-      this.apiUrl = [this.data.indexedDocs.url("apiurl"), "docs"];
-    },
-
-    newViewEditor: function () {
-      var params = app.getParams();
-
-      if (this.toolsView) {
-        this.toolsView.remove();
-      }
-
-      this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.ViewEditor({
-        ddocs: this.data.designDocs,
-        params: params,
-        database: this.data.database,
-        newView: true
-      }));
-
-      this.sidebar.setSelectedTab('new-view');
-      this.crumbs = function () {
-        return [
-          {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
-        ];
-      };
-    },
-
-    updateAllDocsFromView: function (event) {
-      var view = event.view,
-          docOptions = app.getParams(),
-          ddoc = event.ddoc;
-
-      this.documentsView && this.documentsView.remove();
-
-      if (event.allDocs) {
-        this.data.database.buildAllDocs(docOptions);
-        this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-          collection: this.data.database.allDocs
-        }));
-        return;
-      }
-
-      this.data.indexedDocs = new Documents.IndexCollection(null, {
-        database: this.data.database,
-        design: ddoc,
-        view: view,
-        params: app.getParams()
-      });
-
-      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-        database: this.data.database,
-        collection: this.data.indexedDocs,
-        nestedView: Documents.Views.Row,
-        viewList: true
-      }));
-    },
-
-    updateAllDocsFromPreview: function (event) {
-      var view = event.view,
-      rows = event.rows,
-      ddoc = event.ddoc;
-
-      this.data.indexedDocs = new Documents.PouchIndexCollection(null, {
-        database: this.data.database,
-        design: ddoc,
-        view: view,
-        rows: rows
-      });
-
-      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
-        database: this.data.database,
-        collection: this.data.indexedDocs,
-        nestedView: Documents.Views.Row,
-        viewList: true
-      }));
-    },
-
-    paginate: function (direction) {
-      _.extend(this.documentsView.collection.params, app.getParams());
-      this.documentsView.forceRender();
-      if (direction === 'next') {
-        this.documentsView.collection.skipFirstItem = true;
-      } else {
-        this.documentsView.collection.skipFirstItem = false;
-      }
-    },
-
-    reloadDesignDocs: function (event) {
-      this.sidebar.forceRender();
-
-      if (event && event.selectedTab) {
-        this.sidebar.setSelectedTab(event.selectedTab);
-      }
-    }
-
-  });
-
-  var ChangesRouteObject = FauxtonAPI.RouteObject.extend({
-    layout: "with_tabs",
-    selectedHeader: "Databases",
-    crumbs: function () {
-      return [
-        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
-        {"name": "_changes", "link": "/_changes"}
-      ];
-    },
-
-    routes: {
-      "database/:database/_changes(:params)": "changes"
-    },
-
-    initialize: function (route, masterLayout, options) {
-      this.databaseName = options[0];
-      this.database = new Databases.Model({id: this.databaseName});
-
-      var docOptions = app.getParams();
-
-      this.database.buildChanges(docOptions);
-
-      this.setView("#tabs", new Documents.Views.Tabs({
-        collection: this.designDocs,
-        database: this.database,
-        active_id: 'changes'
-      }));
-    },
-
-    changes: function (event) {
-      this.setView("#dashboard-content", new Documents.Views.Changes({
-        model: this.database
-      }));
-    },
-
-    apiUrl: function() {
-      return [this.database.url("apiurl"), this.database.documentation()];
-    }
-
-  });
-
-  Documents.RouteObjects = [DocEditorRouteObject, NewDocEditorRouteObject, DocumentsRouteObject, ChangesRouteObject];
-
-  return Documents;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/documents/tests/resourcesSpec.js
----------------------------------------------------------------------
diff --git a/app/modules/documents/tests/resourcesSpec.js b/app/modules/documents/tests/resourcesSpec.js
deleted file mode 100644
index e848221..0000000
--- a/app/modules/documents/tests/resourcesSpec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-define([
-       'modules/documents/resources',
-      'testUtils'
-], function (Models, testUtils) {
-  var assert = testUtils.assert;
-
-  describe('IndexCollection', function () {
-    var collection;
-    beforeEach(function () {
-      collection = new Models.IndexCollection([{
-        id:'myId1',
-        doc: 'num1'
-      },
-      {
-        id:'myId2',
-        doc: 'num2'
-      }], {
-        database: {id: 'databaseId', safeID: function () { return this.id; }},
-        design: '_design/myDoc'
-      });
-
-    });
-
-    it('Should return urlNext', function () {
-      var url = collection.urlNextPage(20);
-
-      assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=21&reduce=false&startkey_docid=myId2&startkey=');
-
-    });
-
-    it('Should return urlPrevious', function () {
-      var url = collection.urlPreviousPage(20, {limit: 21, reduce: false,  startkey_docid: "myId1",startkey:"myId1"} );
-
-      assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=20&reduce=false&startkey_docid=myId1&startkey=myId1');
-
-    });
-
-  });
-
-  describe('AllDocs', function () {
-    var collection;
-    beforeEach(function () {
-      collection = new Models.AllDocs([{
-        _id:'myId1',
-        doc: 'num1'
-      },
-      {
-        _id:'myId2',
-        doc: 'num2'
-      }], {
-        database: {id: 'databaseId', safeID: function () { return this.id; }},
-        params: {limit: 20}
-      });
-
-    });
-
-    it('Should return urlNext', function () {
-      var url = collection.urlNextPage(20);
-
-      assert.equal(url, 'database/databaseId/_all_docs?limit=21&startkey_docid=%22myId2%22&startkey=%22myId2%22');
-
-    });
-
-     it('Should return urlPrevious', function () {
-      var url = collection.urlPreviousPage(20, {limit: 21, startkey_docid: "myId1",startkey:"myId1"} );
-      assert.equal(url, 'database/databaseId/_all_docs?limit=20&startkey_docid=myId1&startkey=myId1');
-    });
-
-
-  });
-
-});
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/documents/views.js
----------------------------------------------------------------------
diff --git a/app/modules/documents/views.js b/app/modules/documents/views.js
deleted file mode 100644
index 59aba01..0000000
--- a/app/modules/documents/views.js
+++ /dev/null
@@ -1,1855 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       "api",
-       "modules/fauxton/components",
-
-       "modules/documents/resources",
-       "modules/databases/resources",
-       "modules/pouchdb/base",
-
-       // Libs
-       "resizeColumns",
-
-       // Plugins
-       "plugins/prettify"
-
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns) {
-  var Views = {};
-  Views.Tabs = FauxtonAPI.View.extend({
-    template: "templates/documents/tabs",
-    initialize: function(options){
-      this.collection = options.collection;
-      this.database = options.database;
-      this.active_id = options.active_id;
-    },
-
-    events: {
-      "click #delete-database": "delete_database"
-    },
-
-    serialize: function () {
-      return {
-        // TODO make this not hard coded here
-        changes_url: '#' + this.database.url('changes'),
-        db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
-      };
-    },
-
-    beforeRender: function(manage) {
-      this.insertView("#search", new Views.SearchBox({
-        collection: this.collection,
-        database: this.database.id
-      }));
-    },
-
-    afterRender: function () {
-      if (this.active_id) {
-        this.$('.active').removeClass('active');
-        this.$('#'+this.active_id).addClass('active');
-      }
-    },
-
-    delete_database: function (event) {
-      event.preventDefault();
-
-      var result = confirm("Are you sure you want to delete this database?");
-
-      if (!result) { return; }
-      FauxtonAPI.addNotification({
-        msg: "Deleting your database...",
-        type: "error"
-      });
-      return this.database.destroy().done(function () {
-        app.router.navigate('#/_all_dbs', {trigger: true});
-      });
-    }
-  });
-
-  Views.SearchBox = FauxtonAPI.View.extend({
-    template: "templates/documents/search",
-    tagName: "form",
-    initialize: function(options){
-      this.collection = options.collection;
-      this.database = options.database;
-    },
-    afterRender: function(){
-      var collection = this.collection;
-      var form = this.$el;
-      var searchbox = form.find("input#searchbox");
-      var database = this.database;
-
-      form.submit(function(evt){
-        evt.preventDefault();
-        var viewname = form.find("input#view").val().split('/');
-        var url = "#database/" + database + "/_design/";
-        url += viewname[0] + "/_view/" + viewname[1];
-        if (searchbox.val() !== ""){
-          // TODO: this'll need to work when val() is a number etc.
-          url += '?startkey="' + searchbox.val() + '"';
-        }
-        FauxtonAPI.navigate(url);
-      });
-
-      searchbox.typeahead({
-        source: function(query, process) {
-          // TODO: include _all_docs and view keys somehow
-          var views = _.map(collection.pluck('doc'), function(d){
-            return _.map(_.keys(d.views), function(view){
-              return d._id.split('/')[1] + "/" + view;
-            });
-          });
-          return _.flatten(views);
-        },
-        minLength: 3,
-        updater: function(item){
-          // TODO: some way to return the original search box
-          this.$element.removeClass('span12');
-          this.$element.addClass('span6');
-          this.$element.attr('placeholder', 'Search by view key');
-          $('<span class="add-on span6">' + item +'</span>').insertBefore(this.$element);
-          $('<input type="hidden" id="view" value="' + item +'"/>').insertBefore(this.$element);
-          // Remove the type ahead for now
-          $('.typehead').unbind();
-        }
-      });
-    }
-  });
-
-  Views.UploadModal = FauxtonAPI.View.extend({
-    template: "templates/documents/upload_modal",
-
-    disableLoader: true,
-    
-    initialize: function (options) {
-      _.bindAll(this);
-    },
-
-    events: {
-      "click a#upload-btn": "uploadFile"
-    },
-
-    uploadFile: function (event) {
-      event.preventDefault();
-
-      var docRev = this.model.get('_rev'),
-          that = this,
-          $form = this.$('#file-upload');
-
-      if (!docRev) {
-        return this.set_error_msg('The document needs to be saved before adding an attachment.');
-      }
-
-      if ($('input[type="file"]')[0].files.length === 0) {
-        return this.set_error_msg('Selected a file to be uploaded.');
-      }
-
-      this.$('#_rev').val(docRev);
-
-      $form.ajaxSubmit({
-        url: this.model.url(),
-        type: 'POST',
-        beforeSend: this.beforeSend,
-        uploadProgress: this.uploadProgress,
-        success: this.success,
-        error: function (resp) {
-          console.log('ERR on upload', resp);
-          return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
-        }
-      });
-    },
-
-    success: function (resp) {
-      var hideModal = this.hideModal,
-          $form = this.$('#file-upload');
-
-      FauxtonAPI.triggerRouteEvent('reRenderDoc');
-      //slight delay to make this transistion a little more fluid and less jumpy
-      setTimeout(function () {
-        $form.clearForm();
-        hideModal();
-        $('.modal-backdrop').remove();
-      }, 1000);
-    },
-
-    uploadProgress: function(event, position, total, percentComplete) {
-      this.$('.bar').css({width: percentComplete + '%'});
-    },
-
-    beforeSend: function () {
-      this.$('.progress').removeClass('hide');
-    },
-
-    showModal: function () {
-      this.$('.bar').css({width: '0%'});
-      this.$('.progress').addClass('hide');
-      this.clear_error_msg();
-      this.$('.modal').modal();
-      // hack to get modal visible 
-      $('.modal-backdrop').css('z-index',1025);
-    },
-
-    hideModal: function () {
-      this.$('.modal').modal('hide');
-    },
-
-    set_error_msg: function (msg) {
-      var text;
-      if (typeof(msg) == 'string') {
-        text = msg;
-      } else {
-        text = JSON.parse(msg.responseText).reason;
-      }
-      this.$('#modal-error').text(text).removeClass('hide');
-    },
-
-    clear_error_msg: function () {
-      this.$('#modal-error').text(' ').addClass('hide');
-    },
-
-    serialize: function () {
-      return this.model.toJSON();
-    }
-  });
-
-  Views.DuplicateDocModal = FauxtonAPI.View.extend({
-    template: "templates/documents/duplicate_doc_modal",
-
-    initialize: function () {
-      _.bindAll(this);
-    },
-
-    events: {
-      "click #duplicate-btn":"duplicate"
-
-    },
-
-    duplicate: function (event) {
-      event.preventDefault();
-      var newId = this.$('#dup-id').val(),
-          encodedID = app.mixins.safeURLName(newId);
-
-      this.hideModal();
-      FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
-    },
-
-    _showModal: function () {
-      this.$('.bar').css({width: '0%'});
-      this.$('.progress').addClass('hide');
-      this.clear_error_msg();
-      this.$('.modal').modal();
-      // hack to get modal visible 
-      $('.modal-backdrop').css('z-index',1025);
-    },
-
-    showModal: function () {
-      var showModal = this._showModal,
-          setDefaultIdValue = this.setDefaultIdValue,
-          uuid = new FauxtonAPI.UUID();
-
-      uuid.fetch().then(function () {
-        setDefaultIdValue(uuid.next());
-        showModal();
-      });
-    },
-
-    setDefaultIdValue: function (id) {
-      this.$('#dup-id').val(id);
-    },
-
-    hideModal: function () {
-      this.$('.modal').modal('hide');
-    },
-
-    set_error_msg: function (msg) {
-      var text;
-      if (typeof(msg) == 'string') {
-        text = msg;
-      } else {
-        text = JSON.parse(msg.responseText).reason;
-      }
-      this.$('#modal-error').text(text).removeClass('hide');
-    },
-
-    clear_error_msg: function () {
-      this.$('#modal-error').text(' ').addClass('hide');
-    },
-
-    serialize: function () {
-      return this.model.toJSON();
-    }
-
-  });
-
-  Views.FieldEditorTabs = FauxtonAPI.View.extend({
-    template: "templates/documents/doc_field_editor_tabs",
-    disableLoader: true,
-    initialize: function(options) {
-      this.selected = options.selected;
-    },
-
-    events: {
-    },
-    updateSelected: function (selected) {
-      this.selected = selected;
-      this.$('.active').removeClass('active');
-      this.$('#'+this.selected).addClass('active');
-    },
-
-    serialize: function() {
-      var selected = this.selected;
-      return {
-        doc: this.model,
-        isNewDoc: this.model.isNewDoc(),
-        isSelectedClass: function(item) {
-          return item && item === selected ? "active" : "";
-        }
-      };
-    },
-
-    establish: function() {
-      return [this.model.fetch()];
-    }
-  });
-
-  Views.Document = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_item",
-    tagName: "tr",
-    className: "all-docs-item",
-
-    events: {
-      "click button.delete": "destroy",
-      "dblclick pre.prettyprint": "edit"
-    },
-
-    attributes: function() {
-      return {
-        "data-id": this.model.id
-      };
-    },
-
-    serialize: function() {
-      return {
-        doc: this.model
-      };
-    },
-
-    establish: function() {
-      return [this.model.fetch()];
-    },
-
-    edit: function(event) {
-      event.preventDefault();
-      FauxtonAPI.navigate("#" + this.model.url('app'));
-    },
-
-    destroy: function(event) {
-      event.preventDefault();
-      var that = this;
-
-      if (!window.confirm("Are you sure you want to delete this doc?")) {
-        return false;
-      }
-
-      this.model.destroy().then(function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Succesfully destroyed your doc"
-        });
-        that.$el.fadeOut(function () {
-          that.remove();
-        });
-
-        that.model.collection.remove(that.model.id);
-        if (!!that.model.id.match('_design')) {
-          FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
-        }
-      }, function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Failed to destroy your doc!",
-          type: "error"
-        });
-      });
-    }
-  });
-
-  Views.Row = FauxtonAPI.View.extend({
-    template: "templates/documents/index_row_docular",
-    tagName: "tr",
-
-    events: {
-      "click button.delete": "destroy"
-    },
-
-    destroy: function (event) {
-      event.preventDefault(); 
-      
-      window.alert('Cannot delete a document generated from a view.');
-    },
-
-    serialize: function() {
-      return {
-        doc: this.model
-      };
-    }
-  });
-
-  Views.IndexItem = FauxtonAPI.View.extend({
-    template: "templates/documents/index_menu_item",
-    tagName: "li",
-
-    initialize: function(options){
-      this.index = options.index;
-      this.ddoc = options.ddoc;
-      this.database = options.database;
-      this.selected = !! options.selected;
-    },
-
-    serialize: function() {
-      return {
-        index: this.index,
-        ddoc: this.ddoc,
-        database: this.database,
-        index_clean: app.mixins.removeSpecialCharacters(this.index),
-        ddoc_clean: app.mixins.removeSpecialCharacters(this.ddoc), 
-        index_encoded: app.mixins.safeURLName(this.index),
-        ddoc_encoded: app.mixins.safeURLName(this.ddoc),
-        database_encoded: app.mixins.safeURLName(this.database),
-        selected: this.selected
-      };
-    },
-
-    afterRender: function() {
-      if (this.selected) {
-        $("#sidenav ul.nav-list li").removeClass("active");
-        this.$el.addClass("active");
-      }
-    }
-  });
-
-  Views.AllDocsNumber = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_number",
-
-    initialize: function (options) {
-      this.newView = options.newView || false;
-      this.showNumbers = options.showNumbers;
-      this.pagination = options.pagination;
-      
-      this.listenTo(this.collection, 'totalRows:decrement', this.render);
-    },
-
-    serialize: function () {
-       var totalRows = 0,
-          recordStart = 0,
-          updateSeq = false,
-          pageStart = 0,
-          pageEnd = 20;
-
-      if (!this.newView) {
-        totalRows = this.collection.totalRows();
-        updateSeq = this.collection.updateSeq();
-      }
-
-      recordStart = this.collection.recordStart();
-      if (this.pagination) {
-        pageStart = this.pagination.pageStart();
-        pageEnd =  this.pagination.pageEnd();
-      }
-
-      return {
-        database: app.mixins.safeURLName(this.collection.database.id),
-        updateSeq: updateSeq,
-        offset: recordStart,
-        totalRows: totalRows,
-        showNumbers: this.showNumbers,
-        numModels: this.collection.models.length + recordStart - 1,
-        pageStart: pageStart,
-        pageEnd: pageEnd
-      };
-    }
-
-  });
-
-  Views.AllDocsLayout = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_layout",
-    className: "row",
-
-    initialize: function (options) {
-      this.database = options.database;
-      this.params = options.params;
-    },
-
-    events: {
-      'click #toggle-query': "toggleQuery"
-    },
-
-    toggleQuery: function (event) {
-      $('#dashboard-content').scrollTop(0);
-      this.$('#query').toggle('fast');
-    },
-
-    beforeRender: function () {
-      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
-        updateViewFn: this.updateAllDocs,
-        previewFn: this.previewView,
-        hasReduce: false,
-        showPreview: false,
-        database: this.database
-      }));
-
-      this.$('#query').hide();
-    },
-
-    afterRender: function () {
-      if (this.params) {
-        this.advancedOptions.updateFromParams(this.params);
-      }
-
-    },
-
-    updateAllDocs: function (event, paramInfo) {
-      event.preventDefault();
-
-      var errorParams = paramInfo.errorParams,
-          params = paramInfo.params;
-
-      if (_.any(errorParams)) {
-        _.map(errorParams, function(param) {
-
-          // TODO: Where to add this error?
-          // bootstrap wants the error on a control-group div, but we're not using that
-          //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
-          return FauxtonAPI.addNotification({
-            msg: "JSON Parse Error on field: "+param.name,
-            type: "error",
-            selector: ".advanced-options .errors-container"
-          });
-        });
-        FauxtonAPI.addNotification({
-          msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
-          type: "warning",
-          selector: ".advanced-options .errors-container"
-        });
-
-        return false;
-      }
-
-      var fragment = window.location.hash.replace(/\?.*$/, '');
-      fragment = fragment + '?' + $.param(params);
-      FauxtonAPI.navigate(fragment, {trigger: false});
-
-      FauxtonAPI.triggerRouteEvent('updateAllDocs', {allDocs: true});
-    },
-
-    previewView: function (event) {
-      event.preventDefault();
-    }
-
-  });
-
-  // TODO: Rename to reflect that this is a list of rows or documents
-  Views.AllDocsList = FauxtonAPI.View.extend({
-    template: "templates/documents/all_docs_list",
-    events: {
-      "click button.all": "selectAll",
-      "click button.bulk-delete": "bulkDelete",
-      "click #collapse": "collapse",
-      "change .row-select":"toggleTrash"
-    },
-
-    toggleTrash: function () {
-      if (this.$('.row-select:checked').length > 0) {
-        this.$('.bulk-delete').removeClass('disabled');
-      } else {
-        this.$('.bulk-delete').addClass('disabled');
-      }
-    },
-
-    initialize: function(options){
-      this.nestedView = options.nestedView || Views.Document;
-      this.rows = {};
-      this.viewList = !! options.viewList;
-      this.database = options.database;
-      if (options.ddocInfo) {
-        this.designDocs = options.ddocInfo.designDocs;
-        this.ddocID = options.ddocInfo.id;
-      }
-      this.newView = options.newView || false;
-      this.expandDocs = true;
-    },
-
-    establish: function() {
-      if (this.newView) { return null; }
-
-      return this.collection.fetch({reset: true}).fail(function() {
-        // TODO: handle error requests that slip through
-        // This should just throw a notification, not break the page
-        console.log("ERROR: ", arguments);
-      });
-    },
-
-    selectAll: function(evt){
-      $('.all-docs').find("input:checkbox").prop('checked', !$(evt.target).hasClass('active')).trigger('change');
-    },
-
-    serialize: function() {
-      var requestDuration = false;
-
-      if (this.collection.requestDurationInString) {
-        requestDuration = this.collection.requestDurationInString();
-      }
-
-      return {
-        viewList: this.viewList,
-        requestDuration: requestDuration,
-        expandDocs: this.expandDocs
-      };
-    },
-
-    collapse: function (event) {
-      event.preventDefault();
-
-      if (this.expandDocs) {
-        this.expandDocs = false;
-      } else {
-        this.expandDocs = true;
-      }
-
-      this.render();
-    },
-
-    /*
-     * TODO: this should be reconsidered
-     * This currently performs delete operations on the model level,
-     * when we could be using bulk docs with _deleted = true. Using
-     * individual models is cleaner from a backbone standpoint, but
-     * not from the couchdb api.
-     * Also, the delete method is naive and leaves the body intact,
-     * when we should switch the doc to only having id/rev/deleted.
-     */
-    bulkDelete: function() {
-      var that = this;
-      // yuck, data binding ftw?
-      var eles = this.$el.find("input.row-select:checked")
-                         .parents("tr.all-docs-item")
-                         .map(function(e) { return $(this).attr("data-id"); })
-                         .get();
-
-      if (eles.length === 0 || !window.confirm("Are you sure you want to delete these " + eles.length + " docs?")) {
-        return false;
-      }
-
-      _.each(eles, function(ele) {
-        var model = this.collection.get(ele);
-
-        model.destroy().then(function(resp) {
-          that.rows[ele].$el.fadeOut(function () {
-            $(this).remove();
-          });
-
-          model.collection.remove(model.id);
-          if (!!model.id.match('_design')) { 
-            FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
-          }
-          that.$('.bulk-delete').addClass('disabled');
-        }, function(resp) {
-          FauxtonAPI.addNotification({
-            msg: "Failed to destroy your doc!",
-            type: "error"
-          });
-        });
-      }, this);
-    },
-
-    addPagination: function () {
-      var collection = this.collection;
-      var perPage = function () {
-        if (collection.params.limit && collection.skipFirstItem) {
-          return parseInt(collection.params.limit, 10) - 1;
-        } else if (collection.params.limit) {
-          return parseInt(collection.params.limit, 10);
-        }
-
-        return 20;
-      };
-
-      this.pagination = new Components.IndexPagination({
-        collection: this.collection,
-        scrollToSelector: '#dashboard-content',
-        previousUrlfn: function () {
-          return collection.urlPreviousPage(perPage(), this.previousParams.pop());
-        },
-        canShowPreviousfn: function () {
-          if (this.previousParams.length === 0) {
-            return false;
-          }
-
-          return true;
-        },
-        canShowNextfn: function () {
-          if (collection.length < (perPage() -1)) {
-            return false;
-          }
-
-          return true;
-        },
-        
-        nextUrlfn: function () {
-          return collection.urlNextPage(perPage());
-        }
-      });
-    },
-    
-    cleanup: function () {
-      //if (!this.pagination) { return; }
-      this.pagination.remove();
-      //this.pagination = null;
-      this.allDocsNumber.remove();
-      _.each(this.rows, function (row) {row.remove();});
-    },
-
-    beforeRender: function() {
-      var showNumbers = true;
-
-      if (!this.pagination) {
-        this.addPagination();
-      }
-
-      this.insertView('#documents-pagination', this.pagination);
-
-      if (this.designDocs || this.collection.idxType === '_view' || this.collection.params.startkey === '"_design"') {
-        showNumbers = false;
-      }
-
-      this.allDocsNumber = this.setView('#item-numbers', new Views.AllDocsNumber({
-        collection: this.collection,
-        newView: this.newView,
-        showNumbers: showNumbers,
-        pagination: this.pagination
-      }));
-
-      var docs = this.expandDocs ? this.collection : this.collection.simple();
-
-      docs.each(function(doc) {
-        this.rows[doc.id] = this.insertView("table.all-docs tbody", new this.nestedView({
-          model: doc
-        }));
-      }, this);
-    },
-
-    afterRender: function(){
-      prettyPrint();
-    }
-  });
-
-  Views.Doc = FauxtonAPI.View.extend({
-    template: "templates/documents/doc",
-    events: {
-      "click button.save-doc": "saveDoc",
-      "click button.delete": "destroy",
-      "click button.duplicate": "duplicate",
-      "click button.upload": "upload",
-      "click button.cancel-button": "goback"
-    },
-    disableLoader: true,
-    initialize: function (options) {
-      this.database = options.database;
-      _.bindAll(this);
-    },
-    goback: function(){
-      FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
-    },
-    destroy: function(event) {
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'This document has not been saved yet.',
-          type: 'warning'
-        });
-        return;
-      }
-
-      if (!window.confirm("Are you sure you want to delete this doc?")) {
-        return false;
-      }
-
-      var database = this.model.database;
-
-      this.model.destroy().then(function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Succesfully destroyed your doc"
-        });
-        FauxtonAPI.navigate(database.url("index"));
-      }, function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Failed to destroy your doc!",
-          type: "error"
-        });
-      });
-    },
-
-    beforeRender: function () {
-      this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model}));
-      this.uploadModal.render();
-
-      this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model}));
-      this.duplicateModal.render();
-    },
-
-    upload: function (event) {
-      event.preventDefault();
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'Please save the document before uploading an attachment.',
-          type: 'warning'
-        });
-        return;
-      }
-      this.uploadModal.showModal();
-    },
-
-    duplicate: function(event) {
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'Please save the document before duplicating it.',
-          type: 'warning'
-        });
-        return;
-      }
-      event.preventDefault();
-      this.duplicateModal.showModal();
-    },
-
-    updateValues: function() {
-      var notification;
-      if (this.model.changedAttributes()) {
-        notification = FauxtonAPI.addNotification({
-          msg: "Document saved successfully.",
-          type: "success",
-          clear: true
-        });
-        this.editor.setValue(this.model.prettyJSON());
-      }
-    },
-
-    establish: function() {
-      var promise = this.model.fetch(),
-          databaseId = this.database.safeID(),
-          deferred = $.Deferred(),
-          that = this;
-
-      promise.then(function () {
-        deferred.resolve();
-      }, function (xhr, reason, msg) {
-        if (xhr.status === 404) {
-          FauxtonAPI.addNotification({
-            msg: 'The document does not exist',
-            type: 'error',
-            clear: true
-          });
-          that.goback();
-        }
-        deferred.reject();
-     });
-      
-      return deferred;
-    },
-
-    saveDoc: function(event) {
-      var json, notification, 
-      that = this,
-      editor = this.editor,
-      validDoc = this.getDocFromEditor();
-
-      if (validDoc) {
-        this.getDocFromEditor();
-
-        notification = FauxtonAPI.addNotification({msg: "Saving document."});
-
-        this.model.save().then(function () {
-          editor.editSaved();
-          FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
-        }).fail(function(xhr) {
-
-          var responseText = JSON.parse(xhr.responseText).reason;
-          notification = FauxtonAPI.addNotification({
-            msg: "Save failed: " + responseText,
-            type: "error",
-            clear: true,
-            selector: "#doc .errors-container"
-          });
-        });
-      } else if(this.model.validationError && this.model.validationError === 'Cannot change a documents id.') {
-          notification = FauxtonAPI.addNotification({
-            msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
-            type: "error",
-            selector: "#doc .errors-container"
-          });
-        delete this.model.validationError;
-      } else {
-        notification = FauxtonAPI.addNotification({
-          msg: "Please fix the JSON errors and try again.",
-          type: "error",
-          selector: "#doc .errors-container"
-        });
-      }
-    },
-
-    getDocFromEditor: function () {
-      if (!this.hasValidCode()) {
-        return false;
-      }
-
-      json = JSON.parse(this.editor.getValue());
-
-      this.model.clear().set(json, {validate: true});
-      if (this.model.validationError) {
-        return false;
-      }
-
-      return this.model;
-    },
-
-    hasValidCode: function() {
-      var errors = this.editor.getAnnotations();
-      return errors.length === 0;
-    },
-
-    serialize: function() {
-      return {
-        doc: this.model,
-        attachments: this.getAttachments()
-      };
-    },
-
-    getAttachments: function () {
-      var attachments = this.model.get('_attachments');
-
-      if (!attachments) { return false; }
-
-      return _.map(attachments, function (att, key) {
-        return {
-          fileName: key,
-          size: att.length,
-          contentType: att.content_type,
-          url: this.model.url() + '/' + key
-        };
-      }, this);
-    },
-
-    afterRender: function() {
-      var saveDoc = this.saveDoc;
-
-      this.editor = new Components.Editor({
-        editorId: "editor-container",
-        commands: [{
-          name: 'save',
-          bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
-          exec: function(editor) {
-            saveDoc();
-          },
-          readOnly: true // false if this command should not apply in readOnly mode
-        }]
-      });
-      this.editor.render();
-      this.model.on("sync", this.updateValues, this);
-    },
-
-    cleanup: function () {
-      if (this.editor) this.editor.remove();
-    }
-  });
-
-  Views.DocFieldEditor = FauxtonAPI.View.extend({
-    template: "templates/documents/doc_field_editor",
-    disableLoader: true,
-    events: {
-      "click button.save": "saveDoc"
-    },
-
-    saveDoc: function(event) {
-      FauxtonAPI.addNotification({
-        type: "warning",
-        msg: "Save functionality coming soon."
-      });
-    },
-
-    serialize: function() {
-      return {
-        doc: this.getModelWithoutAttachments(),
-        attachments: this.getAttachments()
-      };
-    },
-
-    getModelWithoutAttachments: function() {
-      var model = this.model.toJSON();
-      delete model._attachments;
-      return model;
-    },
-
-    getAttachments: function () {
-      var attachments = this.model.get('_attachments');
-
-      if (!attachments) { return []; }
-
-      return _.map(attachments, function (att, key) {
-        return {
-          fileName: key,
-          size: att.length,
-          contentType: att.content_type,
-          url: this.model.url() + '/' + key
-        };
-      }, this);
-    },
-
-    establish: function() {
-      return [this.model.fetch()];
-    }
-  });
-
-  Views.AdvancedOptions = FauxtonAPI.View.extend({
-    template: "templates/documents/advanced_options",
-    className: "advanced-options well",
-
-    initialize: function (options) {
-      this.database = options.database;
-      this.ddocName = options.ddocName;
-      this.viewName = options.viewName;
-      this.updateViewFn = options.updateViewFn;
-      this.previewFn = options.previewFn;
-      //this.hadReduce = options.hasReduce || true;
-
-      if (typeof(options.hasReduce) === 'undefined') {
-        this.hasReduce = true;
-      } else {
-        this.hasReduce = options.hasReduce;
-      }
-
-      if (typeof(options.showPreview) === 'undefined') {
-        this.showPreview = true;
-      } else {
-        this.showPreview = options.showPreview;
-      }
-    },
-
-    events: {
-      "change form.view-query-update input": "updateFilters",
-      "change form.view-query-update select": "updateFilters",
-      "submit form.view-query-update": "updateView",
-      "click button.preview": "previewView"
-    },
-
-    beforeRender: function () {
-      if (this.viewName && this.ddocName) {
-        var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
-        _.each(buttonViews, function (view) {
-          this.insertView('#button-options', view);
-          view.update(this.database, this.ddocName, this.viewName);
-        }, this);
-      }
-    },
-
-    renderOnUpdatehasReduce: function (hasReduce) {
-      this.hasReduce = hasReduce;
-      this.render();
-    },
-
-    queryParams: function () {
-      var $form = this.$(".view-query-update");
-      // Ignore params without a value
-      var params = _.filter($form.serializeArray(), function(param) {
-        return param.value;
-      });
-
-      // Validate *key* params to ensure they're valid JSON
-      var keyParams = ["key","keys","startkey","endkey"];
-      var errorParams = _.filter(params, function(param) {
-        if (_.contains(keyParams, param.name)) {
-          try {
-            JSON.parse(param.value);
-            return false;
-          } catch(e) {
-            return true;
-          }
-        } else {
-          return false;
-        }
-      });
-
-      return {params: params, errorParams: errorParams};
-    },
-
-    updateFilters: function(event) {
-      event.preventDefault();
-      var $ele = $(event.currentTarget);
-      var name = $ele.attr('name');
-      this.updateFiltersFor(name, $ele);
-    },
-
-    updateFiltersFor: function(name, $ele) {
-      var $form = $ele.parents("form.view-query-update:first");
-      switch (name) {
-        // Reduce constraints
-        //   - Can't include_docs for reduce=true
-        //   - can't include group_level for reduce=false
-        case "reduce":
-          if ($ele.prop('checked') === true) {
-          if ($form.find("input[name=include_docs]").prop("checked") === true) {
-            $form.find("input[name=include_docs]").prop("checked", false);
-            var notification = FauxtonAPI.addNotification({
-              msg: "include_docs has been disabled as you cannot include docs on a reduced view",
-              type: "warn",
-              selector: ".view.show .all-docs-list.errors-container"
-            });
-          }
-          $form.find("input[name=include_docs]").prop("disabled", true);
-          $form.find("select[name=group_level]").prop("disabled", false);
-        } else {
-          $form.find("select[name=group_level]").prop("disabled", true);
-          $form.find("input[name=include_docs]").prop("disabled", false);
-        }
-        break;
-        case "include_docs":
-        break;
-      }
-    },
-
-    updateFromParams: function (params) {
-      var $form = this.$el.find("form.view-query-update");
-      _.each(params, function(val, key) {
-        var $ele;
-        switch (key) {
-          case "limit":
-            case "group_level":
-            $form.find("select[name='"+key+"']").val(val);
-          break;
-          case "include_docs":
-            case "stale":
-            case "descending":
-            case "inclusive_end":
-            $form.find("input[name='"+key+"']").prop('checked', true);
-          break;
-          case "reduce":
-            $ele = $form.find("input[name='"+key+"']");
-          if (val == "true") {
-            $ele.prop('checked', true);
-          }
-          this.updateFiltersFor(key, $ele);
-          break;
-          default:
-            $form.find("input[name='"+key+"']").val(val);
-          break;
-        }
-      }, this);
-    },
-
-    updateView: function (event) {
-      this.updateViewFn(event, this.queryParams());
-    },
-
-    previewView: function (event) {
-      this.previewFn(event, this.queryParams());
-    },
-
-    serialize: function () {
-      return {
-        hasReduce: this.hasReduce,
-        showPreview: this.showPreview
-      };
-    }
-  });
-
-  Views.DesignDocSelector = FauxtonAPI.View.extend({
-    template: "templates/documents/design_doc_selector",
-
-    events: {
-      "change select#ddoc": "updateDesignDoc"
-    },
-
-    initialize: function (options) {
-      this.ddocName = options.ddocName;
-      this.database = options.database;
-      this.listenTo(this.collection, 'add', this.ddocAdded);
-      this.DocModel = options.DocModel || Documents.Doc;
-    },
-
-    ddocAdded: function (ddoc) {
-      this.ddocName = ddoc.id;
-      this.render();
-    },
-
-    serialize: function () {
-      return {
-        ddocName: this.ddocName,
-        ddocs: this.collection
-      };
-    },
-
-    updateDesignDoc: function () {
-      if (this.newDesignDoc()) {
-        this.$('#new-ddoc-section').show();
-      } else {
-        this.$('#new-ddoc-section').hide();
-      }
-    },
-
-    newDesignDoc: function () {
-
-      return this.$('#ddoc').val() === 'new-doc';
-    },
-
-    newDocValidation: function(){
-      return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
-    },
-    getCurrentDesignDoc: function () {
-      if (this.newDesignDoc()) {
-        var doc = {
-          _id: '_design/' + this.$('#new-ddoc').val(),
-          views: {},
-          language: "javascript"
-        };
-        var ddoc = new this.DocModel(doc, {database: this.database});
-        //this.collection.add(ddoc);
-        return ddoc;
-      } else if ( !this.newDesignDoc() ) {
-        var ddocName = this.$('#ddoc').val();
-        return this.collection.find(function (ddoc) {
-          return ddoc.id === ddocName;
-        }).dDocModel();
-      }
-    }
-  });
-
-  Views.ViewEditor = FauxtonAPI.View.extend({
-    template: "templates/documents/view_editor",
-    builtinReduces: ['_sum', '_count', '_stats'],
-
-    events: {
-      "click button.save": "saveView",
-      "click button.delete": "deleteView",
-      "change select#reduce-function-selector": "updateReduce",
-      "click button.preview": "previewView",
-      "click #db-views-tabs-nav": 'toggleIndexNav'
-    },
-
-    langTemplates: {
-      "javascript": {
-        map: "function(doc) {\n  emit(doc._id, 1);\n}",
-        reduce: "function(keys, values, rereduce){\n  if (rereduce){\n    return sum(values);\n  } else {\n    return values.length;\n  }\n}"
-      }
-    },
-
-    defaultLang: "javascript",
-
-    initialize: function(options) {
-      this.newView = options.newView || false;
-      this.ddocs = options.ddocs;
-      this.params = options.params;
-      this.database = options.database;
-      if (this.newView) {
-        this.viewName = 'newView';
-      } else {
-        this.ddocID = options.ddocInfo.id;
-        this.viewName = options.viewName;
-        this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
-      }
-
-      this.showIndex = false;
-      _.bindAll(this);
-    },
-
-    establish: function () {
-      if (this.ddocInfo) {
-        return this.ddocInfo.fetch();
-      }
-    },
-
-    updateValues: function() {
-      var notification;
-      if (this.model.changedAttributes()) {
-        notification = FauxtonAPI.addNotification({
-          msg: "Document saved successfully.",
-          type: "success",
-          clear: true
-        });
-        this.editor.setValue(this.model.prettyJSON());
-      }
-    },
-
-    updateReduce: function(event) {
-      var $ele = $("#reduce-function-selector");
-      var $reduceContainer = $(".control-group.reduce-function");
-      if ($ele.val() == "CUSTOM") {
-        this.createReduceEditor();
-        this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
-        $reduceContainer.show();
-      } else {
-        $reduceContainer.hide();
-      }
-    },
-
-    deleteView: function (event) {
-      event.preventDefault();
-
-      if (this.newView) { return alert('Cannot delete a new view.'); }
-      if (!confirm('Are you sure you want to delete this view?')) {return;}
-
-      var that = this,
-          promise,
-          viewName = this.$('#index-name').val(),
-          ddocName = this.$('#ddoc :selected').val(),
-          ddoc = this.getCurrentDesignDoc();
-
-      ddoc.removeDdocView(viewName);
-
-      if (ddoc.hasViews()) {
-        promise = ddoc.save(); 
-      } else {
-        promise = ddoc.destroy();
-      }
-
-      promise.then(function () {
-        FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
-        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
-      });
-    },
-
-    saveView: function(event) {
-      var json, notification,
-      that = this;
-
-      if (event) { event.preventDefault();}
-
-      $('#dashboard-content').scrollTop(0); //scroll up
-
-      if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
-        var mapVal = this.mapEditor.getValue(), 
-        reduceVal = this.reduceVal(),
-        viewName = this.$('#index-name').val(),
-        ddoc = this.getCurrentDesignDoc(),
-        ddocName = ddoc.id;
-
-        this.viewName = viewName;
-
-        notification = FauxtonAPI.addNotification({
-          msg: "Saving document.",
-          selector: "#define-view .errors-container",
-          clear: true
-        });
-
-        ddoc.setDdocView(viewName, mapVal, reduceVal);
-
-        ddoc.save().then(function () {
-          that.ddocs.add(ddoc);
-
-          that.mapEditor.editSaved();
-          that.reduceEditor && that.reduceEditor.editSaved();
-
-          FauxtonAPI.addNotification({
-            msg: "View has been saved.",
-            type: "success",
-            selector: "#define-view .errors-container",
-            clear: true
-          });
-
-          if (that.newView) {
-            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.mixins.safeURLName(viewName); 
-
-            FauxtonAPI.navigate(fragment, {trigger: false});
-            that.newView = false;
-            that.ddocID = ddoc.safeID();
-            that.viewName = viewName;
-            that.ddocInfo = ddoc;
-            that.showIndex = true;
-            that.render();
-            FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
-              selectedTab: app.mixins.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.mixins.removeSpecialCharacters(viewName)
-            });
-          }
-
-          if (that.reduceFunStr !== reduceVal) {
-            that.reduceFunStr = reduceVal;
-            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce()); 
-          }
-
-          FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
-
-        }, function(xhr) {
-          var responseText = JSON.parse(xhr.responseText).reason;
-          notification = FauxtonAPI.addNotification({
-            msg: "Save failed: " + responseText,
-            type: "error",
-            clear: true
-          });
-        });
-      } else {
-        var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
-        notification = FauxtonAPI.addNotification({
-          msg: errormessage,
-          type: "error",
-          selector: "#define-view .errors-container",
-          clear: true
-        });
-      }
-    },
-
-    updateView: function(event, paramInfo) {
-       event.preventDefault();
- 
-       if (this.newView) { return alert('Please save this new view before querying it.'); }
- 
-       var errorParams = paramInfo.errorParams,
-           params = paramInfo.params;
- 
-       if (_.any(errorParams)) {
-         _.map(errorParams, function(param) {
- 
-           // TODO: Where to add this error?
-           // bootstrap wants the error on a control-group div, but we're not using that
-           //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
-           return FauxtonAPI.addNotification({
-             msg: "JSON Parse Error on field: "+param.name,
-             type: "error",
-             selector: ".advanced-options .errors-container",
-             clear: true
-           });
-         });
-         FauxtonAPI.addNotification({
-           msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
-           type: "warning",
-           selector: ".advanced-options .errors-container",
-           clear: true
-         });
- 
-         return false;
-      }
- 
-       var fragment = window.location.hash.replace(/\?.*$/, '');
-       fragment = fragment + '?' + $.param(params);
-       FauxtonAPI.navigate(fragment, {trigger: false});
- 
-       FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
-    },
-
-
-    previewView: function(event, paramsInfo) {
-      event.preventDefault();
-      var that = this,
-      mapVal = this.mapVal(),
-      reduceVal = this.reduceVal(),
-      paramsArr = [];
-
-      if (paramsInfo && paramsInfo.params) {
-        paramsArr = paramsInfo.params;
-      }
-
-      var params = _.reduce(paramsArr, function (params, param) {
-        params[param.name] = param.value;
-        return params;
-      }, {reduce: false});
-
-      event.preventDefault();
-
-      FauxtonAPI.addNotification({
-        msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
-        type: "warning",
-        selector: ".advanced-options .errors-container",
-        fade: true
-      });
-
-      var promise = FauxtonAPI.Deferred();
-
-      if (!this.database.allDocs) {
-        this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
-        promise = this.database.allDocs.fetch();
-      } else {
-        promise.resolve();
-      }
-
-      promise.then(function () {
-        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
-
-        var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
-        queryPromise.then(function (results) {
-          FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
-        });
-      });
-    },
-
-    getCurrentDesignDoc: function () {
-      return this.designDocSelector.getCurrentDesignDoc();
-    },
-    
-    isCustomReduceEnabled: function() {
-      return $("#reduce-function-selector").val() == "CUSTOM";
-    },
-
-    mapVal: function () {
-      if (this.mapEditor) {
-        return this.mapEditor.getValue();
-      }
-
-      return this.$('#map-function').text();
-    },
-
-    reduceVal: function() {
-      var reduceOption = this.$('#reduce-function-selector :selected').val(),
-      reduceVal = "";
-
-      if (reduceOption === 'CUSTOM') {
-        reduceVal = this.reduceEditor.getValue();
-      } else if ( reduceOption !== 'NONE') {
-        reduceVal = reduceOption;
-      }
-
-      return reduceVal;
-    },
-
-
-    hasValidCode: function() {
-      return _.every(["mapEditor", "reduceEditor"], function(editorName) {
-        var editor = this[editorName];
-        if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
-          return true;
-        } 
-        return editor.hadValidCode();
-      }, this);
-    },
-
-    toggleIndexNav: function (event) {
-      var $targetId = this.$(event.target).attr('id'),
-          $previousTab = this.$(this.$('li.active a').attr('href')),
-          $targetTab = this.$(this.$(event.target).attr('href'));
-
-      if ($targetTab.attr('id') !== $previousTab.attr('id')) {
-        $previousTab.removeAttr('style');
-      }
-
-      if ($targetId === 'index-nav') {
-        if (this.newView) { return; }
-        var that = this;
-        $('#dashboard-content').scrollTop(0); //scroll up
-        $targetTab.toggle('slow', function(){
-           that.showEditors();
-        });
-      } else {
-        $targetTab.toggle('slow');
-      }
-    },
-
-    serialize: function() {
-      return {
-        ddocs: this.ddocs,
-        ddoc: this.model,
-        ddocName: this.model.id,
-        viewName: this.viewName,
-        reduceFunStr: this.reduceFunStr,
-        isCustomReduce: this.hasCustomReduce(),
-        newView: this.newView,
-        langTemplates: this.langTemplates.javascript
-      };
-    },
-
-    hasCustomReduce: function() {
-      return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
-    },
-
-    hasReduce: function () {
-      return this.reduceFunStr || false;
-    },
-
-    createReduceEditor: function () {
-      if (this.reduceEditor) {
-        this.reduceEditor.remove();
-      }
-
-      this.reduceEditor = new Components.Editor({
-        editorId: "reduce-function",
-        mode: "javascript",
-        couchJSHINT: true
-      });
-      this.reduceEditor.render();
-    },
-
-    beforeRender: function () {
-
-      if (this.newView) {
-        this.reduceFunStr = '_sum';
-        if (this.ddocs.length === 0) {
-          this.model = new Documents.Doc(null, {database: this.database});
-        } else {
-          this.model = this.ddocs.first().dDocModel();
-        }
-        this.ddocID = this.model.id;
-      } else {
-        var ddocDecode = decodeURIComponent(this.ddocID);
-        this.model = this.ddocs.get(ddocDecode).dDocModel();
-        this.reduceFunStr = this.model.viewHasReduce(this.viewName);
-        this.setView('#ddoc-info', new Views.DdocInfo({model: this.ddocInfo }));
-      }
-
-      this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
-        collection: this.ddocs,
-        ddocName: this.model.id,
-        database: this.database
-      }));
-      
-      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
-        updateViewFn: this.updateView,
-        previewFn: this.previewView,
-        database: this.database,
-        viewName: this.viewName,
-        ddocName: this.model.id,
-        hasReduce: this.hasReduce()
-      }));
-    },
-
-    afterRender: function() {
-      if (this.params) {
-        this.advancedOptions.updateFromParams(this.params);
-      }
-
-      this.designDocSelector.updateDesignDoc();
-      if (this.newView || this.showIndex) {
-        this.showEditors();
-        this.showIndex = false;
-      } else {
-        this.$('#index').hide();
-        this.$('#index-nav').parent().removeClass('active');
-      }
-    },
-
-    showEditors: function () {
-      this.mapEditor = new Components.Editor({
-        editorId: "map-function",
-        mode: "javascript",
-        couchJSHINT: true
-      });
-      this.mapEditor.render();
-
-      if (this.hasCustomReduce()) {
-        this.createReduceEditor();
-      } else {
-        $(".control-group.reduce-function").hide();
-      }
-
-      if (this.newView) {
-        this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
-        //Use a built in view by default
-        //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
-      } 
-
-      this.mapEditor.editSaved();
-      this.reduceEditor && this.reduceEditor.editSaved();
-    },
-
-    cleanup: function () {
-      this.mapEditor && this.mapEditor.remove();
-      this.reduceEditor && this.reduceEditor.remove();
-    }
-  });
-
-  Views.JumpToDoc = FauxtonAPI.View.extend({
-    template: "templates/documents/jumpdoc",
-
-    initialize: function (options) {
-      this.database = options.database;
-    },
-
-    events: {
-      "submit #jump-to-doc": "jumpToDoc"
-    },
-
-    jumpToDoc: function (event) {
-      event.preventDefault();
-      var docId = this.$('#jump-to-doc-id').val().trim();
-      FauxtonAPI.navigate('/database/' + app.mixins.safeURLName(this.database.id) +'/' + app.mixins.safeURLName(docId), {trigger: true});
-    },
-
-    afterRender: function () {
-     this.typeAhead = new Components.DocSearchTypeahead({el: '#jump-to-doc-id', database: this.database});
-     this.typeAhead.render();
-    }
-  });
-
-  Views.Sidebar = FauxtonAPI.View.extend({
-    template: "templates/documents/sidebar",
-    events: {
-      "click button#delete-database": "deleteDatabase"
-    },
-
-    initialize: function(options) {
-      this.database = options.database;
-      if (options.ddocInfo) {
-        this.ddocID = options.ddocInfo.id;
-        this.currView = options.ddocInfo.currView;
-      }
-    },
-
-    deleteDatabase: function (event) {
-      event.preventDefault();
-
-      var result = confirm('Are you sure you want to delete this database?');
-
-      if (!result) { return; }
-      var databaseName = this.database.id;
-      FauxtonAPI.addNotification({
-        msg: "Deleting your database...",
-        type: "error",
-        clear: true
-      });
-
-      this.database.destroy().then(function () {
-        FauxtonAPI.navigate('#/_all_dbs');
-        FauxtonAPI.addNotification({
-          msg: 'The database ' + databaseName + ' has been deleted.',
-          clear: true
-        });
-      }).fail(function (rsp, error, msg) {
-        FauxtonAPI.addNotification({
-          msg: 'Could not delete the database, reason ' + msg + '.',
-          type: 'error',
-          clear: true
-        });
-      });
-    },
-
-    serialize: function() {
-      var docLinks = FauxtonAPI.getExtensions('docLinks'),
-          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
-          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
-          extensionList = FauxtonAPI.getExtensions('sidebar:list');
-      return {
-        changes_url: '#' + this.database.url('changes'),
-        permissions_url: '#' + this.database.url('app') + '/permissions',
-        db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
-        database: this.collection.database,
-        database_url: '#' + this.database.url('app'), 
-        docLinks: docLinks,
-        docLimit: Databases.DocLimit,
-        addLinks: addLinks,
-        newLinks: newLinks,
-        extensionList: extensionList > 0
-      };
-    },
-
-    buildIndexList: function(collection, selector, design){
-      _.each(_.keys(collection), function(key){
-        var selected = this.ddocID == "_design/"+design;
-        this.insertView("ul.nav." + selector, new Views.IndexItem({
-          ddoc: design,
-          index: key,
-          database: this.collection.database.id,
-          selected: selected && key == this.currView
-        }));
-      }, this);
-    },
-
-    beforeRender: function(manage) {
-
-      var sidebarListViews = FauxtonAPI.getExtensions('sidebar:list');
-      _.each(sidebarListViews, function (view) {
-        var extension = this.insertView('#extension-navs', view);
-        extension.update(this.database, this.collection, this.viewName);
-        extension.render();
-      }, this);
-
-
-      this.collection.each(function(design) {
-        if (design.has('doc')){
-          var ddoc = design.id.replace(/^_design\//,"");
-          if (design.get('doc').views){
-            this.buildIndexList(design.get('doc').views, "views", ddoc);
-          }
-        }
-      }, this);
-    },
-
-
-    afterRender: function () {
-      if (this.selectedTab) {
-        this.setSelectedTab(this.selectedTab);
-      }
-    },
-
-    setSelectedTab: function (selectedTab) {
-      this.selectedTab = selectedTab;
-      this.$('li').removeClass('active');
-      this.$('#' + selectedTab).parent().addClass('active');
-    }
-  });
-
-  Views.Indexed = FauxtonAPI.View.extend({});
-
-  Views.Changes = FauxtonAPI.View.extend({
-    template: "templates/documents/changes",
-
-    establish: function() {
-      return [ this.model.changes.fetch()];
-    },
-
-    serialize: function () {
-      return {
-        changes: this.model.changes.toJSON(),
-        database: this.model
-      };
-    },
-
-    afterRender: function(){
-      prettyPrint();
-    }
-  });
-
-  Views.DdocInfo = FauxtonAPI.View.extend({
-    template: "templates/documents/ddoc_info",
-
-    initialize: function (options) {
-      this.refreshTime = options.refreshTime || 5000;
-      this.listenTo(this.model, 'change', this.render);
-    },
-
-    serialize: function () {
-      return {
-        view_index: this.model.get('view_index')
-      };
-    },
-
-    afterRender: function () {
-      this.startRefreshInterval();
-    },
-
-    startRefreshInterval: function () {
-      var model = this.model;
-
-      // Interval already set
-      if (this.intervalId) { return ; }
-
-      this.intervalId = setInterval(function () {
-        model.fetch();
-      }, this.refreshTime);
-    },
-
-    stopRefreshInterval: function () {
-      clearInterval(this.intervalId);
-    },
-
-    cleanup: function () {
-      this.stopRefreshInterval();
-    }
-  });
-
-  Documents.Views = Views;
-  return Documents;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/modules/fauxton/base.js b/app/modules/fauxton/base.js
deleted file mode 100644
index cf6305c..0000000
--- a/app/modules/fauxton/base.js
+++ /dev/null
@@ -1,275 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-       // Libs
-       "backbone",
-       "resizeColumns"
-
-],
-
-function(app, Backbone, resizeColumns) {
-
-   //resizeAnimation
-   app.resizeColumns = new resizeColumns({});
-   app.resizeColumns.onResizeHandler();
-
-  var Fauxton = app.module();
-
-  Fauxton.Breadcrumbs = Backbone.View.extend({
-    template: "templates/fauxton/breadcrumbs",
-
-    serialize: function() {
-      var crumbs = _.clone(this.crumbs);
-      return {
-        crumbs: crumbs
-      };
-    },
-
-    initialize: function(options) {
-      this.crumbs = options.crumbs;
-    }
-  });
-
-  Fauxton.VersionInfo = Backbone.Model.extend({
-    url: app.host
-  });
-
-  // TODO: this View should extend from FauxtonApi.View.
-  // Chicken and egg problem, api.js extends fauxton/base.js.
-  // Need to sort the loading order.
-  Fauxton.Footer = Backbone.View.extend({
-    template: "templates/fauxton/footer",
-
-    initialize: function() {
-      this.versionInfo = new Fauxton.VersionInfo();
-    },
-
-    establish: function() {
-      return [this.versionInfo.fetch()];
-    },
-
-    serialize: function() {
-      return {
-        version: this.versionInfo.get("version")
-      };
-    }
-  });
-
-  Fauxton.NavBar = Backbone.View.extend({
-    className:"navbar",
-    template: "templates/fauxton/nav_bar",
-    // TODO: can we generate this list from the router?
-    navLinks: [
-      {href:"#/_all_dbs", title:"Databases", icon: "fonticon-database", className: 'databases'}
-    ],
-
-    bottomNavLinks: [],
-    footerNavLinks: [],
-
-    serialize: function() {
-      return {
-        navLinks: this.navLinks,
-        bottomNavLinks: this.bottomNavLinks,
-        footerNavLinks: this.footerNavLinks
-      };
-    },
-
-    addLink: function(link) {
-      // link.top means it gets pushed to the top of the array,
-      // link.bottomNav means it goes to the additional bottom nav
-      // link.footerNav means goes to the footer nav
-      if (link.top && !link.bottomNav){
-        this.navLinks.unshift(link);
-      } else if (link.top && link.bottomNav){
-        this.bottomNavLinks.unshift(link);
-      } else if (link.bottomNav) {
-        this.bottomNavLinks.push(link);
-      } else if (link.footerNav) {
-        this.footerNavLinks.push(link);
-      } else {
-        this.navLinks.push(link);
-      }
-
-      //this.trigger("link:add");
-
-      //this.render();
-    },
-
-    removeLink: function (removeLink) {
-      var links = this.navlinks;
-
-      if (removeLink.bottomNav) {
-        links = this.bottomNavLinks;
-      } else if (removeLink.footerNav) {
-        links = this.footerNavLinks;
-      }
-
-      var foundIndex = -1;
-
-      _.each(links, function (link, index) {
-        if (link.title === removeLink.title) {
-          foundIndex = index;
-        }
-      });
-
-      if (foundIndex === -1) {return;}
-      links.splice(foundIndex, 1);
-      this.render();
-    },
-
-    afterRender: function(){
-
-      $('#primary-navbar li[data-nav-name="' + app.selectedHeader + '"]').addClass('active');
-
-      var menuOpen = true;
-      var $selectorList = $('body');
-      $('.brand').off();
-      $('.brand').on({
-        click: function(e){
-          if(!$(e.target).is('a')){
-            toggleMenu();
-          }
-         }
-      });
-
-      function toggleMenu(){
-        $selectorList.toggleClass('closeMenu');
-        menuOpen = $selectorList.hasClass('closeMenu');
-        app.resizeColumns.onResizeHandler();
-      }
-
-      $('#primary-navbar').on("click", ".nav a", function(){
-        if (!($selectorList.hasClass('closeMenu'))){
-        setTimeout(
-          function(){
-            $selectorList.addClass('closeMenu');
-            app.resizeColumns.onResizeHandler();
-          },3000);
-
-        }
-      });
-
-      app.resizeColumns.initialize();
-    },
-
-    beforeRender: function () {
-      this.addLinkViews();
-    },
-
-    addLinkViews: function () {
-      var that = this;
-
-      _.each(_.union(this.navLinks, this.bottomNavLinks), function (link) {
-        if (!link.view) { return; }
-
-        //TODO check if establish is a function
-        var establish = link.establish || [];
-        $.when.apply(null, establish).then( function () {
-          var selector =  link.bottomNav ? '#bottom-nav-links' : '#nav-links';
-          that.insertView(selector, link.view).render();
-        });
-      }, this);
-    }
-
-    // TODO: ADD ACTIVE CLASS
-  });
-
-  Fauxton.ApiBar = Backbone.View.extend({
-    template: "templates/fauxton/api_bar",
-    endpoint: '_all_docs',
-
-    documentation: 'docs',
-
-    events:  {
-      "click .api-url-btn" : "toggleAPIbar"
-    },
-
-    toggleAPIbar: function(e){
-      var $currentTarget = $(e.currentTarget).find('span');
-      if ($currentTarget.hasClass("fonticon-plus")){
-        $currentTarget.removeClass("fonticon-plus").addClass("fonticon-minus");
-      }else{
-        $currentTarget.removeClass("fonticon-minus").addClass("fonticon-plus");
-      }
-
-      $('.api-navbar').toggle();
-
-    },
-
-    serialize: function() {
-      return {
-        endpoint: this.endpoint,
-        documentation: this.documentation
-      };
-    },
-
-    hide: function(){
-      this.$el.addClass('hide');
-    },
-    show: function(){
-      this.$el.removeClass('hide');
-    },
-    update: function(endpoint) {
-      this.show();
-      this.endpoint = endpoint[0];
-      this.documentation = endpoint[1];
-      this.render();
-    }
-
-  });
-
-  Fauxton.Notification = Backbone.View.extend({
-    fadeTimer: 5000,
-
-    initialize: function(options) {
-      this.msg = options.msg;
-      this.type = options.type || "info";
-      this.selector = options.selector;
-      this.fade = options.fade === undefined ? true : options.fade;
-      this.clear = options.clear;
-      this.data = options.data || "";
-      this.template = options.template || "templates/fauxton/notification";
-    },
-
-    serialize: function() {
-      return {
-        data: this.data,
-        msg: this.msg,
-        type: this.type
-      };
-    },
-
-    delayedFade: function() {
-      var that = this;
-      if (this.fade) {
-        setTimeout(function() {
-          that.$el.fadeOut();
-        }, this.fadeTimer);
-      }
-    },
-
-    renderNotification: function(selector) {
-      selector = selector || this.selector;
-      if (this.clear) {
-        $(selector).html('');
-      }
-      this.render().$el.appendTo(selector);
-      this.delayedFade();
-      return this;
-    }
-  });
-
-  
-  return Fauxton;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/modules/fauxton/components.js b/app/modules/fauxton/components.js
deleted file mode 100644
index a9f45ad..0000000
--- a/app/modules/fauxton/components.js
+++ /dev/null
@@ -1,337 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define('ace_configuration', ["app", "ace/ace"], function (app, ace) {
-  var path = app.host + app.root + 'js/ace';
-  var config = require("ace/config");
-  config.set("packaged", true);
-  config.set("workerPath",path);
-  config.set("modePath",path);
-  config.set("themePath", path);
-  return ace;
-});
-
-define([
-  "app",
-  // Libs
-  "api",
-  "ace_configuration",
-],
-
-function(app, FauxtonAPI, ace) {
-  var Components = app.module();
-
-  Components.Pagination = FauxtonAPI.View.extend({
-    template: "templates/fauxton/pagination",
-
-    initialize: function(options) {
-      this.page = parseInt(options.page, 10);
-      this.perPage = options.perPage;
-      this.total = options.total;
-      this.totalPages = Math.ceil(this.total / this.perPage);
-      this.urlFun = options.urlFun;
-    },
-
-    serialize: function() {
-      return {
-        page: this.page,
-        perPage: this.perPage,
-        total: this.total,
-        totalPages: this.totalPages,
-        urlFun: this.urlFun
-      };
-    }
-  });
-
-  Components.IndexPagination = FauxtonAPI.View.extend({
-    template: "templates/fauxton/index_pagination",
-    events: {
-      "click a": 'scrollTo',
-      "click a#next": 'nextClicked',
-      "click a#previous": 'previousClicked'
-    },
-
-    scrollTo: function () {
-      if (!this.scrollToSelector) { return; }
-      $(this.scrollToSelector).animate({ scrollTop: 0 }, 'slow');
-    },
-
-    initialize: function (options) {
-      this.previousUrlfn = options.previousUrlfn;
-      this.nextUrlfn = options.nextUrlfn;
-      this.canShowPreviousfn = options.canShowPreviousfn;
-      this.canShowNextfn = options.canShowNextfn;
-      this.scrollToSelector = options.scrollToSelector;
-      _.bindAll(this);
-      this.previousParams = [];
-    },
-
-    previousClicked: function (event) {
-      event.preventDefault();
-      event.stopPropagation();
-      if (!this.canShowPreviousfn()) { return; }
-      FauxtonAPI.navigate(this.previousUrlfn(), {trigger: false});
-      FauxtonAPI.triggerRouteEvent('paginate', 'previous');
-    },
-
-    nextClicked: function (event) {
-      event.preventDefault();
-      event.stopPropagation();
-      if (!this.canShowNextfn()) { return; }
-
-      var params = _.clone(this.collection.params);
-
-      if (params) {
-        this.previousParams.push(params);
-      }
-
-      FauxtonAPI.navigate(this.nextUrlfn(), {trigger: false});
-      FauxtonAPI.triggerRouteEvent('paginate', 'next');
-    },
-
-    serialize: function () {
-      return {
-        canShowNextfn: this.canShowNextfn,
-        canShowPreviousfn: this.canShowPreviousfn,
-      };
-    },
-
-    pageLimit: function () {
-      var limit = 20;
-
-      if (this.collection.params.limit && this.collection.skipFirstItem) {
-        limit = parseInt(this.collection.params.limit, 10) - 1;
-      } else if (this.collection.params.limit) {
-        limit = parseInt(this.collection.params.limit, 10);
-      }
-
-      return limit;
-    },
-
-    pageStart: function () {
-      return (this.previousParams.length * this.pageLimit()) + 1; 
-
-    },
-
-    pageEnd: function () {
-      return (this.previousParams.length * this.pageLimit()) + this.pageLimit();
-    }
-
-  });
-
-  //TODO allow more of the typeahead options.
-  //Current this just does what we need but we
-  //need to support the other typeahead options.
-  Components.Typeahead = FauxtonAPI.View.extend({
-
-    initialize: function (options) {
-      this.source = options.source;
-      _.bindAll(this);
-    },
-
-    afterRender: function () {
-      var onUpdate = this.onUpdate;
-
-      this.$el.typeahead({
-        source: this.source,
-        updater: function (item) {
-          if (onUpdate) {
-            onUpdate(item);
-          }
-
-          return item;
-        }
-      });
-    }
-
-  });
-
-
-  Components.DbSearchTypeahead = Components.Typeahead.extend({
-    initialize: function (options) {
-      this.dbLimit = options.dbLimit || 30;
-      this.onUpdate = options.onUpdate;
-      _.bindAll(this);
-    },
-    source: function(query, process) {
-      var url = [
-        app.host,
-        "/_all_dbs?startkey=%22",
-        query,
-        "%22&endkey=%22",
-        query,
-        "\u9999",
-        "%22&limit=",
-        this.dbLimit
-      ].join('');
-
-      if (this.ajaxReq) { this.ajaxReq.abort(); }
-
-      this.ajaxReq = $.ajax({
-        cache: false,
-        url: url,
-        dataType: 'json',
-        success: function(data) {
-          process(data);
-        }
-      });
-    }
-  });
-
-  Components.DocSearchTypeahead = Components.Typeahead.extend({
-    initialize: function (options) {
-      this.docLimit = options.docLimit || 30;
-      this.database = options.database;
-      _.bindAll(this);
-    },
-    source: function(query, process) {
-      var url = [
-        app.host,
-        "/",
-        this.database.id,
-        "/_all_docs?startkey=%22",
-        query,
-        "%22&endkey=%22",
-        query,
-        "\u9999",
-        "%22&limit=",
-        this.docLimit
-      ].join('');
-
-      if (this.ajaxReq) { this.ajaxReq.abort(); }
-
-      this.ajaxReq = $.ajax({
-        cache: false,
-        url: url,
-        dataType: 'json',
-        success: function(data) {
-          var ids = _.map(data.rows, function (row) {
-            return row.id;
-          });
-          process(ids);
-        }
-      });
-    }
-  });
-
-  Components.Editor = FauxtonAPI.View.extend({
-    initialize: function (options) {
-      this.editorId = options.editorId;
-      this.mode = options.mode || "json";
-      this.commands = options.commands;
-      this.theme = options.theme || 'crimson_editor';
-      this.couchJSHINT = options.couchJSHINT;
-      this.edited = false;
-    },
-
-    afterRender: function () {
-      this.editor = ace.edit(this.editorId);
-      this.setHeightToLineCount();
-      this.editor.setTheme("ace/theme/" + this.theme);
-      this.editor.getSession().setMode("ace/mode/" + this.mode);
-      this.editor.getSession().setUseWrapMode(true);
-      this.editor.setShowPrintMargin(false);
-      this.editor.gotoLine(2);
-      this.addCommands();
-
-      if (this.couchJSHINT) {
-        this.removeIncorrectAnnotations();
-      }
-
-      var that = this;
-      this.editor.getSession().on('change', function () {
-        that.setHeightToLineCount();
-        that.edited = true;
-      });
-
-      $(window).on('beforeunload.editor', function() {
-        if (that.edited) {
-          return 'Your changes have not been saved. Click cancel to return to the document.';
-        }
-      });
-
-      FauxtonAPI.beforeUnload("editor", function (deferred) {
-        if (that.edited) {
-          return 'Your changes have not been saved. Click cancel to return to the document.';
-        }
-      });
-    },
-
-    cleanup: function () {
-      $(window).off('beforeunload.editor');
-      FauxtonAPI.removeBeforeUnload("editor");
-    },
-
-    setHeightToLineCount: function () {
-      var lines = this.editor.getSession().getDocument().getLength();
-      this.editor.setOptions({
-        maxLines: lines
-      });
-
-      this.editor.resize();
-    },
-
-    addCommands: function () {
-      _.each(this.commands, function (command) {
-        this.editor.commands.addCommand(command);
-      }, this);
-    },
-
-    removeIncorrectAnnotations: function () {
-      var editor = this.editor;
-
-      this.editor.getSession().on("changeAnnotation", function(){
-        var annotations = editor.getSession().getAnnotations();
-
-        var newAnnotations = _.reduce(annotations, function (annotations, error) {
-          if (!FauxtonAPI.isIgnorableError(error.raw)) {
-            annotations.push(error);
-          }
-          return annotations;
-        }, []);
-
-        if (annotations.length !== newAnnotations.length) {
-          editor.getSession().setAnnotations(newAnnotations);
-        }
-      });
-    },
-
-    editSaved: function () {
-      this.edited = false;
-    },
-
-    setValue: function (data, lineNumber) {
-      lineNumber = lineNumber ? lineNumber : -1;
-      this.editor.setValue(data, lineNumber);
-    },
-
-    getValue: function () {
-      return this.editor.getValue();
-    },
-
-    getAnnotations: function () {
-      return this.editor.getSession().getAnnotations();
-    },
-
-    hadValidCode: function () {
-     var errors = this.getAnnotations();
-     // By default CouchDB view functions don't pass lint
-     return _.every(errors, function(error) {
-      return FauxtonAPI.isIgnorableError(error.raw);
-      },this);
-    }
-
-  });
-
-  return Components;
-});
-


[14/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix so that you can edit view docs, but not delete them


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/bfd419b3
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/bfd419b3
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/bfd419b3

Branch: refs/heads/import-master
Commit: bfd419b378004ace9abea0232c15c9d602dba142
Parents: 404c691
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 15:27:21 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 15:27:21 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/templates/index_row_docular.html | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/bfd419b3/app/addons/documents/templates/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html
index f1b2217..446a031 100644
--- a/app/addons/documents/templates/index_row_docular.html
+++ b/app/addons/documents/templates/index_row_docular.html
@@ -17,11 +17,13 @@ the License.
 <td>
   <div>
     <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
-    <% if (doc.isEditable()) { %>
+
       <div class="btn-group">
         <a href="#<%= doc.url('app') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
-        <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
+        <% if (doc.isEditable()) { %>
+          <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
+        <% } %>
       </div>
-    <% } %>
+
   </div>
 </td>


[44/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
fixed settings.json.dev; added fauxton & cachebuster


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/a15c5075
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/a15c5075
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/a15c5075

Branch: refs/heads/import-master
Commit: a15c5075deab256c180b5cf572bf1273fe347235
Parents: 247b61c
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Fri Jan 31 16:59:16 2014 -0500
Committer: BigBlueHat <by...@bigbluehat.com>
Committed: Mon Feb 3 11:29:00 2014 -0500

----------------------------------------------------------------------
 settings.json.dev | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a15c5075/settings.json.dev
----------------------------------------------------------------------
diff --git a/settings.json.dev b/settings.json.dev
index e2df66b..d354c29 100644
--- a/settings.json.dev
+++ b/settings.json.dev
@@ -1,5 +1,6 @@
 {
   "deps": [
+  { "name": "fauxton" },
   { "name": "databases" },
   { "name": "documents" },
   { "name": "pouchdb" },
@@ -23,7 +24,8 @@
         "variables": {
           "requirejs": "/assets/js/libs/require.js",
           "css": "./css/index.css",
-          "base": null
+          "base": null,
+          "cachebuster": ""
         },
         "app": {
           "root": "/",
@@ -37,7 +39,8 @@
         "variables": {
           "requirejs": "./js/require.js",
           "css": "./css/index.css",
-          "base": null
+          "base": null,
+          "cachebuster": "?v1.0"
         },
         "app": {
           "root": "/_utils/fauxton/",


[46/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
nv.d3.css is the one CSS used in Fauxton

And now it is loaded before the fauxton.less
file. Other options would include moving/renaming
it (to a .less file) and making it an @import.
Not necessary this time, but may be for other
needed CSS.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/ffda4854
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/ffda4854
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/ffda4854

Branch: refs/heads/import-master
Commit: ffda48540511cc23cf181047bf96b32fe0db9987
Parents: c514de1
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Mon Feb 3 15:20:26 2014 -0500
Committer: BigBlueHat <by...@bigbluehat.com>
Committed: Mon Feb 3 15:20:26 2014 -0500

----------------------------------------------------------------------
 Gruntfile.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ffda4854/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index 554eccb..9507a60 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -67,7 +67,7 @@ module.exports = function(grunt) {
       img: ["assets/img/**"],
       // used in concat:index_css to keep file ordering intact
       // fauxton.css should load first
-      css: ["dist/debug/css/fauxton.css"]
+      css: ["assets/css/*.css", "dist/debug/css/fauxton.css"]
     };
     helper.processAddons(function(addon){
       // Less files from addons


[41/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Add Cachebusting to building new releases of fauxton


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/31e99932
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/31e99932
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/31e99932

Branch: refs/heads/import-master
Commit: 31e99932814a35414fd2d47c155ed3a68fb1506f
Parents: 040e38d
Author: suelockwood <de...@apache.org>
Authored: Thu Jan 30 13:32:45 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Thu Jan 30 13:32:45 2014 -0500

----------------------------------------------------------------------
 assets/index.underscore | 4 ++--
 settings.json.default   | 6 ++++--
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/31e99932/assets/index.underscore
----------------------------------------------------------------------
diff --git a/assets/index.underscore b/assets/index.underscore
index cbf5bd6..396cce3 100644
--- a/assets/index.underscore
+++ b/assets/index.underscore
@@ -24,7 +24,7 @@
   <title>Project Fauxton</title>
 
   <!-- Application styles. -->
-  <link rel="stylesheet" href="<%= css %>">
+  <link rel="stylesheet" href="<%= css %><%=cachebuster%>">
   <% if (base) { %>
   <base href="<%= base %>"></base>
   <% } %>
@@ -42,6 +42,6 @@
   </div>
 
   <!-- Application source. -->
-  <script data-main="/config" src="<%= requirejs %>"></script>
+  <script data-main="/config" src="<%= requirejs %><%=cachebuster%>"></script>
 </body>
 </html>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/31e99932/settings.json.default
----------------------------------------------------------------------
diff --git a/settings.json.default b/settings.json.default
index e817b79..1bc88f6 100644
--- a/settings.json.default
+++ b/settings.json.default
@@ -23,7 +23,8 @@
         "variables": {
           "requirejs": "/assets/js/libs/require.js",
           "css": "./css/index.css",
-          "base": null
+          "base": null,
+          "cachebuster": ""
         },
         "app": {
           "root": "/",
@@ -37,7 +38,8 @@
         "variables": {
           "requirejs": "./js/require.js",
           "css": "./css/index.css",
-          "base": null
+          "base": null,
+          "cachebuster": "?v1.0"
         },
         "app": {
           "root": "/_utils/fauxton/",


[24/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: added dependencies to test task list
Added dependencies to test task list and
added test_inline task for use inside watchRun.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/4d80b7fa
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/4d80b7fa
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/4d80b7fa

Branch: refs/heads/import-master
Commit: 4d80b7fa2c10c3d88a71e05e9dad2290880a2507
Parents: 8a2f0c2
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Wed Jan 15 13:27:06 2014 -0500
Committer: Garren Smith <ga...@gmail.com>
Committed: Thu Jan 16 19:50:41 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4d80b7fa/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index cf70440..b42e6b5 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -422,7 +422,9 @@ module.exports = function(grunt) {
    */
   // clean out previous build artefactsa and lint
   grunt.registerTask('lint', ['clean', 'jshint']);
-  grunt.registerTask('test', ['lint', 'mochaSetup','jst', 'concat:test_config_js', 'mocha_phantomjs']);
+  grunt.registerTask('test', ['lint', 'dependencies', 'test_inline']);
+  // lighter weight test task for use inside dev/watch
+  grunt.registerTask('test_inline', ['mochaSetup','jst', 'concat:test_config_js', 'mocha_phantomjs']);
   // Fetch dependencies (from git or local dir), lint them and make load_addons
   grunt.registerTask('dependencies', ['get_deps', 'gen_load_addons:default']);
   // build templates, js and css


[43/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
2029 Consolidate CSS/LESS class name usage to minimize custom-ness


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/247b61cd
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/247b61cd
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/247b61cd

Branch: refs/heads/import-master
Commit: 247b61cd30a3038989217d25ead6f1f664372513
Parents: 31e9993
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Thu Jan 30 13:32:45 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Fri Jan 31 15:33:47 2014 -0500

----------------------------------------------------------------------
 .../activetasks/assets/less/activetasks.less    |   6 +-
 app/addons/auth/assets/less/auth.less           |  15 -
 app/addons/auth/resources.js                    |   2 +-
 app/addons/compaction/views.js                  |   2 +-
 app/addons/config/assets/less/config.less       |  23 +-
 app/addons/config/templates/dashboard.html      |   6 +-
 app/addons/config/templates/item.html           |   6 +-
 app/addons/databases/assets/less/databases.less | 220 +-------
 app/addons/databases/templates/list.html        |   8 +-
 app/addons/databases/templates/newdatabase.html |   3 +-
 app/addons/documents/assets/less/documents.less |  70 ++-
 .../documents/templates/advanced_options.html   |   4 +-
 .../documents/templates/all_docs_layout.html    |   3 +-
 .../documents/templates/all_docs_list.html      |  10 +-
 app/addons/documents/templates/doc.html         |  16 +-
 .../documents/templates/doc_field_editor.html   |   4 +-
 .../templates/duplicate_doc_modal.html          |   4 +-
 app/addons/documents/templates/jumpdoc.html     |   9 +-
 app/addons/documents/templates/sidebar.html     |  10 +-
 .../documents/templates/upload_modal.html       |   4 +-
 app/addons/documents/templates/view_editor.html |  13 +-
 app/addons/documents/views.js                   |   2 +-
 app/addons/fauxton/templates/api_bar.html       |   4 +-
 app/addons/fauxton/templates/nav_bar.html       |   8 +-
 .../permissions/assets/less/permissions.less    |  39 +-
 app/addons/permissions/templates/item.html      |   2 +-
 app/addons/permissions/templates/section.html   |   8 +-
 .../replication/assets/less/replication.less    | 342 +++++++------
 app/addons/stats/assets/less/stats.less         |   6 +-
 app/addons/styletests/base.js                   |  33 ++
 app/addons/styletests/resources.js              |  22 +
 app/addons/styletests/routes.js                 |  40 ++
 app/addons/styletests/templates/theme.html      | 496 +++++++++++++++++++
 app/addons/styletests/views.js                  |  29 ++
 app/addons/verifyinstall/routes.js              |   2 +-
 app/addons/verifyinstall/views.js               |   2 +-
 app/templates/fauxton/api_bar.html              |   4 +-
 app/templates/fauxton/breadcrumbs.html          |   2 +-
 app/templates/fauxton/nav_bar.html              |   8 +-
 assets/less/fauxton.less                        | 150 ++----
 assets/less/variables.less                      |   2 +
 readme.md                                       |  10 +-
 settings.json.dev                               |  59 +++
 43 files changed, 1060 insertions(+), 648 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/activetasks/assets/less/activetasks.less
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/assets/less/activetasks.less b/app/addons/activetasks/assets/less/activetasks.less
index 743917d..b06f550 100644
--- a/app/addons/activetasks/assets/less/activetasks.less
+++ b/app/addons/activetasks/assets/less/activetasks.less
@@ -10,9 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-.task-tabs li {
+.task-tabs li,
+.active-tasks th {
   cursor: pointer;
 }
-table.active-tasks{
-	font-size: 16px;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/auth/assets/less/auth.less
----------------------------------------------------------------------
diff --git a/app/addons/auth/assets/less/auth.less b/app/addons/auth/assets/less/auth.less
deleted file mode 100644
index 598da10..0000000
--- a/app/addons/auth/assets/less/auth.less
+++ /dev/null
@@ -1,15 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-.menuDropdown {
-  display: none;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/auth/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/resources.js b/app/addons/auth/resources.js
index 321d302..0c9b1f5 100644
--- a/app/addons/auth/resources.js
+++ b/app/addons/auth/resources.js
@@ -58,7 +58,7 @@ function (app, FauxtonAPI, CouchdbSession) {
           passwordsNotMatch:  'Passwords do not match.',
           incorrectCredentials: 'Incorrect username or password.',
           loggedIn: 'You have been logged in.',
-          adminCreated: 'Couchdb admin created',
+          adminCreated: 'CouchDB admin created',
           changePassword: 'Your password has been updated.'
         }, options.messages);
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/compaction/views.js
----------------------------------------------------------------------
diff --git a/app/addons/compaction/views.js b/app/addons/compaction/views.js
index f5469cf..a68daef 100644
--- a/app/addons/compaction/views.js
+++ b/app/addons/compaction/views.js
@@ -85,7 +85,7 @@ function (app, FauxtonAPI, Compaction) {
 
   Compaction.CompactView = FauxtonAPI.View.extend({
     template: 'addons/compaction/templates/compact_view',
-    className: 'btn btn-info btn-large pull-right',
+    className: 'btn btn-info pull-right',
     tagName: 'button',
 
     initialize: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/config/assets/less/config.less
----------------------------------------------------------------------
diff --git a/app/addons/config/assets/less/config.less b/app/addons/config/assets/less/config.less
index 737beb4..88bbc66 100644
--- a/app/addons/config/assets/less/config.less
+++ b/app/addons/config/assets/less/config.less
@@ -13,11 +13,6 @@
 .config-item {
   height: 41px;
 
-  .edit-button {
-    float: right;
-    display:none;
-  }
-
   td:hover .edit-button {
     display: block;
   }
@@ -31,24 +26,10 @@
   }
 }
 
-.button-margin {
-  margin-bottom: 15px;
-}
-
 #add-section-modal {
   width: 400px;
 }
 
-table.config {
-  #config-trash {
-    width: 5%;
-  }
-  
-  #delete-value {
-    text-align: center;
-  } 
-}
-
-button#add-section {
-  float: right;
+#config-trash {
+  width: 5%;
 }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/config/templates/dashboard.html
----------------------------------------------------------------------
diff --git a/app/addons/config/templates/dashboard.html b/app/addons/config/templates/dashboard.html
index ffbeb37..b7dbc55 100644
--- a/app/addons/config/templates/dashboard.html
+++ b/app/addons/config/templates/dashboard.html
@@ -13,12 +13,10 @@ the License.
 -->
 
 <div class="row">
-  <div class="span2 offset10">
-    <button id="add-section" href="#" class="button button-margin">
-      <i class="icon-plus icon-white"> </i>
+    <button id="add-section" href="#" class="btn btn-primary pull-right">
+      <i class="icon icon-plus icon-white"> </i>
       Add Section
     </button>
-  </div>
 </div>
 <table class="config table table-striped table-bordered">
   <thead>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/config/templates/item.html
----------------------------------------------------------------------
diff --git a/app/addons/config/templates/item.html b/app/addons/config/templates/item.html
index 1c808b9..502c9b3 100644
--- a/app/addons/config/templates/item.html
+++ b/app/addons/config/templates/item.html
@@ -20,12 +20,12 @@ the License.
 <td> <%= option.name %> </td>
 <td>
   <div id="show-value">
-    <%= option.value %> <button class="edit-button btn-mini btn"> Edit </button>
+    <%= option.value %> <button class="btn btn-mini pull-right hide edit-button"> Edit </button>
   </div>
   <div id="edit-value-form" style="display:none">
     <input class="value-input" type="text" value="<%= option.value %>" />
     <button id="save-value" class="btn btn-success btn-small"> Save </button>
-    <button id="cancel-value" class="btn btn-danger btn-small"> Cancel </button>
+    <button id="cancel-value" class="btn btn-small"> Cancel </button>
   </div>
 </td>
-<td id="delete-value"> <i class="icon-trash"> </i> </td>
+<td id="delete-value" class="text-center"> <i class="icon-trash"> </i> </td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/databases/assets/less/databases.less
----------------------------------------------------------------------
diff --git a/app/addons/databases/assets/less/databases.less b/app/addons/databases/assets/less/databases.less
index 3d86d81..7b7cf6a 100644
--- a/app/addons/databases/assets/less/databases.less
+++ b/app/addons/databases/assets/less/databases.less
@@ -15,194 +15,15 @@
    ---------------------------------------------------------------------- */
 @import "../../../../../assets/less/bootstrap/variables.less";  
 @import "../../../../../assets/less/bootstrap/mixins.less";   
-#db-tools {
-    position: absolute;
-    top: -7px;
-    right: 0;
-    width: 390px;
-
-    .btn-group {
-        position: absolute;
-        left: 0;
-        top: 6px;
-    }
-
-    form {
-        position: absolute;
-        right: 0;
-        top: 0;
-    }
-}
 
 .tools .nav {
     margin-bottom: 10px;
 }
 
-#sidenav {
-    padding-top: 10px;
-
-    h3 {
-        margin: 10px 0;
-    }
-
-    li a span.divider {
-        background: none;
-        color: #ccc;
-        padding: 0 2px;
-    }
-
-    li.nav-header a {
-        display: inline
-    }
-
-    div.btn-group {
-        display: inline-block;
-    }
-
-    li.nav-header, #sidenav li a {
-        padding-left: 4px;
-    }
-
-    li.active a {
-        background-color: #ddd;
-        color: #333;
-        text-shadow: none;
-    }
-}
-
-.edit {
-    display: none;
-
-    form {
-        margin-bottom: 0;
-    }
-
-    h3 {
-        border-bottom: 1px solid #ccc;
-        font-size: 100%;
-        line-height: 1;
-        margin-bottom: 18px;
-    }
-
-    textarea {
-        height: 100px;
-        width: 95%;
-    }
-
-    .btn-toolbar {
-        margin-bottom: 0;
-    }
-
-    .preview {
-        width: 100px;
-    }
-
-    .save {
-    }
-}
-
-#new-view-index {
-    .confirm {
-        display: none;
-    }
-
-    .confirm .progress {
-        display: none;
-        margin: 20px;
-    }
-
-    textarea {
-        height: 100px;
-        width: 95%;
-    }
-}
-
-.view {
-    display: none;
-
-    .result-tools {
-        float: left;
-        width: 100%;
-        margin-bottom: 10px;
-    }
-
-    table td div  {
-        position: relative;
-    }
-
-    table td div div {
-        display: none;
-        line-height: 1;
-        position: absolute;
-        right: 4px;
-        top: 4px;
-    }
-
-    table td div:hover div a.edits {
-        padding-left: 16px;
-        padding-right: 16px;
-    }
-
-    table td div:hover div {
-        display: block;
-    }
-
-}
-.view.show {
-    display: block;
-}
-.view.show.hidden-by-params {
-    display: none;
-}
-#database .view table tr td {
-    padding: 0;
-}
-
-.loading {display: none;}
-
-.view-request-duration {
-  padding-right: 10px;
-  float: right;
-}
-
-table.active-tasks{
-    th {
-        cursor: pointer;
-    }
-}
-
-.well{
-    .row-fluid{
-        margin: 0;
-    }
-    .row-fluid .row-fluid:last-child .well-item {
-        border: none;
-    }
-    .well-item{
-        color: #666;
-        font-size: 12px;
-        border-bottom: 1px solid #e5e5e5;
-        padding: 8px 4px;
-        strong {
-            font-size: 16px;
-        }  
-    } 
-}
-
-
-#doc {
-    .dropdown-menu{
-        width: auto;
-    }
-}
-// #tabs {
-//     height: 40px;
-// }
-
-.databases{
+.databases {
     a.db-actions,
-    a.db-actions:visited{
-        color: @red; 
+    a.db-actions:visited {
+        color: @red;
         border: 1px solid #e3e3e3;
         padding: 5px 7px;
         .border-radius(6px);
@@ -210,38 +31,3 @@ table.active-tasks{
         font-size: 19px;
     }
 }
-.btn-group{
-    ul.dropdown-menu li a:before{
-        margin-right: 10px;
-    }
-}
-
-.design-doc-group{
-    .span3 { margin: 0;}
-    #new-ddoc-section {
-        margin-top: 10px;
-        label{ width: 100px}
-        .controls{
-            margin-left: 100px;
-        }
-    }
-}
-table#changes-table {
-
-  #changes {
-    width: 50%;
-  }
-
-  #seq, #deleted {
-    width: 5%;
-  }
-
-}
-
-.doc-editor-buttons {
-    margin-bottom: 15px;
-    a.button.btn-large.gray {
-        padding: 9px 10px;
-        vertical-align: middle;
-    }
-}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/databases/templates/list.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/list.html b/app/addons/databases/templates/list.html
index 31c0977..1503c32 100644
--- a/app/addons/databases/templates/list.html
+++ b/app/addons/databases/templates/list.html
@@ -14,9 +14,11 @@ the License.
 
 <div class="result-tools" style="">
   <div id="newButton" class="pull-left"></div>
-  <form id="jump-to-db" class="navbar-form pull-right input-append database-search">
-    <input type="text" class="search-autocomplete" name="search-query" placeholder="Database name"></input>
-    <button class="fonticon-search btn button red " type="submit"></button>
+  <form id="jump-to-db" class="navbar-form pull-right database-search">
+    <div class="input-append">
+      <input type="text" class="search-autocomplete" name="search-query" placeholder="Database name" />
+      <button class="btn btn-primary" type="submit"><i class="icon icon-search"></i></button>
+    </div>
   </form>
 
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/databases/templates/newdatabase.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/newdatabase.html b/app/addons/databases/templates/newdatabase.html
index b357e0b..1376ad5 100644
--- a/app/addons/databases/templates/newdatabase.html
+++ b/app/addons/databases/templates/newdatabase.html
@@ -12,6 +12,5 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 
-<a class="button new" id="new"><i class="icon fonticon-new-database"></i>Add New Database</a>
-
+<a class="btn btn-primary new" id="new"><i class="icon fonticon-new-database"></i> Add New Database</a>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index 68fc58d..6f462ef 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -10,7 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 /*ALL DOCS TABLE*/
-tr.all-docs-item{
+tr.all-docs-item {
   border: none;
   background: transparent;
     .btn-group {
@@ -22,3 +22,71 @@ tr.all-docs-item{
 button.beautify {
 	margin-top: 20px;
 }
+
+
+/** used in all_docs_list.html **/
+.view {
+    table td div {
+        position: relative;
+    }
+
+    table td div div {
+        display: none;
+        line-height: 1;
+        position: absolute;
+        right: 4px;
+        top: 4px;
+    }
+
+    table td div:hover div a.edits {
+        padding-left: 16px;
+        padding-right: 16px;
+    }
+
+    table td div:hover div {
+        display: block;
+    }
+}
+
+/** used in ddocs_info.html **/
+.well {
+    .row-fluid {
+        margin: 0;
+    }
+    .row-fluid .row-fluid:last-child .well-item {
+        border: none;
+    }
+    .well-item {
+        color: #666;
+        font-size: 12px;
+        border-bottom: 1px solid #e5e5e5;
+        padding: 8px 4px;
+        strong {
+            font-size: 16px;
+        }
+    }
+}
+
+/** used in view_editor.html **/
+.design-doc-group{
+    .span3 { margin: 0;}
+    #new-ddoc-section {
+        margin-top: 10px;
+        label{ width: 100px}
+        .controls{
+            margin-left: 100px;
+        }
+    }
+}
+
+/** used in changes.html **/
+#changes-table {
+
+  #changes {
+    width: 50%;
+  }
+
+  #seq, #deleted {
+    width: 5%;
+  }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/advanced_options.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/advanced_options.html b/app/addons/documents/templates/advanced_options.html
index e256325..bea256a 100644
--- a/app/addons/documents/templates/advanced_options.html
+++ b/app/addons/documents/templates/advanced_options.html
@@ -86,9 +86,9 @@ the License.
   <div class="controls-group">
     <div class="row-fluid">
       <div id="button-options" class="controls controls-row">
-        <button type="submit" class="button green">Query</button>
+        <button type="submit" class="btn btn-success">Query</button>
         <% if (showPreview) { %>
-        <button class="button btn-info preview">Browser Preview</button>
+        <button class="btn btn-info preview">Browser Preview</button>
         <% } %>
       </div>
     </div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/all_docs_layout.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_layout.html b/app/addons/documents/templates/all_docs_layout.html
index 6b4a31b..2862e16 100644
--- a/app/addons/documents/templates/all_docs_layout.html
+++ b/app/addons/documents/templates/all_docs_layout.html
@@ -12,7 +12,8 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 <ul class="nav nav-tabs window-resizeable" id="db-views-tabs-nav">
-  <li><a id="toggle-query" class="fonticon-plus fonticon" href="#query" data-bypass="true" data-toggle="tab">Query Options</a></li>
+  <li><a id="toggle-query" href="#query" data-bypass="true" data-toggle="tab">
+    <i class="fonticon fonticon-plus"></i> Query Options</a></li>
 </ul>
 <div class="tab-content">
   <div class="tab-pane" id="query">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/all_docs_list.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_list.html b/app/addons/documents/templates/all_docs_list.html
index 335b040..cdec81e 100644
--- a/app/addons/documents/templates/all_docs_list.html
+++ b/app/addons/documents/templates/all_docs_list.html
@@ -12,16 +12,16 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 
-<div class="view show">
+<div class="view">
   <% if (!viewList) { %>
     <div class="row">
       <div class="btn-toolbar span6">
-        <button type="button" class="btn all" data-toggle="button">✓ All</button>
+        <button type="button" class="btn btn-small all" data-toggle="button">✓ All</button>
         <button class="btn btn-small disabled bulk-delete"><i class="icon-trash"></i></button>
         <% if (expandDocs) { %>
-        <button id="collapse" class="btn"><i class="icon-minus"></i> Collapse</button>
+        <button id="collapse" class="btn btn-small"><i class="icon-minus"></i> Collapse</button>
         <% } else { %>
-        <button id="collapse" class="btn"><i class="icon-plus"></i> Expand</button>
+        <button id="collapse" class="btn btn-small"><i class="icon-plus"></i> Expand</button>
         <% } %>
       </div>
     </div>
@@ -31,7 +31,7 @@ the License.
   <div id="item-numbers"> </div>
 
   <% if (requestDuration) { %>
-    <span class="view-request-duration">
+    <span class="view-request-duration pull-right">
     View request duration: <strong> <%= requestDuration %> </strong> 
     </span>
   <% } %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/doc.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/doc.html b/app/addons/documents/templates/doc.html
index 10bbf8b..5ef70fe 100644
--- a/app/addons/documents/templates/doc.html
+++ b/app/addons/documents/templates/doc.html
@@ -15,19 +15,19 @@ the License.
 <div id="doc">
   <div class="errors-container"></div>
    
-<div class="row doc-editor-buttons"> 
+<div class="nav">
   <div class="span3">
-    <button class="save-doc button green btn-medium save fonticon-circle-check" type="button">Save</button>
-    <button class="button cancel-button gray btn-medium">Back to _all_docs</button>
+    <button class="save-doc btn btn-success save" type="button"><i class="icon fonticon-circle-check"></i> Save</button>
+    <button class="btn cancel-button">Back to _all_docs</button>
   </div>
 
   <div class="span7">
     <% if (attachments) { %>
     <div class="btn-group">
-      <a class="button gray btn-medium dropdown-toggle btn" data-bypass="true" data-toggle="dropdown" href="#">
+      <button class="dropdown-toggle btn" data-bypass="true" data-toggle="dropdown">
         View Attachments
         <span class="caret"></span>
-      </a>
+      </button>
       <ul class="dropdown-menu">
         <%_.each(attachments, function (att) { %>
         <li>
@@ -39,11 +39,11 @@ the License.
       </ul>
     </div>
     <% } %> 
-    <button class="button gray btn-medium  upload"><i class="icon-circle-arrow-up"></i> Upload Attachment</button>
-    <button class="button gray btn-medium duplicate"><i class="icon-repeat"></i> Duplicate document</button>
+    <button class="btn upload"><i class="icon icon-circle-arrow-up"></i> Upload Attachment</button>
+    <button class="btn duplicate"><i class="icon icon-repeat"></i> Duplicate document</button>
   </div>
 
-  <button class="button red btn-medium delete"><i class="icon-trash"></i></button>
+  <button class="btn btn-danger delete"><i class="icon icon-trash"></i></button>
   </ul>
 
 <div id="upload-modal"> </div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/doc_field_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/doc_field_editor.html b/app/addons/documents/templates/doc_field_editor.html
index 77d9278..3ad9484 100644
--- a/app/addons/documents/templates/doc_field_editor.html
+++ b/app/addons/documents/templates/doc_field_editor.html
@@ -21,8 +21,8 @@ the License.
       <button class="btn btn-small new" style="margin-left: 64px"><i class="icon-plus"></i> New field</button>
     </div>
     <div class="btn-toolbar pull-right">
-      <button class="btn btn-small cancel button cancel-button outlineGray fonticon-circle-x">Cancel</button>
-      <button class="btn btn-small save button green fonticon-circle-check">Save</button>
+      <button class="btn btn-small cancel cancel-button"><i class="icon fonticon-circle-x"></i> Cancel</button>
+      <button class="btn btn-small btn-success save"><i class="icon fonticon-circle-check"></i> Save</button>
     </div>
   </div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/duplicate_doc_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/duplicate_doc_modal.html b/app/addons/documents/templates/duplicate_doc_modal.html
index dbb25bc..7616300 100644
--- a/app/addons/documents/templates/duplicate_doc_modal.html
+++ b/app/addons/documents/templates/duplicate_doc_modal.html
@@ -28,8 +28,8 @@ the License.
 
   </div>
   <div class="modal-footer">
-    <a href="#" data-dismiss="modal" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
-    <a href="#" id="duplicate-btn" class="btn btn-primary button green save fonticon-circle-check">Duplicate</a>
+    <button data-dismiss="modal" class="btn cancel-button"><i class="icon fonticon-circle-x"></i> Cancel</button>
+    <button id="duplicate-btn" class="btn btn-success save"><i class="fonticon-circle-check"></i> Duplicate</button>
   </div>
 </div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/jumpdoc.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/jumpdoc.html b/app/addons/documents/templates/jumpdoc.html
index 43fdb9c..1ad3de9 100644
--- a/app/addons/documents/templates/jumpdoc.html
+++ b/app/addons/documents/templates/jumpdoc.html
@@ -12,8 +12,9 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 
-<form id="jump-to-doc" class="form-inline input-append" >
-  <input type="text" id="jump-to-doc-id" class="input-large" placeholder="Document ID"></input>
-
-  <button class="fonticon-search btn button red " type="submit"></button>
+<form id="jump-to-doc" class="pull-right">
+  <div class="input-append">
+    <input type="text" id="jump-to-doc-id" class="input-large" placeholder="Document ID"></input>
+    <button class="btn btn-primary" type="submit"><i class="icon icon-search"></i></button>
+  </div>
 </form>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/sidebar.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/sidebar.html b/app/addons/documents/templates/sidebar.html
index c8ce511..7358960 100644
--- a/app/addons/documents/templates/sidebar.html
+++ b/app/addons/documents/templates/sidebar.html
@@ -22,11 +22,11 @@ the License.
         </button>
         <ul class="dropdown-menu">
           <!-- dropdown menu links -->
-          <li><a class="icon-file" href="<%= db_url %>">Docs</a></li>
-          <li><a class="icon-lock" href="<%= permissions_url %>">Permissions</a></li>
-          <li><a class="icon-forward" href="<%= changes_url %>">Changes</a></li>
+          <li><a href="<%= db_url %>"><i class="icon icon-file"></i> Docs</a></li>
+          <li><a href="<%= permissions_url %>"><i class="icon icon-lock"></i> Permissions</a></li>
+          <li><a href="<%= changes_url %>"><i class="icon icon-forward"></i> Changes</a></li>
           <% _.each(docLinks, function (link) { %>
-          <li><a class="<%= link.icon %>" href="<%= database_url + '/' + link.url %>"><%= link.title %></a></li>
+          <li><a href="<%= database_url + '/' + link.url %>"><i class="icon <%= link.icon %>"></i> <%= link.title %></a></li>
           <% }); %>
         </ul>
       </div>
@@ -49,7 +49,7 @@ the License.
           </li>
         </ul>
       </div>
-        <button id="delete-database" class="btn"><i class="icon-trash"></i> Database</button>
+        <button id="delete-database" class="btn pull-right"><i class="icon-trash"></i> Database</button>
     </div>
   </header>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/upload_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/upload_modal.html b/app/addons/documents/templates/upload_modal.html
index 9a5c5cd..b71cd1e 100644
--- a/app/addons/documents/templates/upload_modal.html
+++ b/app/addons/documents/templates/upload_modal.html
@@ -35,8 +35,8 @@ the License.
     </div>
   </div>
   <div class="modal-footer">
-    <a href="#" data-dismiss="modal" data-bypass="true" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
-    <a href="#" id="upload-btn" data-bypass="true" class="btn btn-primary button green save fonticon-circle-check">Upload</a>
+    <button href="#" data-dismiss="modal" data-bypass="true" class="btn"><i class="icon fonticon-circle-x"></i> Cancel</button>
+    <button href="#" id="upload-btn" data-bypass="true" class="btn btn-success save"><i class="icon fonticon-circle-check"></i> Upload</button>
   </div>
 </div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
index d02971e..be60090 100644
--- a/app/addons/documents/templates/view_editor.html
+++ b/app/addons/documents/templates/view_editor.html
@@ -13,9 +13,12 @@ the License.
 -->
 <div class="row">
   <ul class="nav nav-tabs" id="db-views-tabs-nav">
-    <li class="active"> <a data-bypass="true" id="index-nav" class="fonticon-wrench fonticon" data-toggle="tab" href="#index"><% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a></li>
+    <li class="active"> <a data-bypass="true" id="index-nav" data-toggle="tab" href="#index">
+      <i class="fonticon-wrench fonticon"></i>
+      <% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a></li>
     <% if (!newView) { %>
-    <li><a data-bypass="true" id="query-nav" class="fonticon-plus fonticon" href="#query" data-toggle="tab">Query Options</a></li>
+    <li><a data-bypass="true" id="query-nav" href="#query" data-toggle="tab">
+      <i class="fonticon-plus fonticon"></i> Query Options</a></li>
     <li><a data-bypass="true" id="meta-nav" href="#metadata" data-toggle="tab">Design Doc Metadata</a></li>
     <% } %>
   </ul>
@@ -69,10 +72,10 @@ the License.
           </div>
 
           <div class="control-group">
-            <button class="button green save fonticon-circle-check">Save &amp; Build Index</button>
-            <button class="button btn-info preview">Preview</button>
+            <button class="btn btn-success save"><i class="icon fonticon-circle-check"></i> Save &amp; Build Index</button>
+            <button class="btn btn-info preview">Preview</button>
             <% if (!newView) { %>
-            <button class="button delete outlineGray fonticon-circle-x">Delete</button>
+            <button class="btn btn-danger delete"><i class="icon fonticon-circle-x"></i> Delete</button>
             <% } %>
           </div>
           <div class="clearfix"></div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 8ddf46f..298cfb4 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -156,7 +156,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     template: "addons/documents/templates/upload_modal",
 
     events: {
-      "click a#upload-btn": "uploadFile"
+      "click #upload-btn": "uploadFile"
     },
 
     uploadFile: function (event) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/fauxton/templates/api_bar.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/api_bar.html b/app/addons/fauxton/templates/api_bar.html
index 1f03a2c..4fb5971 100644
--- a/app/addons/fauxton/templates/api_bar.html
+++ b/app/addons/fauxton/templates/api_bar.html
@@ -12,9 +12,9 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 
-<button class="button api-url-btn">
+<button class="btn btn-primary pull-right api-url-btn">
   API URL 
-  <span class="fonticon-plus icon"></span>
+  <i class="fonticon-plus icon"></i>
 </button>
 <div class="api-navbar" style="display: none">
     <div class="input-prepend input-append">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/fauxton/templates/nav_bar.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/nav_bar.html b/app/addons/fauxton/templates/nav_bar.html
index da030d6..9ba24f4 100644
--- a/app/addons/fauxton/templates/nav_bar.html
+++ b/app/addons/fauxton/templates/nav_bar.html
@@ -27,7 +27,7 @@ the License.
     <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>" >
           <a href="<%= link.href %>">
-            <span class="<%= link.icon %> fonticon"></span>
+            <i class="<%= link.icon %> fonticon"></i>
             <%= link.title %>
           </a>
         </li>
@@ -39,7 +39,7 @@ the License.
     <ul id="bottom-nav-links" class="nav">
         <li data-nav-name= "Documentation">
             <a href="<%=getDocUrl('docs')%>" target="_blank">
-              <span class="fonticon-bookmark fonticon"></span>
+              <i class="fonticon-bookmark fonticon"></i>
                 Documentation
             </a>
         </li>
@@ -49,7 +49,7 @@ the License.
       <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>">
             <a href="<%= link.href %>">
-              <span class="<%= link.icon %> fonticon"></span>
+              <i class="<%= link.icon %> fonticon"></i>
               <%= link.title %>
             </a>
         </li>
@@ -61,7 +61,7 @@ the License.
       <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>">
             <a href="<%= link.href %>">
-              <span class="<%= link.icon %> fonticon"></span>
+              <i class="<%= link.icon %> fonticon"></i>
               <%= link.title %>
             </a>
         </li>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/permissions/assets/less/permissions.less
----------------------------------------------------------------------
diff --git a/app/addons/permissions/assets/less/permissions.less b/app/addons/permissions/assets/less/permissions.less
index 7ce4d10..83f270c 100644
--- a/app/addons/permissions/assets/less/permissions.less
+++ b/app/addons/permissions/assets/less/permissions.less
@@ -10,35 +10,18 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-.border-hdr {
-  border-bottom: 1px solid #E3E3E3;
-  margin-bottom: 10px;
-  .help{
-
-  }
-  h3{
-    text-transform: capitalize;
-    margin-bottom: 0;
-  }
-}
-
-
-.permission-items.unstyled{
-	margin-left: 0px;
-	li {
-		padding: 5px;
-		border-bottom: 1px solid #E3E3E3;
-		border-right: 1px solid #E3E3E3;
-		border-left: 3px solid #E3E3E3;
-		&:first-child{
-			border-top: 1px solid #E3E3E3;
-		}
-		&:nth-child(odd){
-      border-left: 3px solid red;
+.permission-items.unstyled {
+  margin-left: 0px;
+  li {
+    padding: 5px;
+    border-bottom: 1px solid #E3E3E3;
+    border-right: 1px solid #E3E3E3;
+    border-left: 3px solid #E3E3E3;
+    &:first-child {
+      border-top: 1px solid #E3E3E3;
     }
-    button {
-    	float: right;
-    	margin-bottom: 6px;
+    &:nth-child(odd){
+      border-left: 3px solid red;
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/permissions/templates/item.html
----------------------------------------------------------------------
diff --git a/app/addons/permissions/templates/item.html b/app/addons/permissions/templates/item.html
index 616ffd6..490cff4 100644
--- a/app/addons/permissions/templates/item.html
+++ b/app/addons/permissions/templates/item.html
@@ -13,5 +13,5 @@ the License.
 -->
 
 <span> <%= item %> </span>
-<button type="button" class="close">&times;</button>
+<button type="button" class="pull-right close">&times;</button>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/permissions/templates/section.html
----------------------------------------------------------------------
diff --git a/app/addons/permissions/templates/section.html b/app/addons/permissions/templates/section.html
index 3360308..8f4d552 100644
--- a/app/addons/permissions/templates/section.html
+++ b/app/addons/permissions/templates/section.html
@@ -11,9 +11,9 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 License for the specific language governing permissions and limitations under
 the License.
 -->
-<header class="border-hdr">
+<header class="page-header">
 <h3> <%= (section) %> </h3>
-<p id="help"> <%= help %> <a href="<%=getDocUrl('database_permission')%>" target="_blank"><i class="icon-question-sign"> </i> </a></p>
+<p class="help"> <%= help %> <a href="<%=getDocUrl('database_permission')%>" target="_blank"><i class="icon-question-sign"> </i> </a></p>
 </header>
 
 <div class="row">
@@ -24,7 +24,7 @@ the License.
     </header>
     <form class="permission-item-form form-inline">
       <input data-section="<%= section %>" data-type="names" type="text" class="item input-small" placeholder="Add Name">
-      <button type="submit" class="button btn green fonticon-circle-plus">Add Name</button>
+      <button type="submit" class="btn btn-success"><i class="icon fonticon-circle-plus"></i> Add Name</button>
     </form>
     <ul class="clearfix unstyled permission-items span10" id="<%= (section) %>-items-names">
     </ul>
@@ -38,7 +38,7 @@ the License.
 
     <form class="permission-item-form form-inline">
       <input data-section="<%= section %>" data-type="roles" type="text" class="item input-small" placeholder="Add Role">
-      <button type="submit" class="button btn green fonticon-circle-plus">Add Role</button>
+      <button type="submit" class="btn btn-success"><i class="icon fonticon-circle-plus"></i> Add Role</button>
     </form>
     <ul class="unstyled permission-items span10" id="<%= (section) %>-items-roles">
     </ul>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/replication/assets/less/replication.less
----------------------------------------------------------------------
diff --git a/app/addons/replication/assets/less/replication.less b/app/addons/replication/assets/less/replication.less
index a301966..0f8a8f5 100644
--- a/app/addons/replication/assets/less/replication.less
+++ b/app/addons/replication/assets/less/replication.less
@@ -10,187 +10,179 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+@import "../../../../../assets/less/variables.less";
 
-@brown: #3A2C2B;
-@red: #E33F3B;
-@darkRed: #AF2D24;
-@linkRed: #DA4F49;
-@greyBrown: #A59D9D;
-@fontGrey: #808080;
-@secondarySidebar: #E4DFDC;
+#replication {
+  position: relative;
+  max-width: none;
+  width: auto;
 
+  .form_set {
+    width: 350px;
+    display: inline-block;
+    border: 1px solid @greyBrownLighter;
+    padding: 15px 10px 0;
+    margin-bottom: 20px;
+    &.middle {
+      width: 100px;
+      border: none;
+      position: relative;
+      height: 100px;
+      margin: 0;
+    }
+    input, select {
+      margin: 0 0 16px 5px;
+      height: 40px;
+      width: 318px;
+    }
+    .btn-group {
+      margin: 0 0 16px 5px;
+      .btn {
+        padding: 10px 57px;
+      }
+    }
+    &.local {
+      .local_option {
+        display: block;
+      }
+      .remote_option {
+        display: none;
+      }
+      .local-btn {
+        background-color: @red;
+        color: #fff;
+      }
+      .remote-btn {
+        background-color: #f5f5f5;
+        color: @fontGrey;
+      }
+    }
+    .local_option {
+      display: none;
+    }
+    .remote-btn {
+      background-color: @red;
+      color: #fff;
+    }
+  }
 
-form#replication {
-	position: relative;
-	max-width: none;
-	width: auto;
 
-	.form_set{
-		width: 350px;
-		display: inline-block;
-		border: 1px solid @greyBrown;
-		padding: 15px 10px 0;
-		margin-bottom: 20px;
-		&.middle{
-			width: 100px;
-			border: none;
-			position: relative;
-			height: 100px;
-			margin: 0;
-		}
-		input, select {
-			margin: 0 0 16px 5px;
-			height: 40px;
-			width: 318px;
-		}
-		.btn-group{
-			margin: 0 0 16px 5px;
-			.btn {
-				padding: 10px 57px;
-			}
-		}
-		&.local{
-			.local_option{
-				display: block;
-			}
-			.remote_option{
-				display: none;
-			}
-			.local-btn{
-				background-color: @red;
-				color: #fff;
-			}
-			.remote-btn{
-				background-color: #f5f5f5;
-				color: @fontGrey;
-			}
-		}
-		.local_option{
-			display: none;
-		}
-		.remote-btn{
-			background-color: @red;
-			color: #fff;
-		}
-	}
+  .options {
+    position: relative;
+    &:after {
+      content: '';
+      display: block;
+      position: absolute;
+      right: -16px;
+      top: 9px;
+      width: 0;
+      height: 0;
+      border-left: 5px solid transparent;
+      border-right: 5px solid transparent;
+      border-bottom: 5px solid black;
+      border-top: none;
+    }
+    &.off {
+      &:after {
+      content: '';
+      display: block;
+      position: absolute;
+      right: -16px;
+      top: 9px;
+      width: 0;
+      height: 0;
+      border-left: 5px solid transparent;
+      border-right: 5px solid transparent;
+      border-bottom: none;
+      border-top: 5px solid black;
+      }
+    }
+  }
+  .control-group {
+    label {
+      float: left;
+      min-height: 30px;
+      vertical-align: top;
+      padding-right: 5px;
+      min-width: 130px;
+      padding-left: 0px;
+    }
+    input[type=radio],
+    input[type=checkbox] {
+      margin: 0 0 2px 0;
+    }
+  }
 
+  .circle {
+    z-index: 0;
+    position: absolute;
+    top: 20px;
+    left: 15px;
 
-	.options {
-		position: relative;
-		&:after{
-			content: '';
-			display: block;
-			position: absolute;
-			right: -16px;
-			top: 9px;
-			width: 0; 
-			height: 0; 
-			border-left: 5px solid transparent;
-			border-right: 5px solid transparent;
-			border-bottom: 5px solid black;
-			border-top: none;
-		}
-		&.off {
-			&:after{
-			content: '';
-			display: block;
-			position: absolute;
-			right: -16px;
-			top: 9px;
-			width: 0; 
-			height: 0; 
-			border-left: 5px solid transparent;
-			border-right: 5px solid transparent;
-			border-bottom: none;
-			border-top: 5px solid black;
-			}
-		}
-	}
-	.control-group{
-		label{
-			float: left;
-			min-height: 30px;
-			vertical-align: top;
-			padding-right: 5px;
-			min-width: 130px;
-			padding-left: 0px;
-		}
-		input[type=radio],
-		input[type=checkbox]{
-			margin: 0 0 2px 0;
-		}
-	}
-
-	.circle{
-		z-index: 0;
-		position: absolute;
-		top: 20px;
-		left: 15px;
-
-		&:after {
-			width: 70px;
-			height: 70px;
-			content: '';
-			display: block;
-			position: relative;
-			margin: 0 auto;
-			border: 1px solid @greyBrown;
-			-webkit-border-radius: 40px;
-			-moz-border-radius: 40px;
-			border-radius:40px;
-		}
-	}
-	.swap {
-		text-decoration: none;
-		z-index: 30;
-		cursor: pointer;
-		position: absolute;
-		font-size: 40px;
-		width: 27px;
-		height: 12px;
-		top: 31px;
-		left: 30px;
-		&:hover {
-			color: @greyBrown;
-		}
-	}
-
+    &:after {
+      width: 70px;
+      height: 70px;
+      content: '';
+      display: block;
+      position: relative;
+      margin: 0 auto;
+      border: 1px solid @greyBrownLighter;
+      -webkit-border-radius: 40px;
+      -moz-border-radius: 40px;
+      border-radius:40px;
+    }
+  }
+  .swap {
+    text-decoration: none;
+    z-index: 30;
+    cursor: pointer;
+    position: absolute;
+    font-size: 40px;
+    width: 27px;
+    height: 12px;
+    top: 31px;
+    left: 30px;
+    &:hover {
+      color: @greyBrownLighter;
+    }
+  }
 }
-#replicationStatus{
-	&.showHeader{
-		li.header{
-			display: block;
-			border: none;
-		}
-		ul {
-			border:1px solid @greyBrown;
-		}
-	}
-	li.header{
-		display: none;
-	}
-	ul{
-		margin: 0;
-		li{
-			.progress,
-			p{
-				margin: 0px;
-				vertical-align: bottom;
-				&.break {
-					-ms-word-break: break-all;
-					word-break: break-all;
 
-					/* Non standard for webkit */
-					word-break: break-word;
-					-webkit-hyphens: auto;
-					-moz-hyphens: auto;
-					hyphens: auto;
-				}
-			}
-			padding: 10px 10px;
-			margin: 0;
-			list-style: none;
-			border-top: 1px solid @greyBrown;
-		}
-	}
+#replicationStatus {
+  &.showHeader {
+    li.header {
+      display: block;
+      border: none;
+    }
+    ul {
+      border:1px solid @greyBrownLighter;
+    }
+  }
+  li.header {
+    display: none;
+  }
+  ul {
+    margin: 0;
+    li {
+      .progress,
+      p {
+        margin: 0px;
+        vertical-align: bottom;
+        &.break {
+          -ms-word-break: break-all;
+          word-break: break-all;
+
+          /* Non standard for webkit */
+          word-break: break-word;
+          -webkit-hyphens: auto;
+          -moz-hyphens: auto;
+          hyphens: auto;
+        }
+      }
+      padding: 10px 10px;
+      margin: 0;
+      list-style: none;
+      border-top: 1px solid @greyBrownLighter;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/stats/assets/less/stats.less
----------------------------------------------------------------------
diff --git a/app/addons/stats/assets/less/stats.less b/app/addons/stats/assets/less/stats.less
index cfa7679..7ec88b9 100644
--- a/app/addons/stats/assets/less/stats.less
+++ b/app/addons/stats/assets/less/stats.less
@@ -11,9 +11,5 @@
 // the License.
 
 .datatypes {
-  border: #d3d3d3 1px solid;
-  -webkit-border-radius: 5px;
-  -moz-border-radius: 5px;
-  border-radius: 5px;
-  padding: 15px;
+  padding: 0 15px;
 }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/styletests/base.js
----------------------------------------------------------------------
diff --git a/app/addons/styletests/base.js b/app/addons/styletests/base.js
new file mode 100644
index 0000000..fae6d11
--- /dev/null
+++ b/app/addons/styletests/base.js
@@ -0,0 +1,33 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  "api",
+  "addons/styletests/routes"
+],
+
+function(app, FauxtonAPI, tests) {
+
+	tests.initialize = function() {
+
+		FauxtonAPI.addHeaderLink({
+			title: "Tests", 
+			href: '#/tests',
+			bottomNav: true,
+			icon: "fonticon-wrench"
+		});
+		
+	};
+
+	return tests;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/styletests/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/styletests/resources.js b/app/addons/styletests/resources.js
new file mode 100644
index 0000000..0309d8e
--- /dev/null
+++ b/app/addons/styletests/resources.js
@@ -0,0 +1,22 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  "api"
+],
+
+function (app, FauxtonAPI) {
+  var resources = {};
+
+  return resources;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/styletests/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/styletests/routes.js b/app/addons/styletests/routes.js
new file mode 100644
index 0000000..cafd9f2
--- /dev/null
+++ b/app/addons/styletests/routes.js
@@ -0,0 +1,40 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  "api",
+  "addons/styletests/views"
+],
+
+function(app, FauxtonAPI, Views) {
+
+	var TestRouteObject = FauxtonAPI.RouteObject.extend({
+		layout: "one_pane",
+		routes: {
+			"tests": "initialize"
+		},
+		selectedHeader: 'theme tests',
+		crumbs:[],
+    apiUrl: function(){
+      return false;
+    },
+    initialize: function(){
+			this.setView("#dashboard-content", new Views.tests({}));
+    }
+	});
+
+	Views.RouteObjects = [TestRouteObject];
+
+	return Views;
+ 
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/styletests/templates/theme.html
----------------------------------------------------------------------
diff --git a/app/addons/styletests/templates/theme.html b/app/addons/styletests/templates/theme.html
new file mode 100644
index 0000000..f05bad1
--- /dev/null
+++ b/app/addons/styletests/templates/theme.html
@@ -0,0 +1,496 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+<div class="container theme-showcase">
+
+  <!-- Main jumbotron for a primary marketing message or call to action -->
+  <div class="jumbotron">
+    <h1>Fauxton Style Guide <small>mostly made of Bootstrap 2.x</small></h1>
+    <p>(Mostly) Standard Bootstrap styles customized for Fauxton.</p>
+  </div>
+
+  <div class="page-header">
+    <h1>Typography</h1>
+  </div>
+  <h1>h1. Heading 1</h1>
+  <h2>h2. Heading 2</h2>
+  <h3>h3. Heading 3</h3>
+  <h4>h4. Heading 4</h4>
+  <h5>h5. Heading 5</h5>
+  <h6>h6. Heading 6</h6>
+
+  <div class="page-header">
+    <h1>Buttons</h1>
+  </div>
+
+  <h4>Bootstrap Standard Button class names</h4>
+  <p>.btn.btn-large.btn-*<br />
+    <button type="button" class="btn btn-large btn-default">Default</button>
+    <button type="button" class="btn btn-large btn-primary">Primary</button>
+    <button type="button" class="btn btn-large btn-success">Success</button>
+    <button type="button" class="btn btn-large btn-info">Info</button>
+    <button type="button" class="btn btn-large btn-warning">Warning</button>
+    <button type="button" class="btn btn-large btn-danger">Danger</button>
+    <button type="button" class="btn btn-large btn-link">Link</button>
+  </p>
+  <p>.btn.btn-*<br />
+    <button type="button" class="btn btn-default">Default</button>
+    <button type="button" class="btn btn-primary">Primary</button>
+    <button type="button" class="btn btn-success">Success</button>
+    <button type="button" class="btn btn-info">Info</button>
+    <button type="button" class="btn btn-warning">Warning</button>
+    <button type="button" class="btn btn-danger">Danger</button>
+    <button type="button" class="btn btn-link">Link</button>
+  </p>
+  <p>.btn.btn-small.btn-*<br />
+    <button type="button" class="btn btn-small btn-default">Default</button>
+    <button type="button" class="btn btn-small btn-primary">Primary</button>
+    <button type="button" class="btn btn-small btn-success">Success</button>
+    <button type="button" class="btn btn-small btn-info">Info</button>
+    <button type="button" class="btn btn-small btn-warning">Warning</button>
+    <button type="button" class="btn btn-small btn-danger">Danger</button>
+    <button type="button" class="btn btn-small btn-link">Link</button>
+  </p>
+  <p>.btn.btn-mini.btn-*<br />
+    <button type="button" class="btn btn-mini btn-default">Default</button>
+    <button type="button" class="btn btn-mini btn-primary">Primary</button>
+    <button type="button" class="btn btn-mini btn-success">Success</button>
+    <button type="button" class="btn btn-mini btn-info">Info</button>
+    <button type="button" class="btn btn-mini btn-warning">Warning</button>
+    <button type="button" class="btn btn-mini btn-danger">Danger</button>
+    <button type="button" class="btn btn-mini btn-link">Link</button>
+  </p>
+
+  <h4>with Icons</h4>
+  <p>.btn.btn-large.btn-*<br />
+    <button type="button" class="btn btn-large btn-default"><i class="icon fonticon-new-database"></i> Default</button>
+    <button type="button" class="btn btn-large btn-primary"><i class="icon fonticon-new-database"></i> Primary</button>
+    <button type="button" class="btn btn-large btn-success"><i class="icon fonticon-new-database"></i> Success</button>
+    <button type="button" class="btn btn-large btn-info"><i class="icon fonticon-new-database"></i> Info</button>
+    <button type="button" class="btn btn-large btn-warning"><i class="icon fonticon-new-database"></i> Warning</button>
+    <button type="button" class="btn btn-large btn-danger"><i class="icon fonticon-new-database"></i> Danger</button>
+    <button type="button" class="btn btn-large btn-link"><i class="icon fonticon-new-database"></i> Link</button>
+  </p>
+
+  <p>.btn.btn-*<br />
+    <button type="button" class="btn btn-default"><i class="icon fonticon-new-database"></i> Default</button>
+    <button type="button" class="btn btn-primary"><i class="icon fonticon-new-database"></i> Primary</button>
+    <button type="button" class="btn btn-success"><i class="icon fonticon-new-database"></i> Success</button>
+    <button type="button" class="btn btn-info"><i class="icon fonticon-new-database"></i> Info</button>
+    <button type="button" class="btn btn-warning"><i class="icon fonticon-new-database"></i> Warning</button>
+    <button type="button" class="btn btn-danger"><i class="icon fonticon-new-database"></i> Danger</button>
+    <button type="button" class="btn btn-link"><i class="icon fonticon-new-database"></i> Link</button>
+  </p>
+  <p>.btn.btn-small.btn-*<br />
+    <button type="button" class="btn btn-small btn-default"><i class="icon fonticon-new-database"></i> Default</button>
+    <button type="button" class="btn btn-small btn-primary"><i class="icon fonticon-new-database"></i> Primary</button>
+    <button type="button" class="btn btn-small btn-success"><i class="icon fonticon-new-database"></i> Success</button>
+    <button type="button" class="btn btn-small btn-info"><i class="icon fonticon-new-database"></i> Info</button>
+    <button type="button" class="btn btn-small btn-warning"><i class="icon fonticon-new-database"></i> Warning</button>
+    <button type="button" class="btn btn-small btn-danger"><i class="icon fonticon-new-database"></i> Danger</button>
+    <button type="button" class="btn btn-small btn-link"><i class="icon fonticon-new-database"></i> Link</button>
+  </p>
+  <p>.btn.btn-mini.btn-*<br />
+    <button type="button" class="btn btn-mini btn-default"><i class="icon fonticon-new-database"></i> Default</button>
+    <button type="button" class="btn btn-mini btn-primary"><i class="icon fonticon-new-database"></i> Primary</button>
+    <button type="button" class="btn btn-mini btn-success"><i class="icon fonticon-new-database"></i> Success</button>
+    <button type="button" class="btn btn-mini btn-info"><i class="icon fonticon-new-database"></i> Info</button>
+    <button type="button" class="btn btn-mini btn-warning"><i class="icon fonticon-new-database"></i> Warning</button>
+    <button type="button" class="btn btn-mini btn-danger"><i class="icon fonticon-new-database"></i> Danger</button>
+    <button type="button" class="btn btn-mini btn-link"><i class="icon fonticon-new-database"></i> Link</button>
+  </p>
+
+  <h4>just Icons</h4>
+  <p>.btn.btn-large.btn-*<br />
+    <button type="button" class="btn btn-large btn-default"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-primary"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-success"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-info"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-warning"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-danger"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-large btn-link"><i class="icon fonticon-new-database"></i></button>
+  </p>
+
+  <p>.btn.btn-*<br />
+    <button type="button" class="btn btn-default"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-primary"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-success"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-info"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-warning"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-danger"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-link"><i class="icon fonticon-new-database"></i></button>
+  </p>
+  <p>.btn.btn-small.btn-*<br />
+    <button type="button" class="btn btn-small btn-default"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-primary"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-success"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-info"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-warning"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-danger"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-small btn-link"><i class="icon fonticon-new-database"></i></button>
+  </p>
+  <p>.btn.btn-mini.btn-*<br />
+    <button type="button" class="btn btn-mini btn-default"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-primary"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-success"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-info"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-warning"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-danger"><i class="icon fonticon-new-database"></i></button>
+    <button type="button" class="btn btn-mini btn-link"><i class="icon fonticon-new-database"></i></button>
+  </p>
+  <p>.btn-group<br />
+    <div class="btn-group">
+      <a href="#" class="btn btn-small edits">Edit design doc</a>
+      <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
+    </div>
+  </p>
+
+  <h4>disabled</h4>
+  <p>.btn.btn-*<br />
+    <button type="button" disabled="disabled" class="btn btn-default"><i class="icon fonticon-new-database"></i> Default</button>
+    <button type="button" disabled="disabled" class="btn btn-primary"><i class="icon fonticon-new-database"></i> Primary</button>
+    <button type="button" disabled="disabled" class="btn btn-success"><i class="icon fonticon-new-database"></i> Success</button>
+    <button type="button" disabled="disabled" class="btn btn-info"><i class="icon fonticon-new-database"></i> Info</button>
+    <button type="button" disabled="disabled" class="btn btn-warning"><i class="icon fonticon-new-database"></i> Warning</button>
+    <button type="button" disabled="disabled" class="btn btn-danger"><i class="icon fonticon-new-database"></i> Danger</button>
+    <button type="button" disabled="disabled" class="btn btn-link"><i class="icon fonticon-new-database"></i> Link</button>
+  </p>
+  <p>.btn.btn-*<br />
+    <button type="button" disabled="disabled" class="btn btn-default">Default</button>
+    <button type="button" disabled="disabled" class="btn btn-primary">Primary</button>
+    <button type="button" disabled="disabled" class="btn btn-success">Success</button>
+    <button type="button" disabled="disabled" class="btn btn-info">Info</button>
+    <button type="button" disabled="disabled" class="btn btn-warning">Warning</button>
+    <button type="button" disabled="disabled" class="btn btn-danger">Danger</button>
+    <button type="button" disabled="disabled" class="btn btn-link">Link</button>
+  </p>
+
+  <div class="page-header">
+    <h1>Forms</h1>
+  </div>
+
+  <form class="navbar-form database-search">
+    <div class="input-append">
+      <input class="search-autocomplete" name="search-query" placeholder="Database name" type="text">
+      <button class="btn btn-primary" type="submit"><i class="icon icon-search"></i></button>
+    </div>
+  </form>
+
+  <form class="navbar-form database-search">
+    <div class="input-append">
+      <input class="search-autocomplete" name="search-query" placeholder="Database name" type="text">
+      <button class="btn btn-primary" type="submit"><i class="icon icon-search"></i> Search</button>
+    </div>
+  </form>
+
+  <form class="navbar-form">
+    <div class="input-append">
+      <input name="search-query" placeholder="Database name" type="text">
+      <button class="btn btn-primary" type="submit">Search</button>
+    </div>
+  </form>
+
+  <form>
+    <fieldset>
+      <legend>Legend</legend>
+      <label>Label name</label>
+      <input type="text" placeholder="Type something…">
+      <span class="help-block">Example block-level help text here.</span>
+      <label class="checkbox">
+        <input type="checkbox"> Check me out
+      </label>
+      <button type="submit" class="btn">Submit</button>
+    </fieldset>
+  </form>
+
+  <p>Search</p>
+  <form class="form-search">
+    <input type="text" class="input-medium search-query">
+    <button type="submit" class="btn">Search</button>
+  </form>
+
+  <p>Sign in</p>
+  <form class="form-inline">
+    <input type="text" class="input-small" placeholder="Email">
+    <input type="password" class="input-small" placeholder="Password">
+    <label class="checkbox">
+      <input type="checkbox"> Remember me
+    </label>
+    <button type="submit" class="btn">Sign in</button>
+  </form>
+
+  <p>Whole form</p>
+  <form class="form-horizontal">
+  <div class="control-group">
+    <label class="control-label" for="inputEmail">Email</label>
+    <div class="controls">
+      <input type="text" id="inputEmail" placeholder="Email">
+    </div>
+  </div>
+  <div class="control-group">
+    <label class="control-label" for="inputPassword">Password</label>
+    <div class="controls">
+      <input type="password" id="inputPassword" placeholder="Password">
+    </div>
+  </div>
+  <div class="control-group">
+    <div class="controls">
+      <label class="checkbox">
+        <input type="checkbox"> Remember me
+      </label>
+      <button type="submit" class="btn">Sign in</button>
+    </div>
+  </div>
+  </form>
+
+  <p>Selects</p>
+  <select>
+    <option>1</option>
+    <option>2</option>
+    <option>3</option>
+    <option>4</option>
+    <option>5</option>
+  </select>
+   
+  <select multiple="multiple">
+    <option>1</option>
+    <option>2</option>
+    <option>3</option>
+    <option>4</option>
+    <option>5</option>
+  </select>
+
+  <p>Inputs with pre</p>
+  <div class="input-prepend">
+    <span class="add-on">@</span>
+    <input class="span2" id="prependedInput" type="text" placeholder="Username">
+  </div>
+  <p>Inputs with post</p>
+  <div class="input-append">
+    <input class="span2" id="appendedInput" type="text">
+    <span class="add-on">.00</span>
+  </div>
+  <p>Inputs with pre and post</p>
+  <div class="input-prepend input-append">
+    <span class="add-on">$</span>
+    <input class="span2" id="appendedPrependedInput" type="text">
+    <span class="add-on">.00</span>
+  </div>
+  <p>Inputs with button</p>
+<div class="input-append">
+  <input class="span2" id="appendedInputButton" type="text">
+  <button class="btn" type="button">Go!</button>
+</div>
+  <p>Inputs with two buttons</p>
+<div class="input-append">
+  <input class="span2" id="appendedInputButtons" type="text">
+  <button class="btn" type="button">Search</button>
+  <button class="btn" type="button">Options</button>
+</div>
+<p>Inputs with dropdown button</p>
+<div class="input-append">
+  <input class="span2" id="appendedDropdownButton" type="text">
+  <div class="btn-group">
+    <button class="btn dropdown-toggle" data-toggle="dropdown">
+      Action
+      <span class="caret"></span>
+    </button>
+    <ul class="dropdown-menu">
+      ...
+    </ul>
+  </div>
+</div>
+<p>Inputs sizes</p>
+<input class="input-mini" type="text" placeholder=".input-mini">
+<input class="input-small" type="text" placeholder=".input-small">
+<input class="input-medium" type="text" placeholder=".input-medium">
+<input class="input-large" type="text" placeholder=".input-large">
+<input class="input-xlarge" type="text" placeholder=".input-xlarge">
+<input class="input-xxlarge" type="text" placeholder=".input-xxlarge">
+
+
+  <div class="page-header">
+    <h1>Thumbnails</h1>
+  </div>
+<img src="https://dl.dropboxusercontent.com/u/44146427/ripley.jpeg" class="img-rounded">
+<img src="https://dl.dropboxusercontent.com/u/44146427/ripley.jpeg" class="img-circle">
+<img src="https://dl.dropboxusercontent.com/u/44146427/ripley.jpeg" class="img-polaroid">
+
+
+  <div class="page-header">
+    <h1>Dropdown menus</h1>
+  </div>
+  <div class="dropdown theme-dropdown clearfix">
+    <a id="dropdownMenu1" href="#" role="button" class="sr-only dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
+    <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
+      <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
+      <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
+      <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
+      <li role="presentation" class="divider"></li>
+      <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
+    </ul>
+  </div>
+
+
+
+
+  <div class="page-header">
+    <h1>Navbars</h1>
+  </div>
+
+  <div class="navbar navbar-default">
+    <div class="container">
+      <div class="navbar-header">
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+        <a class="navbar-brand" href="#">Project name</a>
+      </div>
+      <div class="navbar-collapse collapse">
+        <ul class="nav navbar-nav">
+          <li class="active"><a href="#">Home</a></li>
+          <li><a href="#about">About</a></li>
+          <li><a href="#contact">Contact</a></li>
+        </ul>
+        <ul class="nav navbar-nav navbar-right">
+          <li><a href="../navbar/">Default</a></li>
+          <li><a href="../navbar-static-top/">Static top</a></li>
+          <li class="active"><a href="./">Fixed top</a></li>
+        </ul>
+      </div><!--/.nav-collapse -->
+    </div>
+  </div>
+
+  <div class="navbar navbar-inverse">
+    <div class="container">
+      <div class="navbar-header">
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+        <a class="navbar-brand" href="#">Project name</a>
+      </div>
+      <div class="navbar-collapse collapse">
+        <ul class="nav navbar-nav">
+          <li class="active"><a href="#">Home</a></li>
+          <li><a href="#about">About</a></li>
+          <li><a href="#contact">Contact</a></li>
+        </ul>
+        <ul class="nav navbar-nav navbar-right">
+          <li><a href="../navbar/">Default</a></li>
+          <li><a href="../navbar-static-top/">Static top</a></li>
+          <li class="active"><a href="./">Fixed top</a></li>
+        </ul>
+      </div><!--/.nav-collapse -->
+    </div>
+  </div>
+
+
+
+  <div class="page-header">
+    <h1>Alerts</h1>
+  </div>
+  <div class="alert alert-success">
+    <strong>Well done!</strong> You successfully read this important alert message.
+  </div>
+  <div class="alert alert-info">
+    <strong>Heads up!</strong> This alert needs your attention, but it's not super important.
+  </div>
+  <div class="alert alert-warning">
+    <strong>Warning!</strong> Best check yo self, you're not looking too good.
+  </div>
+  <div class="alert alert-danger">
+    <strong>Oh snap!</strong> Change a few things up and try submitting again.
+  </div>
+
+
+
+  <div class="page-header">
+    <h1>Progresss</h1>
+  </div>
+  <div class="progress">
+    <div class="bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"><span class="sr-only">60% Complete</span></div>
+  </div>
+  <div class="progress">
+    <div class="bar bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%"><span class="sr-only">40% Complete (success)</span></div>
+  </div>
+  <div class="progress">
+    <div class="bar bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%"><span class="sr-only">20% Complete</span></div>
+  </div>
+  <div class="progress">
+    <div class="bar bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete (warning)</span></div>
+  </div>
+  <div class="progress">
+    <div class="bar bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%"><span class="sr-only">80% Complete (danger)</span></div>
+  </div>
+  <div class="progress">
+    <div class="bar bar-success" style="width: 35%"><span class="sr-only">35% Complete (success)</span></div>
+    <div class="bar bar-warning" style="width: 20%"><span class="sr-only">20% Complete (warning)</span></div>
+    <div class="bar bar-danger" style="width: 10%"><span class='sr-only'>10% Complete (danger)</span></div>
+  </div>
+
+
+
+  <div class="page-header">
+    <h1>List groups</h1>
+  </div>
+  <div class="row">
+    <div class="col-sm-4">
+      <ul class="nav nav-tabs nav-stacked">
+        <li class="list-group-item">Cras justo odio</li>
+        <li class="list-group-item">Dapibus ac facilisis in</li>
+        <li class="list-group-item">Morbi leo risus</li>
+        <li class="list-group-item">Porta ac consectetur ac</li>
+        <li class="list-group-item">Vestibulum at eros</li>
+      </ul>
+    </div><!-- /.col-sm-4 -->
+    <div class="col-sm-4">
+      <div class="nav nav-tabs nav-stacked">
+        <a href="#" class="list-group-item active">
+          Cras justo odio
+        </a>
+        <a href="#" class="list-group-item">Dapibus ac facilisis in</a>
+        <a href="#" class="list-group-item">Morbi leo risus</a>
+        <a href="#" class="list-group-item">Porta ac consectetur ac</a>
+        <a href="#" class="list-group-item">Vestibulum at eros</a>
+      </div>
+    </div><!-- /.col-sm-4 -->
+    <div class="col-sm-4">
+      <div class="nav nav-tabs nav-stacked">
+        <a href="#" class="list-group-item active">
+          <h4 class="list-group-item-heading">List group item heading</h4>
+          <p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
+        </a>
+        <a href="#" class="list-group-item">
+          <h4 class="list-group-item-heading">List group item heading</h4>
+          <p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
+        </a>
+        <a href="#" class="list-group-item">
+          <h4 class="list-group-item-heading">List group item heading</h4>
+          <p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
+        </a>
+      </div>
+    </div><!-- /.col-sm-4 -->
+  </div>
+
+  <div class="page-header">
+    <h1>Wells</h1>
+  </div>
+  <div class="well">
+    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p>
+  </div>
+
+
+</div> <!-- /container -->

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/styletests/views.js
----------------------------------------------------------------------
diff --git a/app/addons/styletests/views.js b/app/addons/styletests/views.js
new file mode 100644
index 0000000..f3e8bbb
--- /dev/null
+++ b/app/addons/styletests/views.js
@@ -0,0 +1,29 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  "api"
+],
+
+
+function (app, FauxtonAPI) {
+  var Views= {};
+
+  Views.tests = FauxtonAPI.View.extend({
+    template: "addons/styletests/templates/theme"
+  });
+
+  return Views;
+});
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/verifyinstall/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/verifyinstall/routes.js b/app/addons/verifyinstall/routes.js
index e5024ba..df00736 100644
--- a/app/addons/verifyinstall/routes.js
+++ b/app/addons/verifyinstall/routes.js
@@ -29,7 +29,7 @@ function(app, FauxtonAPI, VerifyInstall) {
       this.setView('#dashboard-content', new VerifyInstall.Main({}));
     },
 
-    crumbs: [{name: 'Verify Couchdb Installation', link: '#'}]
+    crumbs: [{name: 'Verify CouchDB Installation', link: '#'}]
   });
 
   VerifyInstall.RouteObjects = [VerifyRouteObject];

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/addons/verifyinstall/views.js
----------------------------------------------------------------------
diff --git a/app/addons/verifyinstall/views.js b/app/addons/verifyinstall/views.js
index eb6dac4..1e7e6f5 100644
--- a/app/addons/verifyinstall/views.js
+++ b/app/addons/verifyinstall/views.js
@@ -43,7 +43,7 @@ function(app, FauxtonAPI, VerifyInstall) {
 
     complete: function () {
       FauxtonAPI.addNotification({
-        msg: 'Success! You Couchdb install is working. Time to Relax',
+        msg: 'Success! You CouchDB install is working. Time to Relax',
         type: 'success',
         selector: '#error'
       });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/templates/fauxton/api_bar.html
----------------------------------------------------------------------
diff --git a/app/templates/fauxton/api_bar.html b/app/templates/fauxton/api_bar.html
index 1f03a2c..4fb5971 100644
--- a/app/templates/fauxton/api_bar.html
+++ b/app/templates/fauxton/api_bar.html
@@ -12,9 +12,9 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 
-<button class="button api-url-btn">
+<button class="btn btn-primary pull-right api-url-btn">
   API URL 
-  <span class="fonticon-plus icon"></span>
+  <i class="fonticon-plus icon"></i>
 </button>
 <div class="api-navbar" style="display: none">
     <div class="input-prepend input-append">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/templates/fauxton/breadcrumbs.html
----------------------------------------------------------------------
diff --git a/app/templates/fauxton/breadcrumbs.html b/app/templates/fauxton/breadcrumbs.html
index 026db89..34c4136 100644
--- a/app/templates/fauxton/breadcrumbs.html
+++ b/app/templates/fauxton/breadcrumbs.html
@@ -16,7 +16,7 @@ the License.
   <% _.each(_.initial(crumbs), function(crumb) { %>
     <li>
       <a href="#<%= crumb.link %>"><%= crumb.name %></a>
-      <span class="divider fonticon fonticon-carrot"> </span>
+      <i class="divider fonticon fonticon-carrot"> </i>
     </li>
   <% }); %>
   <% var last = _.last(crumbs) || {name: ''} %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/app/templates/fauxton/nav_bar.html
----------------------------------------------------------------------
diff --git a/app/templates/fauxton/nav_bar.html b/app/templates/fauxton/nav_bar.html
index da030d6..9ba24f4 100644
--- a/app/templates/fauxton/nav_bar.html
+++ b/app/templates/fauxton/nav_bar.html
@@ -27,7 +27,7 @@ the License.
     <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>" >
           <a href="<%= link.href %>">
-            <span class="<%= link.icon %> fonticon"></span>
+            <i class="<%= link.icon %> fonticon"></i>
             <%= link.title %>
           </a>
         </li>
@@ -39,7 +39,7 @@ the License.
     <ul id="bottom-nav-links" class="nav">
         <li data-nav-name= "Documentation">
             <a href="<%=getDocUrl('docs')%>" target="_blank">
-              <span class="fonticon-bookmark fonticon"></span>
+              <i class="fonticon-bookmark fonticon"></i>
                 Documentation
             </a>
         </li>
@@ -49,7 +49,7 @@ the License.
       <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>">
             <a href="<%= link.href %>">
-              <span class="<%= link.icon %> fonticon"></span>
+              <i class="<%= link.icon %> fonticon"></i>
               <%= link.title %>
             </a>
         </li>
@@ -61,7 +61,7 @@ the License.
       <% if (link.view) {return;}  %>
         <li data-nav-name= "<%= link.title %>">
             <a href="<%= link.href %>">
-              <span class="<%= link.icon %> fonticon"></span>
+              <i class="<%= link.icon %> fonticon"></i>
               <%= link.title %>
             </a>
         </li>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/assets/less/fauxton.less
----------------------------------------------------------------------
diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less
index e1cfa06..ec3ff55 100644
--- a/assets/less/fauxton.less
+++ b/assets/less/fauxton.less
@@ -65,7 +65,7 @@ body {
   /* OVERRIDE BOOTSTRAP BTN STYLES */
   .btn{
     .box-shadow(none);
-    .border-radius(0);
+    .border-radius(@baseBorderRadius);
     background-image: none;
     text-shadow: none;
     background-repeat: no-repeat;
@@ -125,11 +125,19 @@ a:hover{
   }
 }
 
-/* bootstrap override */
+/* bootstrap overrides */
 .container-fluid {
   padding-right: 0px;
   padding-left: 0px;
 }
+.page-header {
+  border-bottom: 1px solid #E3E3E3;
+  margin-bottom: 10px;
+  h3 {
+    text-transform: capitalize;
+    margin-bottom: 0;
+  }
+}
 
 /* Fixed side navigation */
 #primary-navbar {
@@ -209,11 +217,11 @@ a:hover{
             }
             background-color: @red;
           }
-          &:hover a.fonticon:before{
+          &:hover .fonticon:before{
             color: @white;
           }
-          &.active a.fonticon:before,
-          &:hover a.fonticon:before,
+          &.active .fonticon:before,
+          &:hover .fonticon:before,
           {
             text-shadow: @boxShadow;
             color: @NavIconActive;
@@ -226,7 +234,7 @@ a:hover{
             &.closeMenu{
               color: transparent;
             }
-            & span.fonticon {
+            .fonticon {
               position: relative;
               &:before {
                 position: absolute;
@@ -459,6 +467,11 @@ footer#mainFooter{
         padding: 10px 5px 10px 15px;
         color: #333333;
         border-bottom: 1px solid #989898;
+        .divider {
+          background: none;
+          color: #ccc;
+          padding: 0 2px;
+        }
       }
       .nav-header{
         background-color: #B2B2B2;
@@ -499,14 +512,6 @@ footer#mainFooter{
   margin-bottom: 10px;
 }
 
-.navbar-form.pull-right.database-search {
-  margin: -10px 50px 12px 0;
-  padding: 11px;
-    input[type=text]{
-      margin-top: 0px;
-    }
-}
-
 #db-views-tabs-nav{
   position: fixed;
   z-index: 12;
@@ -600,84 +605,27 @@ tbody {padding-top: 10px;}
 }
 
 .btn {
-  padding-top: 12px;
-  padding-bottom: 12px;
-  margin-top: 0px;
-}
-
-.button{
-  .button-style;
-  .transition(all @transitionSpeed @transitionEaseType);
-  border: none;
-  background-color: @redButton;
-  color: #fff;
   padding: 10px;
+  margin-top: 0px;
   .icon {
-    margin-right: 10px;
-    font-size: 20px;
-  }
-  &:hover {
-    color: #fff;
-    text-decoration: none;
-  }
-}
-
-
-.button-style{
-  background-color: @redButton;
-  color: #fff;
-  padding: 10px 15px;
-  cursor: pointer;
-  &:before{
-    padding-right: 5px;
+    margin-right: 0.2em;
   }
-  &.outlineGray{
-    border: 1px solid @grayLight;
-    background-color: transparent;
-    color: @grayDark;
-    &:hover{
-      border: 1px solid @orange;
+  &.btn-small {
+    padding: 5px 10px;
+    .icon {
+      margin-right: 0;
+      font-size: inherit;
     }
   }
-  &.gray{
-    background-color: #ddd;
-    color: @grayDark;
-  }
-  &.green{
-    background-color: @green;
-  }
-
-  &.round-btn {
-    .border-radius(@radius);
-  }
-  .icon {
-    margin-right: 10px;
-    font-size: 20px;
-  }
-  &:hover {
-    color: #fff;
-    text-decoration: none;
-    background-color: @orange;
-  }
-  a&,
-  a&:visited,
-  a&:active{
-    color: #fff;
-  }
-  &:disabled {
-    opacity: 0.5;
+  &.btn-mini {
+    padding: 3px 8px;
+    .icon {
+      margin-right: 0;
+      font-size: inherit;
+    }
   }
 }
 
-
-
-
-a.button, 
-a.button:visited, 
-a.button:active {
-  .button-style;
-}
-
 .select{
   > a{
     display: block;
@@ -883,15 +831,12 @@ form.view-query-update, form.view-query-save {
     font-size: 18px;
     padding: 14px 5px 30px;
   }
+  .btn .icon{
+    font-size: 21.5px;
+    margin-right: 0;
+  }
 }
 
-.input-append .btn:last-child, 
-.input-append .btn-group:last-child > .dropdown-toggle {
-  padding: 10px 5px 14px;
-}
-.input-append .btn{
-  padding: 10px 5px 14px;
-}
 .row-fluid .input-append [class*="span"],
 .input-prepend input[class*="span"]{
   width: auto;
@@ -936,6 +881,10 @@ div.spinner {
   border: solid 1px #ddd;
 }
 
+.btn-primary {
+  background: @redButton;
+}
+
 .btn-primary a:visited {
   color: #fff;
 }
@@ -944,11 +893,11 @@ div.spinner {
   position: relative;
 }
 
-.button.api-url-btn {
+.api-url-btn {
   position: absolute;
   right: 15px;
   top: -50px;
-  span.icon {
+  .icon {
     font-size: 11px;
   }
 }
@@ -975,17 +924,6 @@ div.spinner {
   }
 }
 
-#jump-to-doc,
-#jump-to-db
- {
-  width: auto;
-  float:right;
-  button{
-    padding-left: 20px;
-    padding-right: 10px;
-  }
-}
-
 #map-function, #reduce-function{
     width: 100%;
     font-size: 16px;
@@ -996,7 +934,3 @@ div.spinner {
     height: 688px;
     font-size: 16px;
 }
-
-#delete-database {
-  float: right;
-}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/assets/less/variables.less
----------------------------------------------------------------------
diff --git a/assets/less/variables.less b/assets/less/variables.less
index bf97b5d..34f8b90 100644
--- a/assets/less/variables.less
+++ b/assets/less/variables.less
@@ -18,6 +18,7 @@
 @darkRed: #AF2D24;
 @linkRed: #DA4F49;
 @greyBrown: #554D4C;
+@greyBrownLighter: #A59D9D;
 @fontGrey: #808080;
 @secondarySidebar: #E4DFDC;
 
@@ -77,6 +78,7 @@
 @textShadowOff: 1px 2px rgba(0,0,0,0);
 
 @radius: 4px;
+@baseBorderRadius: 0;
 @transitionSpeed: .25s;
 @transitionEaseType: linear;
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/247b61cd/readme.md
----------------------------------------------------------------------
diff --git a/readme.md b/readme.md
index a0c7702..bb81095 100644
--- a/readme.md
+++ b/readme.md
@@ -21,7 +21,7 @@ A recent of [node.js](http://nodejs.org/) and npm is required.
 
 ### CouchDB Setup ###
 
-    1. Clone the Couchdb repo: https://github.com/apache/couchdb.git or http://git-wip-us.apache.org/repos/asf/couchdb.git
+    1. Clone the CouchDB repo: https://github.com/apache/couchdb.git or http://git-wip-us.apache.org/repos/asf/couchdb.git
     cd couchdb
 
 ### Fauxton Setup ###
@@ -32,7 +32,11 @@ A recent of [node.js](http://nodejs.org/) and npm is required.
     npm install
 
 ### Dev Server
-    Using the dev server is the easiest way to use fauxton, specially when developing for it.
+Using the dev server is the easiest way to use fauxton, specially when
+developing for it. Copy or symlink the `settings.json.default` (or the
+`settings.json.dev` file if you'd like to see the `styletests` addon).
+
+And then...
 
     grunt dev
 
@@ -63,7 +67,7 @@ A recent of [node.js](http://nodejs.org/) and npm is required.
 
 ### To Deploy Fauxton
 
-    ./bin/grunt couchapp_deploy - to deploy to your local [Couchdb instance] (http://localhost:5984/fauxton/_design/fauxton/index.html)
+    ./bin/grunt couchapp_deploy - to deploy to your local [CouchDB instance] (http://localhost:5984/fauxton/_design/fauxton/index.html)
 
 ## Understang Fauxton Code layout
 


[10/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Keep errors from fading on Doc Editor


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/00c053d8
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/00c053d8
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/00c053d8

Branch: refs/heads/import-master
Commit: 00c053d889e99749fa35c38ebd24f59c3a2176c0
Parents: e22f256
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 12:37:11 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 12:37:11 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/00c053d8/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 2502b58..80c8251 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -890,6 +890,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
           notification = FauxtonAPI.addNotification({
             msg: "Save failed: " + responseText,
             type: "error",
+            fade: false,
             clear: true,
             selector: "#doc .errors-container"
           });


[11/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Remove unused templates


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/aa228e02
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/aa228e02
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/aa228e02

Branch: refs/heads/import-master
Commit: aa228e02e92ce9d1993aa0a154b5909fb869e862
Parents: 00c053d
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 14:45:31 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 14:46:00 2014 -0500

----------------------------------------------------------------------
 app/templates/layouts/one_pane_notabs.html    | 27 ----------------------
 app/templates/layouts/with_right_sidebar.html | 26 ---------------------
 2 files changed, 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/aa228e02/app/templates/layouts/one_pane_notabs.html
----------------------------------------------------------------------
diff --git a/app/templates/layouts/one_pane_notabs.html b/app/templates/layouts/one_pane_notabs.html
deleted file mode 100644
index f58661f..0000000
--- a/app/templates/layouts/one_pane_notabs.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div id="primary-navbar"></div>
-<div id="dashboard" class="container-fluid one-pane">
-  <div class="fixed-header">
-    <div id="breadcrumbs"></div>
-    <div id="api-navbar"></div>
-  </div>
-
-
-  <div class="row-fluid content-area">
-    <div id="dashboard-content" class="window-resizeable"></div>
-  </div>
-</div>
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/aa228e02/app/templates/layouts/with_right_sidebar.html
----------------------------------------------------------------------
diff --git a/app/templates/layouts/with_right_sidebar.html b/app/templates/layouts/with_right_sidebar.html
deleted file mode 100644
index ade5b82..0000000
--- a/app/templates/layouts/with_right_sidebar.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-
-<div id="primary-navbar"></div>
-<div id="dashboard" class="container-fluid">
-  <div class="fixed-header">
-    <div id="breadcrumbs"></div>
-    <div id="api-navbar"></div>
-  </div>
-  <div class="with-sidebar-right content-area">
-    <div id="dashboard-content" class="list"></div>
-    <div id="sidebar-content" class="sidebar pull-right window-resizeable"></div>
-  </div>
-</div>
-


[08/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton fix build


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/c601fdc9
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/c601fdc9
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/c601fdc9

Branch: refs/heads/import-master
Commit: c601fdc92cd5885b341b31a2fc8f105b677e4b95
Parents: 13ef5d1
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Jan 13 14:42:40 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Jan 13 14:42:40 2014 +0200

----------------------------------------------------------------------
 app/addons/documents/assets/less/documents.less  | 11 +++++++++++
 app/addons/documents/views.js                    |  7 +++++--
 app/addons/pouchdb/base.js                       | 11 +++++++++++
 app/templates/documents/duplicate_doc_modal.html |  2 +-
 test/core/layoutSpec.js                          |  2 +-
 test/core/navbarSpec.js                          |  2 +-
 test/core/paginateSpec.js                        |  4 ++--
 7 files changed, 32 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index ff9e88c..38fd792 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -1,3 +1,14 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
 /*ALL DOCS TABLE*/
 tr.all-docs-item{
   border: none;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 80c0d87..94332a2 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -234,7 +234,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     },
 
     events: {
-      "click #duplicate-btn":"duplicate"
+      "click #duplicate-btn":"duplicate",
+      "submit #doc-duplicate": "duplicate"
 
     },
 
@@ -1481,6 +1482,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       promise.then(function () {
         params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
 
+        console.log('p', params, paramsInfo);
         var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
         queryPromise.then(function (results) {
           FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
@@ -1507,8 +1509,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     reduceVal: function() {
       var reduceOption = this.$('#reduce-function-selector :selected').val(),
       reduceVal = "";
-
+      
       if (reduceOption === 'CUSTOM') {
+        if (!this.reduceEditor) { this.createReduceEditor(); }
         reduceVal = this.reduceEditor.getValue();
       } else if ( reduceOption !== 'NONE') {
         reduceVal = reduceOption;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/app/addons/pouchdb/base.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/base.js b/app/addons/pouchdb/base.js
index df6c726..69962bb 100644
--- a/app/addons/pouchdb/base.js
+++ b/app/addons/pouchdb/base.js
@@ -1,3 +1,14 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
 /*
  * NOTE:
  * This temporarily uses the PouchDB map reduce implementation

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/app/templates/documents/duplicate_doc_modal.html
----------------------------------------------------------------------
diff --git a/app/templates/documents/duplicate_doc_modal.html b/app/templates/documents/duplicate_doc_modal.html
index 3f374b6..dbb25bc 100644
--- a/app/templates/documents/duplicate_doc_modal.html
+++ b/app/templates/documents/duplicate_doc_modal.html
@@ -19,7 +19,7 @@ the License.
   </div>
   <div class="modal-body">
     <div id="modal-error" class="hide alert alert-error"/>
-    <form id="file-upload" class="form" method="post">
+    <form id="doc-duplicate" class="form" method="post">
       <p class="help-block">
       Set new documents ID:
       </p>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/test/core/layoutSpec.js
----------------------------------------------------------------------
diff --git a/test/core/layoutSpec.js b/test/core/layoutSpec.js
index 3876b70..4167100 100644
--- a/test/core/layoutSpec.js
+++ b/test/core/layoutSpec.js
@@ -10,7 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 define([
-       'modules/fauxton/layout',
+       'addons/fauxton/layout',
       'testUtils'
 ], function (Layout, testUtils) {
   var assert = testUtils.assert;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/test/core/navbarSpec.js
----------------------------------------------------------------------
diff --git a/test/core/navbarSpec.js b/test/core/navbarSpec.js
index ec3e71f..3eca6f6 100644
--- a/test/core/navbarSpec.js
+++ b/test/core/navbarSpec.js
@@ -10,7 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 define([
-       'modules/fauxton/base',
+       'addons/fauxton/base',
       'testUtils'
 ], function (Fauxton, testUtils) {
   var assert = testUtils.assert,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c601fdc9/test/core/paginateSpec.js
----------------------------------------------------------------------
diff --git a/test/core/paginateSpec.js b/test/core/paginateSpec.js
index 114c434..d05b322 100644
--- a/test/core/paginateSpec.js
+++ b/test/core/paginateSpec.js
@@ -11,8 +11,8 @@
 // the License.
 define([
        'api',
-       'modules/fauxton/components',
-       'modules/documents/resources',
+       'addons/fauxton/components',
+       'addons/documents/resources',
        'testUtils',
        'app'
 ], function (FauxtonAPI, Views, Models, testUtils, app) {


[05/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: move modules to addons


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/5f9a88f6
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/5f9a88f6
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/5f9a88f6

Branch: refs/heads/import-master
Commit: 5f9a88f6913951fcc83214e9a1c94a7fdb988e79
Parents: 27542b1
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Jan 6 12:33:00 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Jan 13 10:51:51 2014 +0200

----------------------------------------------------------------------
 app/addons/activetasks/resources.js             |    2 +-
 app/addons/compaction/routes.js                 |    2 +-
 app/addons/databases/base.js                    |   37 +
 app/addons/databases/resources.js               |  193 ++
 app/addons/databases/routes.js                  |   69 +
 app/addons/databases/templates/item.html        |   24 +
 app/addons/databases/templates/list.html        |   35 +
 app/addons/databases/templates/newdatabase.html |   17 +
 app/addons/databases/templates/sidebar.html     |   31 +
 app/addons/databases/views.js                   |  255 +++
 app/addons/documents/base.js                    |   24 +
 app/addons/documents/resources.js               |  646 ++++++
 app/addons/documents/routes.js                  |  409 ++++
 .../documents/templates/advanced_options.html   |   97 +
 .../documents/templates/all_docs_item.html      |   26 +
 .../documents/templates/all_docs_layout.html    |   20 +
 .../documents/templates/all_docs_list.html      |   43 +
 .../documents/templates/all_docs_number.html    |   21 +
 app/addons/documents/templates/changes.html     |   38 +
 app/addons/documents/templates/ddoc_info.html   |   28 +
 .../templates/design_doc_selector.html          |   35 +
 app/addons/documents/templates/doc.html         |   55 +
 .../documents/templates/doc_field_editor.html   |   74 +
 .../templates/doc_field_editor_tabs.html        |   19 +
 .../templates/duplicate_doc_modal.html          |   36 +
 app/addons/documents/templates/edit_tools.html  |   44 +
 .../documents/templates/index_menu_item.html    |   17 +
 .../documents/templates/index_row_docular.html  |   26 +
 .../documents/templates/index_row_tabular.html  |   25 +
 app/addons/documents/templates/jumpdoc.html     |   19 +
 app/addons/documents/templates/search.html      |   15 +
 app/addons/documents/templates/sidebar.html     |   67 +
 app/addons/documents/templates/tabs.html        |   18 +
 .../documents/templates/upload_modal.html       |   42 +
 app/addons/documents/templates/view_editor.html |   87 +
 app/addons/documents/tests/resourcesSpec.js     |   84 +
 app/addons/documents/views.js                   | 1855 ++++++++++++++++++
 app/addons/fauxton/base.js                      |  271 +++
 app/addons/fauxton/components.js                |  337 ++++
 app/addons/fauxton/layout.js                    |   98 +
 app/addons/fauxton/templates/api_bar.html       |   30 +
 app/addons/fauxton/templates/breadcrumbs.html   |   24 +
 app/addons/fauxton/templates/footer.html        |   15 +
 .../fauxton/templates/index_pagination.html     |   24 +
 app/addons/fauxton/templates/nav_bar.html       |   75 +
 app/addons/fauxton/templates/notification.html  |   18 +
 app/addons/fauxton/templates/pagination.html    |   31 +
 app/addons/permissions/routes.js                |    2 +-
 app/addons/pouchdb/base.js                      |   47 +
 app/addons/pouchdb/pouch.collate.js             |  115 ++
 app/addons/pouchdb/pouchdb.mapreduce.js         |  324 +++
 app/addons/replication/views.js                 |    2 +-
 app/addons/stats/resources.js                   |    2 +-
 app/addons/verifyinstall/resources.js           |    4 +-
 app/api.js                                      |    2 +-
 app/app.js                                      |    8 +-
 app/modules/databases/base.js                   |   37 -
 app/modules/databases/resources.js              |  193 --
 app/modules/databases/routes.js                 |   69 -
 app/modules/databases/views.js                  |  255 ---
 app/modules/documents/base.js                   |   24 -
 app/modules/documents/resources.js              |  646 ------
 app/modules/documents/routes.js                 |  409 ----
 app/modules/documents/tests/resourcesSpec.js    |   84 -
 app/modules/documents/views.js                  | 1855 ------------------
 app/modules/fauxton/base.js                     |  275 ---
 app/modules/fauxton/components.js               |  337 ----
 app/modules/fauxton/layout.js                   |   98 -
 app/modules/pouchdb/base.js                     |   47 -
 app/modules/pouchdb/pouch.collate.js            |  115 --
 app/modules/pouchdb/pouchdb.mapreduce.js        |  324 ---
 app/router.js                                   |   39 +-
 settings.json.default                           |    3 +
 73 files changed, 5961 insertions(+), 4813 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/activetasks/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/resources.js b/app/addons/activetasks/resources.js
index ca732fb..3ac0898 100644
--- a/app/addons/activetasks/resources.js
+++ b/app/addons/activetasks/resources.js
@@ -13,7 +13,7 @@
 define([
   "app",
   "backbone",
-  "modules/fauxton/base",
+  "addons/fauxton/base",
   "d3"
 ],
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/compaction/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/compaction/routes.js b/app/addons/compaction/routes.js
index 2a33e07..ff15c88 100644
--- a/app/addons/compaction/routes.js
+++ b/app/addons/compaction/routes.js
@@ -17,7 +17,7 @@ define([
 
        // Modules
        "addons/compaction/views",
-       "modules/databases/resources"
+       "addons/databases/resources"
 ],
 
 function(app, FauxtonAPI, Compaction, Databases) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/base.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/base.js b/app/addons/databases/base.js
new file mode 100644
index 0000000..1a3dc66
--- /dev/null
+++ b/app/addons/databases/base.js
@@ -0,0 +1,37 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/databases/routes",
+  // Views
+  "addons/databases/views"
+
+],
+
+function(app, FauxtonAPI, Databases, Views) {
+  Databases.Views = Views;
+
+  // Utility functions
+  Databases.databaseUrl = function(database) {
+    var name = _.isObject(database) ? database.id : database,
+        dbname = app.mixins.safeURLName(name);
+
+    return ["/database/", dbname, "/_all_docs?limit=" + Databases.DocLimit].join('');
+  };
+
+  return Databases;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
new file mode 100644
index 0000000..b6d6536
--- /dev/null
+++ b/app/addons/databases/resources.js
@@ -0,0 +1,193 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/documents/resources"
+],
+
+function(app, FauxtonAPI, Documents) {
+  var Databases = FauxtonAPI.addon();
+
+  Databases.DocLimit = 20;
+
+  Databases.Model = Backbone.Model.extend({
+    initialize: function(options) {
+      this.status = new Databases.Status({
+        database: this
+      });
+    },
+
+    documentation: function(){
+      return "all_dbs";
+    },
+    
+    buildAllDocs: function(params) {
+      this.allDocs = new Documents.AllDocs(null, {
+        database: this,
+        params: params
+      });
+
+      return this.allDocs;
+    },
+
+    isNew: function(){
+      // Databases are never new, to make Backbone do a PUT
+      return false;
+    },
+
+    url: function(context) {
+      if (context === "index") {
+        return "/database/" + this.safeID() + "/_all_docs";
+      } else if (context === "web-index") {
+        return "#/database/"+ this.safeID() + "/_all_docs?limit=" + Databases.DocLimit;
+      } else if (context === "apiurl") { 
+        return window.location.origin + "/database/" + this.safeID() + "/_all_docs";
+      } else if (context === "changes") {
+        return "/database/" + this.safeID() + "/_changes?descending=true&limit=100&include_docs=true";
+      } else if (context === "changes-apiurl") { 
+        return window.location.origin + "/database/" + this.safeID() + "/_changes?descending=true&limit=100&include_docs=true";
+      } else if (context === "app") {
+        return "/database/" + this.safeID();
+      } else {
+        return app.host + "/" + this.safeID();
+      }
+    },
+    safeName: function(){
+      return app.mixins.safeURLName(this.get("name"));
+    },
+    safeID: function() {
+      return app.mixins.safeURLName(this.id);
+    },
+    buildChanges: function (params) {
+      this.changes = new Databases.Changes({
+        database: this,
+        params: params
+      });
+
+      return this.changes;
+    }
+  });
+
+  Databases.Changes = Backbone.Collection.extend({
+
+    initialize: function(options) {
+      this.database = options.database;
+      this.params = options.params;
+    },
+    documentation: function(){
+      return "changes";
+    },
+    url: function (context) {
+      var query = "";
+      if (this.params) {
+        query = "?" + $.param(this.params);
+      }
+      if (context === "apiurl") { 
+        return window.location.origin + '/' + this.database.safeID() + '/_changes' + query;
+      } else {
+
+      return app.host + '/' + this.database.safeID() + '/_changes' + query;
+      }
+    },
+
+    parse: function (resp) {
+      this.last_seq = resp.last_seq;
+      return resp.results;
+    }
+  });
+
+  Databases.Status = Backbone.Model.extend({
+    url: function() {
+      return app.host + "/" + this.database.safeID();
+    },
+
+    initialize: function(options) {
+      this.database = options.database;
+    },
+
+    numDocs: function() {
+      return this.get("doc_count");
+    },
+
+    updateSeq: function(full) {
+      var updateSeq = this.get("update_seq");
+      if (full || (typeof(updateSeq) === 'number')) {
+        return updateSeq;
+      } else if (updateSeq) {
+        return updateSeq.split('-')[0];
+      } else {
+        return 0;
+      }
+    },
+
+    humanSize: function() {
+      // cribbed from http://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable
+      var i = -1;
+      var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
+      var fileSizeInBytes = this.dataSize();
+
+      if (!fileSizeInBytes) {
+        return 0;
+      }
+
+      do {
+          fileSizeInBytes = fileSizeInBytes / 1024;
+          i++;
+      } while (fileSizeInBytes > 1024);
+
+      return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
+    },
+    diskSize: function () {
+      return this.get("disk_size");
+    },
+
+    dataSize: function () {
+      if (this.get("other")){
+        return this.get("other").data_size;
+      }else{
+        return 0;
+      }  
+    }
+  });
+
+  // TODO: shared databases - read from the user doc
+  Databases.List = Backbone.Collection.extend({
+    model: Databases.Model,
+    documentation: function(){
+      return "all_dbs";
+    },
+    url: function(context) {
+      if (context === "apiurl") { 
+        return window.location.origin + "/_all_dbs";
+      } else {
+        return app.host + "/_all_dbs";
+      }
+    },
+
+    parse: function(resp) {
+      // TODO: pagination!
+      return _.map(resp, function(database) {
+        return {
+          id: app.mixins.safeURLName(database),
+          name: database
+        };
+      });
+    }
+  });
+
+  return Databases;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/routes.js b/app/addons/databases/routes.js
new file mode 100644
index 0000000..c413018
--- /dev/null
+++ b/app/addons/databases/routes.js
@@ -0,0 +1,69 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/databases/resources",
+  // TODO:: fix the include flow modules so we don't have to require views here
+  "addons/databases/views"
+],
+
+function(app, FauxtonAPI, Databases, Views) {
+
+  var AllDbsRouteObject = FauxtonAPI.RouteObject.extend({
+    layout: "one_pane",
+
+    crumbs: [
+      {"name": "Databases", "link": "/_all_dbs"}
+    ],
+
+    routes: {
+      "": "allDatabases",
+      "index.html": "allDatabases",
+      "_all_dbs(:params)": "allDatabases"
+    },
+
+    apiUrl: function() {
+      return [this.databases.url("apiurl"), this.databases.documentation()];
+    },
+
+    selectedHeader: "Databases",
+
+    initialize: function() {
+      this.databases = new Databases.List();
+      this.deferred = FauxtonAPI.Deferred();
+    },
+
+    allDatabases: function() {
+      var params = app.getParams(),
+          dbPage = params.page;
+
+      this.databasesView = this.setView("#dashboard-content", new Views.List({
+        collection: this.databases
+      }));
+
+      this.databasesView.setPage(dbPage);
+    },
+
+    establish: function() {
+     return [this.databases.fetch()];
+    }
+  });
+
+  Databases.RouteObjects = [AllDbsRouteObject];
+
+  return Databases;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/templates/item.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/item.html b/app/addons/databases/templates/item.html
new file mode 100644
index 0000000..e2f8071
--- /dev/null
+++ b/app/addons/databases/templates/item.html
@@ -0,0 +1,24 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<td>
+  <a href="#/database/<%=encoded%>/_all_docs?limit=<%=docLimit%>"><%= database.get("name") %></a>
+</td>
+<td><%= database.status.humanSize() %></td>
+<td><%= database.status.numDocs() %></td>
+<td><%= database.status.updateSeq() %></td>
+<td>
+  <a class="db-actions btn fonticon-replicate set-replication-start" title="Replicate <%= database.get("name") %>" href="#/replication/new/<%=encoded%>"></a>
+  <a class="db-actions btn icon-lock set-permissions" title="Set permissions for <%= database.get("name") %>" href="#/database/<%=encoded%>/permissions"></a>
+</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/templates/list.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/list.html b/app/addons/databases/templates/list.html
new file mode 100644
index 0000000..31c0977
--- /dev/null
+++ b/app/addons/databases/templates/list.html
@@ -0,0 +1,35 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="result-tools" style="">
+  <div id="newButton" class="pull-left"></div>
+  <form id="jump-to-db" class="navbar-form pull-right input-append database-search">
+    <input type="text" class="search-autocomplete" name="search-query" placeholder="Database name"></input>
+    <button class="fonticon-search btn button red " type="submit"></button>
+  </form>
+
+
+</div>
+<table class="databases table table-striped">
+  <thead>
+    <th>Name</th>
+    <th>Size</th>
+    <th># of Docs</th>
+    <th>Update Seq</th>
+    <th>Actions</th>
+  </thead>
+  <tbody>
+  </tbody>
+</table>
+<div id="database-pagination"></div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/templates/newdatabase.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/newdatabase.html b/app/addons/databases/templates/newdatabase.html
new file mode 100644
index 0000000..b357e0b
--- /dev/null
+++ b/app/addons/databases/templates/newdatabase.html
@@ -0,0 +1,17 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<a class="button new" id="new"><i class="icon fonticon-new-database"></i>Add New Database</a>
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/templates/sidebar.html
----------------------------------------------------------------------
diff --git a/app/addons/databases/templates/sidebar.html b/app/addons/databases/templates/sidebar.html
new file mode 100644
index 0000000..a8bbd89
--- /dev/null
+++ b/app/addons/databases/templates/sidebar.html
@@ -0,0 +1,31 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="row-fluid">
+  <a href="http://couchdb.org" target="_blank"><img src="img/couchdblogo.png"/></a>
+  <br/>
+</div>
+<hr>
+<ul class="nav nav-list">
+  <!-- <li class="nav-header">Database types</li> -->
+  <li class="active"><a class="toggle-view" id="owned">Your databases</a></li>
+  <li><a class="btn new" id="new"><i class="icon-plus"></i> New database</a></li>
+</ul>
+<hr>
+
+<div>
+  <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/CouchDB" data-widget-id="314360971646869505">Tweets by @CouchDB</a>
+<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
+
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
new file mode 100644
index 0000000..80d64ed
--- /dev/null
+++ b/app/addons/databases/views.js
@@ -0,0 +1,255 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  
+  "addons/fauxton/components",
+  "api",
+  "addons/databases/resources"
+],
+
+function(app, Components, FauxtonAPI, Databases) {
+  var Views = {};
+
+  Views.Item = FauxtonAPI.View.extend({
+    template: "templates/databases/item",
+    tagName: "tr",
+    establish: function(){
+      return [this.model.fetch()];
+    },
+    serialize: function() {
+      return {
+        encoded: app.mixins.safeURLName(this.model.get("name")),
+        database: this.model,
+        docLimit: Databases.DocLimit
+      };
+    }
+  });
+
+  Views.List = FauxtonAPI.View.extend({
+    dbLimit: 20,
+    perPage: 20,
+    template: "templates/databases/list",
+    events: {
+      "click button.all": "selectAll",
+      "submit form#jump-to-db": "switchDatabase"
+    },
+
+    initialize: function(options) {
+      var params = app.getParams();
+      this.page = params.page ? parseInt(params.page, 10) : 1;
+    },
+
+    serialize: function() {
+      return {
+        databases: this.collection
+      };
+    },
+    establish: function(){
+      var currentDBs = this.paginated();
+      var deferred = FauxtonAPI.Deferred();
+
+      FauxtonAPI.when(currentDBs.map(function(database) {
+        return database.status.fetch();
+      })).always(function(resp) {
+        //make this always so that even if a user is not allowed access to a database
+        //they will still see a list of all databases
+        deferred.resolve();
+      });
+      return [deferred];
+    },
+    switchDatabase: function(event, selectedName) {
+      event && event.preventDefault();
+
+      var dbname = this.$el.find("[name='search-query']").val().trim();
+
+      if (selectedName) {
+        dbname = selectedName;
+      }
+
+      if (dbname && this.collection.where({"id":app.mixins.safeURLName(dbname)}).length > 0){
+          // TODO: switch to using a model, or Databases.databaseUrl()
+          // Neither of which are in scope right now
+          // var db = new Database.Model({id: dbname});
+          var url = ["/database/", app.mixins.safeURLName(dbname), "/_all_docs?limit=" + Databases.DocLimit].join('');
+          FauxtonAPI.navigate(url);
+      } else {
+        FauxtonAPI.addNotification({
+          msg: 'Database does not exist.',
+          type: 'error'
+        });
+      }
+    },
+
+    paginated: function() {
+      var start = (this.page - 1) * this.perPage;
+      var end = this.page * this.perPage;
+      return this.collection.slice(start, end);
+    },
+
+    beforeRender: function() {
+
+      this.insertView("#newButton", new Views.NewDatabaseButton({
+        collection: this.collection
+      }));
+
+      _.each(this.paginated(), function(database) {
+        this.insertView("table.databases tbody", new Views.Item({
+          model: database
+        }));
+      }, this);
+
+      this.insertView("#database-pagination", new Components.Pagination({
+        page: this.page,
+        perPage: this.perPage,
+        total: this.collection.length,
+        urlFun: function(page) {
+          return "#/_all_dbs?page=" + page;
+        }
+      }));
+    },
+
+    setPage: function(page) {
+      this.page = page || 1;
+    },
+
+    afterRender: function() {
+      var that = this;
+      this.dbSearchTypeahead = new Components.DbSearchTypeahead({
+        dbLimit: this.dbLimit,
+        el: "input.search-autocomplete",
+        onUpdate: function (item) {
+          that.switchDatabase(null, item);
+        }
+      });
+
+      this.dbSearchTypeahead.render();
+    },
+
+    selectAll: function(evt){
+      $("input:checkbox").attr('checked', !$(evt.target).hasClass('active'));
+    }
+  });
+
+
+  Views.NewDatabaseButton = FauxtonAPI.View.extend({
+    template: "templates/databases/newdatabase",
+    events: {
+      "click a#new": "newDatabase"
+    },
+    newDatabase: function() {
+      var notification;
+      var db;
+      // TODO: use a modal here instead of the prompt
+      var name = prompt('Name of database', 'newdatabase');
+      if (name === null) {
+        return;
+      } else if (name.length === 0) {
+        notification = FauxtonAPI.addNotification({
+          msg: "Please enter a valid database name",
+          type: "error",
+          clear: true
+        });
+        return;
+      }
+      db = new this.collection.model({
+        id: name,
+        name: name
+      });
+      notification = FauxtonAPI.addNotification({msg: "Creating database."});
+      db.save().done(function() {
+        notification = FauxtonAPI.addNotification({
+          msg: "Database created successfully",
+          type: "success",
+          clear: true
+        });
+        var route = "#/database/" +  app.mixins.safeURLName(name) + "/_all_docs?limit=" + Databases.DocLimit;
+        app.router.navigate(route, { trigger: true });
+      }
+      ).error(function(xhr) {
+        var responseText = JSON.parse(xhr.responseText).reason;
+        notification = FauxtonAPI.addNotification({
+          msg: "Create database failed: " + responseText,
+          type: "error",
+          clear: true
+        });
+      }
+      );
+    }
+  });
+
+  Views.Sidebar = FauxtonAPI.View.extend({
+    template: "templates/databases/sidebar",
+    events: {
+      "click a#new": "newDatabase",
+      "click a#owned": "showMine",
+      "click a#shared": "showShared"
+    },
+
+    newDatabase: function() {
+      var notification;
+      var db;
+      // TODO: use a modal here instead of the prompt
+      var name = prompt('Name of database', 'newdatabase');
+      if (name === null) {
+        return;
+      } else if (name.length === 0) {
+        notification = FauxtonAPI.addNotification({
+          msg: "Please enter a valid database name",
+          type: "error",
+          clear: true
+        });
+        return;
+      }
+      db = new this.collection.model({
+        id: encodeURIComponent(name),
+        name: name
+      });
+      notification = FauxtonAPI.addNotification({msg: "Creating database."});
+      db.save().done(function() {
+        notification = FauxtonAPI.addNotification({
+          msg: "Database created successfully",
+          type: "success",
+          clear: true
+        });
+        var route = "#/database/" +  name + "/_all_docs?limit=" + Databases.DocLimit;
+        app.router.navigate(route, { trigger: true });
+      }
+      ).error(function(xhr) {
+        var responseText = JSON.parse(xhr.responseText).reason;
+        notification = FauxtonAPI.addNotification({
+          msg: "Create database failed: " + responseText,
+          type: "error",
+          clear: true
+        });
+      }
+      );
+    },
+
+    showMine: function(){
+      $.contribute(
+        'Show unshared databases',
+        'app/addons/databases/views.js'
+      );
+    },
+
+    showShared: function(){
+      $.contribute(
+        'Show shared databases (e.g. continuous replications to/from the database)',
+        'app/addons/databases/views.js'
+      );
+    }
+  });
+
+  return Views;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/base.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/base.js b/app/addons/documents/base.js
new file mode 100644
index 0000000..cb68a31
--- /dev/null
+++ b/app/addons/documents/base.js
@@ -0,0 +1,24 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/documents/routes"
+],
+
+function(app, FauxtonAPI, Documents) {
+  return Documents;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
new file mode 100644
index 0000000..5254302
--- /dev/null
+++ b/app/addons/documents/resources.js
@@ -0,0 +1,646 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+  "app",
+  "api"
+],
+
+function(app, FauxtonAPI) {
+  var Documents = FauxtonAPI.addon();
+
+  Documents.Doc = Backbone.Model.extend({
+    idAttribute: "_id",
+    documentation: function(){
+      return "docs";
+    },
+    url: function(context) {
+      if (context === "app") {
+        return this.getDatabase().url("app") + "/" + this.safeID();
+      } else if (context === "web-index") {
+        return this.getDatabase().url("app") + "/" + app.mixins.safeURLName(this.id);
+      } else if (context === "apiurl"){
+        return window.location.origin + "/" + this.getDatabase().safeID() + "/" + this.safeID();
+      } else {
+        return app.host + "/" + this.getDatabase().safeID() + "/" + this.safeID();
+      }
+    },
+
+    initialize: function(_attrs, options) {
+      if (this.collection && this.collection.database) {
+        this.database = this.collection.database;
+      } else if (options.database) {
+        this.database = options.database;
+      }
+    },
+
+    // HACK: the doc needs to know about the database, but it may be
+    // set directly or indirectly in all docs
+    getDatabase: function() {
+      return this.database ? this.database : this.collection.database;
+    },
+
+    validate: function(attrs, options) {
+      if (this.id && this.id !== attrs._id && this.get('_rev') ) {
+        return "Cannot change a documents id.";
+      }
+    },
+
+    docType: function() {
+      return this.id.match(/^_design/) ? "design doc" : "doc";
+    },
+
+    isEditable: function() {
+      return this.docType() != "reduction";
+    },
+
+    isDdoc: function() {
+      return this.docType() === "design doc";
+    },
+
+    hasViews: function() {
+      if (!this.isDdoc()) return false;
+      var doc = this.get('doc');
+      if (doc) {
+        return doc && doc.views && _.keys(doc.views).length > 0;
+      }
+
+      var views = this.get('views');
+      return views && _.keys(views).length > 0;
+    },
+
+    hasAttachments: function () {
+      return !!this.get('_attachments');
+    },
+
+    getDdocView: function(view) {
+      if (!this.isDdoc() || !this.hasViews()) return false;
+
+      var doc = this.get('doc');
+      if (doc) {
+        return doc.views[view];
+      }
+
+      return this.get('views')[view];
+    },
+
+    setDdocView: function (view, map, reduce) {
+      if (!this.isDdoc()) return false;
+      var views = this.get('views');
+          tempView = views[view] || {};
+
+      if (reduce) {
+        tempView.reduce=reduce;
+      } else {
+        delete tempView.reduce;
+      }
+      tempView.map= map;
+
+      views[view] = tempView;
+      this.set({views: views});
+
+      return true;
+    },
+
+    removeDdocView: function (viewName) {
+      if (!this.isDdoc()) return false;
+      var views = this.get('views');
+
+      delete views[viewName];
+      this.set({views: views});
+    },
+
+    dDocModel: function () {
+      if (!this.isDdoc()) return false;
+      var doc = this.get('doc');
+
+      if (doc) {
+        return new Documents.Doc(doc, {database: this.database});
+      } 
+
+      return this;
+    },
+
+    viewHasReduce: function(viewName) {
+      var view = this.getDdocView(viewName);
+
+      return view && view.reduce;
+    },
+
+    // Need this to work around backbone router thinking _design/foo
+    // is a separate route. Alternatively, maybe these should be
+    // treated separately. For instance, we could default into the
+    // json editor for docs, or into a ddoc specific page.
+    safeID: function() {
+      if (this.isDdoc()){
+        var ddoc = this.id.replace(/^_design\//,"");
+        return "_design/"+app.mixins.safeURLName(ddoc);
+      }else{
+        return app.mixins.safeURLName(this.id);
+      }
+    },
+
+    destroy: function() {
+      var url = this.url() + "?rev=" + this.get('_rev');
+      return $.ajax({
+        url: url,
+        dataType: 'json',
+        type: 'DELETE'
+      });
+    },
+
+    parse: function(resp) {
+      if (resp.rev) {
+        resp._rev = resp.rev;
+        delete resp.rev;
+      }
+      if (resp.id) {
+        if (typeof(this.id) === "undefined") {
+          resp._id = resp.id;
+        }
+        delete resp.id;
+      }
+      if (resp.ok) {
+        delete resp.ok;
+      }
+      return resp;
+    },
+
+    prettyJSON: function() {
+      var data = this.get("doc") ? this.get("doc") : this;
+
+      return JSON.stringify(data, null, "  ");
+    },
+
+    copy: function (copyId) {
+      return $.ajax({
+        type: 'COPY',
+        url: '/' + this.database.safeID() + '/' + this.safeID(),
+        headers: {Destination: copyId}
+      });
+    },
+
+    isNewDoc: function () {
+      return this.get('_rev') ? false : true;
+    }
+  });
+
+  Documents.DdocInfo = Backbone.Model.extend({
+    idAttribute: "_id",
+    documentation: function(){
+      return "docs";
+    },
+    initialize: function (_attrs, options) {
+      this.database = options.database;
+    },
+
+    url: function(context) {
+      if (context === "app") {
+        return this.database.url("app") + "/" + this.safeID() + '/_info';
+      } else if (context === "apiurl"){
+        return window.location.origin + "/" + this.database.safeID() + "/" + this.safeID() + '/_info';
+      } else {
+        return app.host + "/" + this.database.safeID() + "/" + this.safeID() + '/_info';
+      }
+    },
+
+    // Need this to work around backbone router thinking _design/foo
+    // is a separate route. Alternatively, maybe these should be
+    // treated separately. For instance, we could default into the
+    // json editor for docs, or into a ddoc specific page.
+    safeID: function() {
+      var ddoc = this.id.replace(/^_design\//,"");
+      return "_design/"+app.mixins.safeURLName(ddoc);
+    }
+
+  });
+
+  Documents.ViewRow = Backbone.Model.extend({
+    // this is a hack so that backbone.collections doesn't group 
+    // these by id and reduce the number of items returned.
+    idAttribute: "_id",
+
+    docType: function() {
+      if (!this.id) return "reduction";
+
+      return this.id.match(/^_design/) ? "design doc" : "doc";
+    },
+    documentation: function(){
+      return "docs";
+    },
+    url: function(context) {
+      if (!this.isEditable()) return false;
+
+      return this.collection.database.url(context) + "/" + this.safeID();
+    },
+
+    isEditable: function() {
+      return this.docType() != "reduction";
+    },
+    safeID: function() {
+      return app.mixins.safeURLName(this.id);
+    },
+
+    prettyJSON: function() {
+      //var data = this.get("doc") ? this.get("doc") : this;
+      return JSON.stringify(this, null, "  ");
+    }
+  });
+
+  Documents.NewDoc = Documents.Doc.extend({
+    fetch: function() {
+      var uuid = new FauxtonAPI.UUID();
+      var deferred = this.deferred = $.Deferred();
+      var that = this;
+
+      uuid.fetch().done(function() {
+        that.set("_id", uuid.next());
+        deferred.resolve();
+      });
+
+      return deferred.promise();
+    }
+
+  });
+
+  Documents.AllDocs = Backbone.Collection.extend({
+    model: Documents.Doc,
+    documentation: function(){
+      return "docs";
+    },
+    initialize: function(_models, options) {
+      this.database = options.database;
+      this.params = options.params;
+      this.skipFirstItem = false;
+
+      this.on("remove",this.decrementTotalRows , this);
+    },
+
+    url: function(context) {
+      var query = "";
+      if (this.params) {
+        query = "?" + $.param(this.params);
+      }
+
+      if (context === 'app') {
+        return 'database/' + this.database.safeID() + "/_all_docs" + query;
+      } else if (context === "apiurl"){
+        return window.location.origin + "/" + this.database.safeID() + "/_all_docs" + query;
+      } else {
+        return app.host + "/" + this.database.safeID() + "/_all_docs" + query;
+      }
+    },
+
+    simple: function () {
+      var docs = this.map(function (item) {
+        return {
+          _id: item.id,
+          _rev: item.get('_rev'),
+        };
+      });
+
+      return new Documents.AllDocs(docs, {
+        database: this.database,
+        params: this.params
+      });
+    },
+
+    urlNextPage: function (num, lastId) {
+      if (!lastId) {
+        var doc = this.last();
+
+        if (doc) {
+          lastId = doc.id;
+        } else {
+          lastId = '';
+        }
+      }
+
+      this.params.startkey_docid = '"' + lastId + '"';
+      this.params.startkey = '"' + lastId + '"';
+      // when paginating forward, fetch 21 and don't show
+      // the first item as it was the last item in the previous list
+      this.params.limit = num + 1;
+      return this.url('app');
+    },
+
+    urlPreviousPage: function (num, params) {
+      if (params) { 
+        this.params = params;
+      } else {
+        this.params = {reduce: false};
+      }
+
+      this.params.limit = num;
+      return this.url('app'); 
+    },
+
+    totalRows: function() {
+      return this.viewMeta.total_rows || "unknown";
+    },
+
+    decrementTotalRows: function () {
+      if (this.viewMeta.total_rows) {
+        this.viewMeta.total_rows = this.viewMeta.total_rows -1;
+        this.trigger('totalRows:decrement');
+      }
+    },
+
+    updateSeq: function() {
+      return this.viewMeta.update_seq || false;
+    },
+
+    recordStart: function () {
+      if (this.viewMeta.offset === 0) {
+        return 1;
+      }
+
+      if (this.skipFirstItem) {
+        return this.viewMeta.offset + 2;
+      }
+
+      return this.viewMeta.offset + 1;
+    },
+
+    parse: function(resp) {
+      var rows = resp.rows;
+
+      this.viewMeta = {
+        total_rows: resp.total_rows,
+        offset: resp.offset,
+        update_seq: resp.update_seq
+      };
+
+      //Paginating, don't show first item as it was the last
+      //item in the previous page
+      if (this.skipFirstItem) {
+        rows = rows.splice(1);
+      }
+      return _.map(rows, function(row) {
+        return {
+          _id: row.id,
+          _rev: row.value.rev,
+          value: row.value,
+          key: row.key,
+          doc: row.doc || undefined
+        };
+      });
+    }
+  });
+
+  Documents.IndexCollection = Backbone.Collection.extend({
+    model: Documents.ViewRow,
+    documentation: function(){
+      return "docs";
+    },
+    initialize: function(_models, options) {
+      this.database = options.database;
+      this.params = _.extend({limit: 20, reduce: false}, options.params);
+      this.idxType = "_view";
+      this.view = options.view;
+      this.design = options.design.replace('_design/','');
+      this.skipFirstItem = false;
+    },
+
+    url: function(context) {
+      var query = "";
+      if (this.params) {
+        query = "?" + $.param(this.params);
+      }
+      
+      var startOfUrl = app.host;
+      if (context === 'app') {
+        startOfUrl = 'database';
+      } else if (context === "apiurl"){
+        startOfUrl = window.location.origin;
+      }
+      var design = app.mixins.safeURLName(this.design),
+          view = app.mixins.safeURLName(this.view);
+
+      var url = [startOfUrl, this.database.safeID(), "_design", design, this.idxType, view];
+      return url.join("/") + query;
+    },
+
+    urlNextPage: function (num, lastId) {
+      if (!lastId) {
+        lastDoc = this.last();
+      }
+
+      var id = lastDoc.get("id");
+      if (id) {
+        this.params.startkey_docid = id;
+      }
+
+      this.params.startkey =  JSON.stringify(lastDoc.get('key'));
+      this.params.limit = num + 1;
+      return this.url('app');
+    },
+
+     urlPreviousPage: function (num, params) {
+      if (params) { 
+        this.params = params;
+      } else {
+        this.params = {reduce: false};
+      }
+
+      this.params.limit = num;
+      return this.url('app');
+    },
+
+    recordStart: function () {
+      if (this.viewMeta.offset === 0) {
+        return 1;
+      }
+
+      if (this.skipFirstItem) {
+        return this.viewMeta.offset + 2;
+      }
+
+      return this.viewMeta.offset + 1;
+    },
+
+    totalRows: function() {
+      if (this.params.reduce) { return "unknown_reduce";}
+
+      return this.viewMeta.total_rows || "unknown";
+    },
+
+    updateSeq: function() {
+      return this.viewMeta.update_seq || false;
+    },
+
+    simple: function () {
+      var docs = this.map(function (item) {
+        return {
+          _id: item.id,
+          key: item.get('key'),
+          value: item.get('value')
+        };
+      });
+
+      return new Documents.IndexCollection(docs, {
+        database: this.database,
+        params: this.params,
+        view: this.view,
+        design: this.design
+      });
+    },
+
+    parse: function(resp) {
+      var rows = resp.rows;
+      this.endTime = new Date().getTime();
+      this.requestDuration = (this.endTime - this.startTime);
+
+      if (this.skipFirstItem) {
+        rows = rows.splice(1);
+      }
+
+      this.viewMeta = {
+        total_rows: resp.total_rows,
+        offset: resp.offset,
+        update_seq: resp.update_seq
+      };
+      return _.map(rows, function(row) {
+        return {
+          value: row.value,
+          key: row.key,
+          doc: row.doc,
+          id: row.id
+        };
+      });
+    },
+
+    buildAllDocs: function(){
+      this.fetch();
+    },
+
+    // We implement our own fetch to store the starttime so we that
+    // we can get the request duration
+    fetch: function () {
+      this.startTime = new Date().getTime();
+      return Backbone.Collection.prototype.fetch.call(this);
+    },
+
+    allDocs: function(){
+      return this.models;
+    },
+
+    // This is taken from futon.browse.js $.timeString
+    requestDurationInString: function () {
+      var ms, sec, min, h, timeString, milliseconds = this.requestDuration;
+
+      sec = Math.floor(milliseconds / 1000.0);
+      min = Math.floor(sec / 60.0);
+      sec = (sec % 60.0).toString();
+      if (sec.length < 2) {
+         sec = "0" + sec;
+      }
+
+      h = (Math.floor(min / 60.0)).toString();
+      if (h.length < 2) {
+        h = "0" + h;
+      }
+
+      min = (min % 60.0).toString();
+      if (min.length < 2) {
+        min = "0" + min;
+      }
+
+      timeString = h + ":" + min + ":" + sec;
+
+      ms = (milliseconds % 1000.0).toString();
+      while (ms.length < 3) {
+        ms = "0" + ms;
+      }
+      timeString += "." + ms;
+
+      return timeString;
+    }
+  });
+
+  
+  Documents.PouchIndexCollection = Backbone.Collection.extend({
+    model: Documents.ViewRow,
+    documentation: function(){
+      return "docs";
+    },
+    initialize: function(_models, options) {
+      this.database = options.database;
+      this.rows = options.rows;
+      this.view = options.view;
+      this.design = options.design.replace('_design/','');
+      this.params = _.extend({limit: 20, reduce: false}, options.params);
+      this.idxType = "_view";
+    },
+
+    url: function () {
+      return '';
+    },
+
+    simple: function () {
+      var docs = this.map(function (item) {
+        return {
+          _id: item.id,
+          key: item.get('key'),
+          value: item.get('value')
+        };
+      });
+
+      return new Documents.PouchIndexCollection(docs, {
+        database: this.database,
+        params: this.params,
+        view: this.view,
+        design: this.design,
+        rows: this.rows
+      });
+
+    },
+
+    fetch: function() {
+      var deferred = FauxtonAPI.Deferred();
+      this.reset(this.rows, {silent: true});
+
+      this.viewMeta = {
+        total_rows: this.rows.length,
+        offset: 0,
+        update_seq: false
+      };
+
+      deferred.resolve();
+      return deferred;
+    },
+
+    recordStart: function () {
+      return 1;
+    },
+
+    totalRows: function() {
+      return this.viewMeta.total_rows || "unknown";
+    },
+
+    updateSeq: function() {
+      return this.viewMeta.update_seq || false;
+    },
+
+    buildAllDocs: function(){
+      this.fetch();
+    },
+
+    allDocs: function(){
+      return this.models;
+    }
+  });
+
+
+
+  return Documents;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
new file mode 100644
index 0000000..d120feb
--- /dev/null
+++ b/app/addons/documents/routes.js
@@ -0,0 +1,409 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+
+       "api",
+
+       // Modules
+       "addons/documents/views",
+       "addons/databases/base"
+],
+
+function(app, FauxtonAPI, Documents, Databases) {
+
+  var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({
+    layout: "one_pane",
+    disableLoader: true,
+    selectedHeader: "Databases",
+    initialize: function(route, masterLayout, options) {
+      var databaseName = options[0];
+      this.docID = options[1]||'new';
+
+      this.database = this.database || new Databases.Model({id: databaseName});
+      this.doc = new Documents.Doc({
+        _id: this.docID
+      }, {
+        database: this.database
+      });
+
+      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
+        disableLoader: true,
+        selected: "code_editor",
+        model: this.doc
+      }));
+
+    },
+
+    routes: {
+      // We are hiding the field_editor for this first release
+      // "database/:database/:doc/field_editor": "field_editor",
+      "database/:database/:doc/code_editor": "code_editor",
+      "database/:database/:doc": "code_editor"
+    },
+
+    events: {
+      "route:reRenderDoc": "reRenderDoc",
+      "route:duplicateDoc": "duplicateDoc"
+    },
+
+    crumbs: function() {
+      return [
+        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
+        {"name": this.docID, "link": "#"}
+      ];
+    },
+
+    code_editor: function (database, doc) {
+      this.tabsView.updateSelected('code_editor');
+
+      this.docView = this.setView("#dashboard-content", new Documents.Views.Doc({
+        model: this.doc,
+        database: this.database
+      }));
+    },
+
+    reRenderDoc: function () {
+      this.docView.forceRender();
+    },
+
+    field_editor: function(events) {
+      this.tabsView.updateSelected('field_editor');
+      this.docView = this.setView("#dashboard-content", new Documents.Views.DocFieldEditor({
+        model: this.doc
+      }));
+    },
+
+    duplicateDoc: function (newId) {
+      var doc = this.doc,
+      docView = this.docView,
+      database = this.database;
+
+      doc.copy(newId).then(function () {
+        doc.set({_id: newId}); 
+        docView.forceRender();
+        FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.mixins.safeURLName(newId), {trigger: true});
+        FauxtonAPI.addNotification({
+          msg: "Document has been duplicated."
+        });
+
+      }, function (error) {
+        var errorMsg = "Could not duplicate document, reason: " + error.responseText + ".";
+        FauxtonAPI.addNotification({
+          msg: errorMsg,
+          type: "error"
+        });
+      });
+    },
+
+    apiUrl: function() {
+      return [this.doc.url("apiurl"), this.doc.documentation()];
+    }
+  });
+
+  var NewDocEditorRouteObject = DocEditorRouteObject.extend({
+    initialize: function (route, masterLayout, options) {
+      var databaseName = options[0];
+
+      this.database = this.database || new Databases.Model({id: databaseName});
+      this.doc = new Documents.NewDoc(null,{
+        database: this.database
+      });
+
+      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
+        selected: "code_editor",
+        model: this.doc
+      }));
+
+    },
+    crumbs: function() {
+      return [
+        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
+        {"name": "New", "link": "#"}
+      ];
+    },
+    routes: {
+      "database/:database/new": "code_editor"
+    },
+    selectedHeader: "Databases",
+
+  });
+
+  var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({
+    layout: "with_tabs_sidebar",
+    selectedHeader: "Databases",
+    routes: {
+      "database/:database/_all_docs(:extra)": "allDocs", 
+      "database/:database/_design/:ddoc/_view/:view": {
+        route: "viewFn",
+        roles: ['_admin']
+      },
+      "database/:database/new_view": "newViewEditor"
+    },
+
+    events: {
+      "route:updateAllDocs": "updateAllDocsFromView",
+      "route:updatePreviewDocs": "updateAllDocsFromPreview",
+      "route:reloadDesignDocs": "reloadDesignDocs",
+      "route:paginate": "paginate"
+    },
+
+    initialize: function (route, masterLayout, options) {
+      var docOptions = app.getParams();
+      docOptions.include_docs = true;
+
+      this.databaseName = options[0];
+
+      this.data = {
+        database: new Databases.Model({id:this.databaseName})
+      };
+
+      this.data.designDocs = new Documents.AllDocs(null, {
+        database: this.data.database,
+        params: {startkey: '"_design"',
+          endkey: '"_design1"',
+          include_docs: true}
+      });
+
+      this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar({
+        collection: this.data.designDocs,
+        database: this.data.database
+      }));
+    },
+
+    establish: function () {
+      return this.data.designDocs.fetch();
+    },
+
+    allDocs: function(databaseName, options) {
+      var docOptions = app.getParams(options);
+
+      this.data.database.buildAllDocs(docOptions);
+
+      if (docOptions.startkey && docOptions.startkey.indexOf('_design') > -1) {
+        this.sidebar.setSelectedTab('design-docs');
+      } else {
+        this.sidebar.setSelectedTab('all-docs');
+      }
+
+      if (this.viewEditor) { this.viewEditor.remove(); }
+
+      this.toolsView = this.setView("#dashboard-upper-menu", new Documents.Views.JumpToDoc({
+        database: this.data.database,
+        collection: this.data.database.allDocs
+      }));
+
+      this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({
+        database: this.data.database,
+        collection: this.data.database.allDocs,
+        params: docOptions
+      }));
+
+      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+        collection: this.data.database.allDocs
+      }));
+
+      this.crumbs = [
+        {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}
+      ];
+
+      this.apiUrl = [this.data.database.allDocs.url("apiurl"), this.data.database.allDocs.documentation() ];
+    },
+
+    viewFn: function (databaseName, ddoc, view) {
+      var params = app.getParams(),
+          decodeDdoc = decodeURIComponent(ddoc);
+
+      view = view.replace(/\?.*$/,'');
+
+      this.data.indexedDocs = new Documents.IndexCollection(null, {
+        database: this.data.database,
+        design: decodeDdoc,
+        view: view,
+        params: params
+      });
+
+      var ddocInfo = {
+        id: "_design/" + decodeDdoc,
+        currView: view,
+        designDocs: this.data.designDocs
+      };
+
+      this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.ViewEditor({
+        model: this.data.database,
+        ddocs: this.data.designDocs,
+        viewName: view,
+        params: params,
+        newView: false,
+        database: this.data.database,
+        ddocInfo: ddocInfo
+      }));
+
+      if (this.toolsView) { this.toolsView.remove(); }
+
+      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+        database: this.data.database,
+        collection: this.data.indexedDocs,
+        nestedView: Documents.Views.Row,
+        viewList: true,
+        ddocInfo: ddocInfo
+      }));
+
+      this.sidebar.setSelectedTab(app.mixins.removeSpecialCharacters(ddoc) + '_' + app.mixins.removeSpecialCharacters(view));
+
+      this.crumbs = function () {
+        return [
+          {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+        ];
+      };
+
+      this.apiUrl = [this.data.indexedDocs.url("apiurl"), "docs"];
+    },
+
+    newViewEditor: function () {
+      var params = app.getParams();
+
+      if (this.toolsView) {
+        this.toolsView.remove();
+      }
+
+      this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.ViewEditor({
+        ddocs: this.data.designDocs,
+        params: params,
+        database: this.data.database,
+        newView: true
+      }));
+
+      this.sidebar.setSelectedTab('new-view');
+      this.crumbs = function () {
+        return [
+          {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+        ];
+      };
+    },
+
+    updateAllDocsFromView: function (event) {
+      var view = event.view,
+          docOptions = app.getParams(),
+          ddoc = event.ddoc;
+
+      this.documentsView && this.documentsView.remove();
+
+      if (event.allDocs) {
+        this.data.database.buildAllDocs(docOptions);
+        this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+          collection: this.data.database.allDocs
+        }));
+        return;
+      }
+
+      this.data.indexedDocs = new Documents.IndexCollection(null, {
+        database: this.data.database,
+        design: ddoc,
+        view: view,
+        params: app.getParams()
+      });
+
+      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+        database: this.data.database,
+        collection: this.data.indexedDocs,
+        nestedView: Documents.Views.Row,
+        viewList: true
+      }));
+    },
+
+    updateAllDocsFromPreview: function (event) {
+      var view = event.view,
+      rows = event.rows,
+      ddoc = event.ddoc;
+
+      this.data.indexedDocs = new Documents.PouchIndexCollection(null, {
+        database: this.data.database,
+        design: ddoc,
+        view: view,
+        rows: rows
+      });
+
+      this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
+        database: this.data.database,
+        collection: this.data.indexedDocs,
+        nestedView: Documents.Views.Row,
+        viewList: true
+      }));
+    },
+
+    paginate: function (direction) {
+      _.extend(this.documentsView.collection.params, app.getParams());
+      this.documentsView.forceRender();
+      if (direction === 'next') {
+        this.documentsView.collection.skipFirstItem = true;
+      } else {
+        this.documentsView.collection.skipFirstItem = false;
+      }
+    },
+
+    reloadDesignDocs: function (event) {
+      this.sidebar.forceRender();
+
+      if (event && event.selectedTab) {
+        this.sidebar.setSelectedTab(event.selectedTab);
+      }
+    }
+
+  });
+
+  var ChangesRouteObject = FauxtonAPI.RouteObject.extend({
+    layout: "with_tabs",
+    selectedHeader: "Databases",
+    crumbs: function () {
+      return [
+        {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
+        {"name": "_changes", "link": "/_changes"}
+      ];
+    },
+
+    routes: {
+      "database/:database/_changes(:params)": "changes"
+    },
+
+    initialize: function (route, masterLayout, options) {
+      this.databaseName = options[0];
+      this.database = new Databases.Model({id: this.databaseName});
+
+      var docOptions = app.getParams();
+
+      this.database.buildChanges(docOptions);
+
+      this.setView("#tabs", new Documents.Views.Tabs({
+        collection: this.designDocs,
+        database: this.database,
+        active_id: 'changes'
+      }));
+    },
+
+    changes: function (event) {
+      this.setView("#dashboard-content", new Documents.Views.Changes({
+        model: this.database
+      }));
+    },
+
+    apiUrl: function() {
+      return [this.database.url("apiurl"), this.database.documentation()];
+    }
+
+  });
+
+  Documents.RouteObjects = [DocEditorRouteObject, NewDocEditorRouteObject, DocumentsRouteObject, ChangesRouteObject];
+
+  return Documents;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/advanced_options.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/advanced_options.html b/app/addons/documents/templates/advanced_options.html
new file mode 100644
index 0000000..8e96574
--- /dev/null
+++ b/app/addons/documents/templates/advanced_options.html
@@ -0,0 +1,97 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div class="errors-container"></div>
+<form class="view-query-update custom-inputs">
+  <div class="controls-group">
+    <div class="row-fluid">
+      <div class="controls controls-row">
+        <input name="key" class="span6" type="text" placeholder="Key">
+        <input name="keys" class="span6" type="text" placeholder="Keys">
+      </div>
+    </div>
+    <div class="row-fluid">
+      <div class="controls controls-row">
+        <input name="startkey" class="span6" type="text" placeholder="Start Key">
+        <input name="endkey" class="span6" type="text" placeholder="End Key">
+      </div>
+    </div>
+  </div>
+  <div class="controls-group">
+    <div class="row-fluid">
+      <div class="controls controls-row">
+        <div class="checkbox inline">  
+          <input id="check1" type="checkbox" name="include_docs" value="true">  
+          <label name="include_docs" for="check1">Include Docs</label>  
+          <% if (hasReduce) { %>
+          <input id="check2" name="reduce" type="checkbox" value="true">
+          <label for="check2">Reduce</label>  
+        </div> 
+        <label id="select1" class="drop-down inline">
+          Group Level:
+          <select id="select1" disabled name="group_level" class="input-small">
+            <option value="0">None</option>
+            <option value="1">1</option>
+            <option value="2">2</option>
+            <option value="3">3</option>
+            <option value="4">4</option>
+            <option value="5">5</option>
+            <option value="6">6</option>
+            <option value="7">7</option>
+            <option value="8">8</option>
+            <option value="9">9</option>
+            <option value="999" selected="selected">exact</option>
+          </select>
+        </label>
+        <% } else{ %>
+        </div>
+        <% } %>
+
+        <div class="checkbox inline">  
+          <input id="check3" name="stale" type="checkbox" value="ok">
+          <label for="check3">Stale</label>
+          <input id="check4" name="descending" type="checkbox" value="true">  
+          <label for="check4">Descending</label>  
+        </div> 
+        <label class="drop-down inline">
+          Limit:
+          <select name="limit" class="input-small">
+            <option>5</option>
+            <option selected="selected">10</option>
+            <option>25</option>
+            <option>50</option>
+            <option>100</option>
+          </select>
+        </label>
+        <div class="checkbox inline">  
+          <input id="check5" name="inclusive_end" type="checkbox" value="false">
+          <label for="check5">Disable Inclusive End</label>
+          <input id="check6" name="update_seq" type="checkbox" value="true">  
+          <label for="check6">Update Sequence</label>  
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="controls-group">
+    <div class="row-fluid">
+      <div id="button-options" class="controls controls-row">
+        <button type="submit" class="button green">Query</button>
+        <% if (showPreview) { %>
+        <button class="button btn-info preview">Browser Preview</button>
+        <% } %>
+      </div>
+    </div>
+  </div>
+</form>
+</div>
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/all_docs_item.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_item.html b/app/addons/documents/templates/all_docs_item.html
new file mode 100644
index 0000000..bfedaaa
--- /dev/null
+++ b/app/addons/documents/templates/all_docs_item.html
@@ -0,0 +1,26 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<td class="select"><input type="checkbox" class="row-select"></td>
+<td>
+  <div>
+    <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
+    <% if (doc.isEditable()) { %>
+      <div class="btn-group">
+        <a href="#<%= doc.url('web-index') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
+        <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
+      </div>
+    <% } %>
+  </div>
+</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/all_docs_layout.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_layout.html b/app/addons/documents/templates/all_docs_layout.html
new file mode 100644
index 0000000..526c200
--- /dev/null
+++ b/app/addons/documents/templates/all_docs_layout.html
@@ -0,0 +1,20 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<ul class="nav nav-tabs window-resizeable" id="db-views-tabs-nav">
+  <li><a id="toggle-query" class="fonticon-plus fonticon" href="#query" data-toggle="tab">Query Options</a></li>
+</ul>
+<div class="tab-content">
+  <div class="tab-pane" id="query">
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/all_docs_list.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_list.html b/app/addons/documents/templates/all_docs_list.html
new file mode 100644
index 0000000..335b040
--- /dev/null
+++ b/app/addons/documents/templates/all_docs_list.html
@@ -0,0 +1,43 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="view show">
+  <% if (!viewList) { %>
+    <div class="row">
+      <div class="btn-toolbar span6">
+        <button type="button" class="btn all" data-toggle="button">✓ All</button>
+        <button class="btn btn-small disabled bulk-delete"><i class="icon-trash"></i></button>
+        <% if (expandDocs) { %>
+        <button id="collapse" class="btn"><i class="icon-minus"></i> Collapse</button>
+        <% } else { %>
+        <button id="collapse" class="btn"><i class="icon-plus"></i> Expand</button>
+        <% } %>
+      </div>
+    </div>
+  <% } %>
+  <p>
+
+  <div id="item-numbers"> </div>
+
+  <% if (requestDuration) { %>
+    <span class="view-request-duration">
+    View request duration: <strong> <%= requestDuration %> </strong> 
+    </span>
+  <% } %>
+  </p>
+  <table class="all-docs table table-striped table-condensed">
+    <tbody></tbody>
+  </table>
+  <div id="documents-pagination"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/all_docs_number.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_number.html b/app/addons/documents/templates/all_docs_number.html
new file mode 100644
index 0000000..c4ea8f6
--- /dev/null
+++ b/app/addons/documents/templates/all_docs_number.html
@@ -0,0 +1,21 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<% if (totalRows === "unknown"){ %>
+  Showing 0 documents. <a href="#/database/<%=database%>/new"> Create your first document.</a>
+<% } else { %>
+  Showing <%=offset%> - <%= numModels %> of <%= totalRows %> rows
+<%}%>
+<% if (updateSeq) { %>
+  -- Update Sequence: <%= updateSeq %>
+<% } %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/changes.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/changes.html b/app/addons/documents/templates/changes.html
new file mode 100644
index 0000000..9408979
--- /dev/null
+++ b/app/addons/documents/templates/changes.html
@@ -0,0 +1,38 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<table id="changes-table" class="table">
+  <thead>
+    <th id="seq"> seq </th>
+    <th> id </th>
+    <th id="changes"> changes </th>
+    <th id="deleted"> deleted? </th>
+  </thead>
+  <tbody>
+  <% _.each(changes, function (change) { %>
+    <tr>
+      <td> <%= change.seq %> </td>
+      <% if (change.deleted) { %>
+        <td> <%= change.id %> </td>
+      <% } else { %>
+        <td> <a href="#<%= database.url('app') %>/<%= change.id %>"><%= change.id %></a> </td>
+      <% } %>
+        <td> 
+          <pre class="prettyprint">  <%- JSON.stringify({changes: change.changes, doc: change.doc}, null, " ") %> </pre>
+      </td>
+      <td><%= change.deleted ? "true" : "false" %></td>
+    </tr>
+  <% }); %>
+  </tbody>
+</table>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/ddoc_info.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/ddoc_info.html b/app/addons/documents/templates/ddoc_info.html
new file mode 100644
index 0000000..ed0aed6
--- /dev/null
+++ b/app/addons/documents/templates/ddoc_info.html
@@ -0,0 +1,28 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div>
+  <h2> Design Doc MetaData </h2>
+  <div class="row-fluid">
+	<% i=0; _.map(view_index, function (val, key) { %>
+		<% if(i%2==0){%>
+			<div class="row-fluid">
+		<% }; %>
+	    <div class="span6 well-item"><strong> <%= key %></strong> : <%= val %>  </div>
+	    <% if(i%2==1){%>
+			</div>
+		<% }; %>
+	  	<% ++i;
+	}); %>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/design_doc_selector.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/design_doc_selector.html b/app/addons/documents/templates/design_doc_selector.html
new file mode 100644
index 0000000..7bbe310
--- /dev/null
+++ b/app/addons/documents/templates/design_doc_selector.html
@@ -0,0 +1,35 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div class="span3">
+  <label for="ddoc">Save to Design Document <a href="<%=getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+  <select id="ddoc">
+    <optgroup label="Select a document">
+      <option value="new-doc">New document</option>
+      <% ddocs.each(function(ddoc) { %>
+      <% if (ddoc.id === ddocName) { %>
+      <option selected="selected" value="<%= ddoc.id %>"><%= ddoc.id %></option>
+      <% } else { %>
+      <option value="<%= ddoc.id %>"><%= ddoc.id %></option>
+      <% } %>
+      <% }); %>
+    </optgroup>
+  </select>
+</div>
+
+<div id="new-ddoc-section" class="span5" style="display:none">
+  <label class="control-label" for="new-ddoc"> _design/ </label>
+  <div class="controls">
+    <input type="text" id="new-ddoc" placeholder="newDesignDoc">
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/doc.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/doc.html b/app/addons/documents/templates/doc.html
new file mode 100644
index 0000000..10bbf8b
--- /dev/null
+++ b/app/addons/documents/templates/doc.html
@@ -0,0 +1,55 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div id="doc">
+  <div class="errors-container"></div>
+   
+<div class="row doc-editor-buttons"> 
+  <div class="span3">
+    <button class="save-doc button green btn-medium save fonticon-circle-check" type="button">Save</button>
+    <button class="button cancel-button gray btn-medium">Back to _all_docs</button>
+  </div>
+
+  <div class="span7">
+    <% if (attachments) { %>
+    <div class="btn-group">
+      <a class="button gray btn-medium dropdown-toggle btn" data-bypass="true" data-toggle="dropdown" href="#">
+        View Attachments
+        <span class="caret"></span>
+      </a>
+      <ul class="dropdown-menu">
+        <%_.each(attachments, function (att) { %>
+        <li>
+        <a href="<%= att.url %>" target="_blank"> <strong> <%= att.fileName %> </strong> -
+          <span> <%= att.contentType %>, <%= formatSize(att.size)%> </span>
+        </a>
+        </li>
+        <% }) %>
+      </ul>
+    </div>
+    <% } %> 
+    <button class="button gray btn-medium  upload"><i class="icon-circle-arrow-up"></i> Upload Attachment</button>
+    <button class="button gray btn-medium duplicate"><i class="icon-repeat"></i> Duplicate document</button>
+  </div>
+
+  <button class="button red btn-medium delete"><i class="icon-trash"></i></button>
+  </ul>
+
+<div id="upload-modal"> </div>
+<div id="duplicate-modal"> </div> 
+</div>
+
+  <div id="editor-container" class="doc-code"><%- JSON.stringify(doc.attributes, null, "  ") %></div>
+
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/doc_field_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/doc_field_editor.html b/app/addons/documents/templates/doc_field_editor.html
new file mode 100644
index 0000000..77d9278
--- /dev/null
+++ b/app/addons/documents/templates/doc_field_editor.html
@@ -0,0 +1,74 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div id="doc-field-editor">
+  <div class="tools">
+
+    <div class="btn-toolbar pull-left">
+      <button class="btn btn-small all">&#x2713; All</button>
+      <button class="btn btn-small disabled delete"><i class="icon-trash"></i> Delete field</button>
+      <button class="btn btn-small new" style="margin-left: 64px"><i class="icon-plus"></i> New field</button>
+    </div>
+    <div class="btn-toolbar pull-right">
+      <button class="btn btn-small cancel button cancel-button outlineGray fonticon-circle-x">Cancel</button>
+      <button class="btn btn-small save button green fonticon-circle-check">Save</button>
+    </div>
+  </div>
+
+  <div class="clearfix"></div>
+  <!-- <hr style="margin-top: 0"/> -->
+
+  <table class="table table-striped  table-condensed">
+    <thead>
+      <tr>
+        <th class="select">
+        </th>
+        <th>Key</th>
+        <th>Value</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr style="display:none">
+        <td class="select"><input type="checkbox" /></td>
+        <td class="key"><input type="text" class="input-large" value='' /></td>
+        <td class="value"><input type="text" class="input-xxlarge" value='' /></td>
+      </tr>
+      <% _.each(doc, function(value, key) { %>
+        <tr>
+          <td class="select"><input type="checkbox" /></td>
+          <td class="key">
+            <input type="text" class="input-large" name="doc[<%= key %>]" value="<%= key %>" />
+          </td>
+          <td class="value"><input type="text" class="input-xxlarge" value='<%= JSON.stringify(value) %>' /></td>
+        </tr>
+      <% }); %>
+        <tr>
+          <th colspan="3">
+            Attachments
+          </th>
+        </tr>
+      <%_.each(attachments, function (att) { %>
+        <tr>
+          <td class="select"><input type="checkbox" /></td>
+          <td colspan="2">
+            <a href="<%= att.url %>" target="_blank"> <%= att.fileName %> </a>
+            <span> <%= att.contentType %>, <%= formatSize(att.size)%> </span>
+          </td>
+        </tr>
+      <% }) %>
+    </tbody>
+  </table>
+  <a class="btn btn-small new" style="margin-left: 64px"><i class="icon-plus"></i> New field</a>
+
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/doc_field_editor_tabs.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/doc_field_editor_tabs.html b/app/addons/documents/templates/doc_field_editor_tabs.html
new file mode 100644
index 0000000..766647c
--- /dev/null
+++ b/app/addons/documents/templates/doc_field_editor_tabs.html
@@ -0,0 +1,19 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<!--<ul class="nav nav-tabs">
+  <li id="field_editor" class="<%= isSelectedClass('field_editor') %>"><a href="#<%= doc.url('app') %>/field_editor">Doc fields</a></li>
+  <li id="code_editor" class="<%= isSelectedClass('code_editor') %>"><a href="#<%= doc.url('app') %>/code_editor"><i class="icon-pencil"> </i> Code editor</a>
+  </li>
+</ul>-->

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/duplicate_doc_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/duplicate_doc_modal.html b/app/addons/documents/templates/duplicate_doc_modal.html
new file mode 100644
index 0000000..3f374b6
--- /dev/null
+++ b/app/addons/documents/templates/duplicate_doc_modal.html
@@ -0,0 +1,36 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="modal hide fade">
+  <div class="modal-header">
+    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+    <h3>Duplicate Document</h3>
+  </div>
+  <div class="modal-body">
+    <div id="modal-error" class="hide alert alert-error"/>
+    <form id="file-upload" class="form" method="post">
+      <p class="help-block">
+      Set new documents ID:
+      </p>
+      <input id="dup-id" type="text" class="input-xlarge">
+    </form>
+
+  </div>
+  <div class="modal-footer">
+    <a href="#" data-dismiss="modal" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
+    <a href="#" id="duplicate-btn" class="btn btn-primary button green save fonticon-circle-check">Duplicate</a>
+  </div>
+</div>
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/edit_tools.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/edit_tools.html b/app/addons/documents/templates/edit_tools.html
new file mode 100644
index 0000000..40c884d
--- /dev/null
+++ b/app/addons/documents/templates/edit_tools.html
@@ -0,0 +1,44 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="view show">
+  <p>
+    Showing 1-<%= numModels %> of <%= totalRows %> rows
+    <% if (updateSeq) { %>
+      -- Update Sequence: <%= updateSeq %>
+    <% } %>
+    <% if (requestDuration) { %>
+  <span class="view-request-duration">
+    View request duration: <strong> <%= requestDuration %> </strong> 
+   </span>
+   <% } %>
+  </p>
+  <table class="all-docs table table-striped table-condensed">
+    <tbody></tbody>
+  </table>
+  <!--
+  <div class="pagination pagination-centered">
+    <ul>
+      <li class="disabled"><a href="#">&laquo;</a></li>
+      <li class="active"><a href="#">1</a></li>
+      <li><a href="#">2</a></li>
+      <li><a href="#">3</a></li>
+      <li><a href="#">4</a></li>
+      <li><a href="#">5</a></li>
+      <li><a href="#">&raquo;</a></li>
+    </ul>
+  </div>
+  -->
+
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/index_menu_item.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_menu_item.html b/app/addons/documents/templates/index_menu_item.html
new file mode 100644
index 0000000..7ca9012
--- /dev/null
+++ b/app/addons/documents/templates/index_menu_item.html
@@ -0,0 +1,17 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<a id="<%= ddoc_clean %>_<%= index_clean %>" href="#database/<%= database_encoded %>/_design/<%= ddoc_encoded %>/_view/<%= index_encoded %>" class="toggle-view">
+  <%= ddoc %><span class="divider">/</span><%= index %>
+</a>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html
new file mode 100644
index 0000000..3835453
--- /dev/null
+++ b/app/addons/documents/templates/index_row_docular.html
@@ -0,0 +1,26 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<td class="select"><input type="checkbox"></td>
+<td>
+  <div>
+    <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
+    <% if (doc.isEditable()) { %>
+      <div class="btn-group">
+        <a href="#<%= doc.url('app') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
+        <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
+      </div>
+    <% } %>
+  </div>
+</td>


[20/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
made couchserver configurable via settings.json


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/60561d66
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/60561d66
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/60561d66

Branch: refs/heads/import-master
Commit: 60561d663d1b4727e193d459d23aadbf1a9d79bb
Parents: ae05109
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Tue Jan 14 14:27:27 2014 -0500
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Jan 15 09:01:19 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/60561d66/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index 49b52a4..cf70440 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -112,6 +112,28 @@ module.exports = function(grunt) {
     return settings.template || defaultSettings;
   }();
 
+  var couchserver_config  = function () {
+    // add a "couchserver" key to settings.json with JSON that matches the
+    // keys and values below (plus your customizations) to have Fauxton work
+    // against a remote CouchDB-compatible server.
+    var defaults = {
+      dist: './dist/debug/',
+      port: 8000,
+      proxy: {
+        target: {
+          host: 'localhost',
+          port: 5984,
+          https: false
+        },
+        // This sets the Host header in the proxy so that you can use external
+        // CouchDB instances and not have the Host set to 'localhost'
+        changeOrigin: true
+      }
+    };
+
+    return helper.readSettingsFile().couchserver || defaults;
+  }();
+
   grunt.initConfig({
 
     // The clean task ensures all files are removed from the dist/ directory so
@@ -223,20 +245,7 @@ module.exports = function(grunt) {
     },
 
     // Runs a proxy server for easier development, no need to keep deploying to couchdb
-    couchserver: {
-      dist: './dist/debug/',
-      port: 8000,
-      proxy: {
-        target: {
-          host: 'localhost',
-          port: 5984,
-          https: false
-        },
-        // This sets the Host header in the proxy so that you can use external
-        // CouchDB instances and not have the Host set to 'localhost'
-        changeOrigin: true
-      }
-    },
+    couchserver: couchserver_config,
 
     watch: {
       js: { 


[23/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix for view preview bug with _count


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/8a2f0c25
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/8a2f0c25
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/8a2f0c25

Branch: refs/heads/import-master
Commit: 8a2f0c2525da3edc1d6265a4e63f1cecabab49b7
Parents: 733c71e
Author: suelockwood <de...@apache.org>
Authored: Thu Jan 16 09:48:42 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Thu Jan 16 09:48:42 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js       | 6 +++---
 app/addons/pouchdb/pouch.collate.js | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/8a2f0c25/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 9902541..bde08f8 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1476,12 +1476,12 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
       var promise = FauxtonAPI.Deferred();
 
-      if (!this.database.allDocs) {
+      if (!this.database.allDocs || this.database.allDocs.params.include_docs !== true) {
         this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
         promise = this.database.allDocs.fetch();
-      } else {
+       } else {
         promise.resolve();
-      }
+       }
 
       promise.then(function () {
         params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/8a2f0c25/app/addons/pouchdb/pouch.collate.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/pouch.collate.js b/app/addons/pouchdb/pouch.collate.js
index 31e5650..8f15808 100644
--- a/app/addons/pouchdb/pouch.collate.js
+++ b/app/addons/pouchdb/pouch.collate.js
@@ -110,6 +110,6 @@ function(app, FauxtonAPI, Collate) {
 
   return Pouch;
 
-}).call(this);
+});
 
 


[28/52] [abbrv] Fauxton: Update jQuery to v1.11

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c67fc295/assets/js/libs/jquery.js
----------------------------------------------------------------------
diff --git a/assets/js/libs/jquery.js b/assets/js/libs/jquery.js
index c5c6482..3c88fa8 100644
--- a/assets/js/libs/jquery.js
+++ b/assets/js/libs/jquery.js
@@ -1,91 +1,83 @@
 /*!
- * jQuery JavaScript Library v1.10.2
+ * jQuery JavaScript Library v1.11.0
  * http://jquery.com/
  *
  * Includes Sizzle.js
  * http://sizzlejs.com/
  *
- * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
  * Released under the MIT license
  * http://jquery.org/license
  *
- * Date: 2013-07-03T13:48Z
+ * Date: 2014-01-23T21:02Z
  */
-(function( window, undefined ) {
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper window is present,
+		// execute the factory and get jQuery
+		// For environments that do not inherently posses a window with a document
+		// (such as Node.js), expose a jQuery-making factory as module.exports
+		// This accentuates the need for the creation of a real window
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
 
 // Can't do this because several apps including ASP.NET trace
 // the stack via arguments.caller.callee and Firefox dies if
 // you try to trace through "use strict" call chains. (#13335)
 // Support: Firefox 18+
-//"use strict";
-var
-	// The deferred used on DOM ready
-	readyList,
+//
 
-	// A central reference to the root jQuery(document)
-	rootjQuery,
+var deletedIds = [];
 
-	// Support: IE<10
-	// For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
-	core_strundefined = typeof undefined,
+var slice = deletedIds.slice;
 
-	// Use the correct document accordingly with window argument (sandbox)
-	location = window.location,
-	document = window.document,
-	docElem = document.documentElement,
+var concat = deletedIds.concat;
 
-	// Map over jQuery in case of overwrite
-	_jQuery = window.jQuery,
+var push = deletedIds.push;
 
-	// Map over the $ in case of overwrite
-	_$ = window.$,
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var trim = "".trim;
 
-	// [[Class]] -> type pairs
-	class2type = {},
+var support = {};
 
-	// List of deleted data cache ids, so we can reuse them
-	core_deletedIds = [],
 
-	core_version = "1.10.2",
 
-	// Save a reference to some core methods
-	core_concat = core_deletedIds.concat,
-	core_push = core_deletedIds.push,
-	core_slice = core_deletedIds.slice,
-	core_indexOf = core_deletedIds.indexOf,
-	core_toString = class2type.toString,
-	core_hasOwn = class2type.hasOwnProperty,
-	core_trim = core_version.trim,
+var
+	version = "1.11.0",
 
 	// Define a local copy of jQuery
 	jQuery = function( selector, context ) {
 		// The jQuery object is actually just the init constructor 'enhanced'
-		return new jQuery.fn.init( selector, context, rootjQuery );
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
 	},
 
-	// Used for matching numbers
-	core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
-
-	// Used for splitting on whitespace
-	core_rnotwhite = /\S+/g,
-
 	// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
 	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
 
-	// A simple way to check for HTML strings
-	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
-	// Strict HTML recognition (#11290: must start with <)
-	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
-
-	// Match a standalone tag
-	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
-
-	// JSON RegExp
-	rvalidchars = /^[\],:{}\s]*$/,
-	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
-	rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
-	rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
-
 	// Matches dashed string for camelizing
 	rmsPrefix = /^-ms-/,
 	rdashAlpha = /-([\da-z])/gi,
@@ -93,134 +85,13 @@ var
 	// Used by jQuery.camelCase as callback to replace()
 	fcamelCase = function( all, letter ) {
 		return letter.toUpperCase();
-	},
-
-	// The ready event handler
-	completed = function( event ) {
-
-		// readyState === "complete" is good enough for us to call the dom ready in oldIE
-		if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
-			detach();
-			jQuery.ready();
-		}
-	},
-	// Clean-up method for dom ready events
-	detach = function() {
-		if ( document.addEventListener ) {
-			document.removeEventListener( "DOMContentLoaded", completed, false );
-			window.removeEventListener( "load", completed, false );
-
-		} else {
-			document.detachEvent( "onreadystatechange", completed );
-			window.detachEvent( "onload", completed );
-		}
 	};
 
 jQuery.fn = jQuery.prototype = {
 	// The current version of jQuery being used
-	jquery: core_version,
+	jquery: version,
 
 	constructor: jQuery,
-	init: function( selector, context, rootjQuery ) {
-		var match, elem;
-
-		// HANDLE: $(""), $(null), $(undefined), $(false)
-		if ( !selector ) {
-			return this;
-		}
-
-		// Handle HTML strings
-		if ( typeof selector === "string" ) {
-			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
-				// Assume that strings that start and end with <> are HTML and skip the regex check
-				match = [ null, selector, null ];
-
-			} else {
-				match = rquickExpr.exec( selector );
-			}
-
-			// Match html or make sure no context is specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] ) {
-					context = context instanceof jQuery ? context[0] : context;
-
-					// scripts is true for back-compat
-					jQuery.merge( this, jQuery.parseHTML(
-						match[1],
-						context && context.nodeType ? context.ownerDocument || context : document,
-						true
-					) );
-
-					// HANDLE: $(html, props)
-					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
-						for ( match in context ) {
-							// Properties of context are called as methods if possible
-							if ( jQuery.isFunction( this[ match ] ) ) {
-								this[ match ]( context[ match ] );
-
-							// ...and otherwise set as attributes
-							} else {
-								this.attr( match, context[ match ] );
-							}
-						}
-					}
-
-					return this;
-
-				// HANDLE: $(#id)
-				} else {
-					elem = document.getElementById( match[2] );
-
-					// Check parentNode to catch when Blackberry 4.6 returns
-					// nodes that are no longer in the document #6963
-					if ( elem && elem.parentNode ) {
-						// Handle the case where IE and Opera return items
-						// by name instead of ID
-						if ( elem.id !== match[2] ) {
-							return rootjQuery.find( selector );
-						}
-
-						// Otherwise, we inject the element directly into the jQuery object
-						this.length = 1;
-						this[0] = elem;
-					}
-
-					this.context = document;
-					this.selector = selector;
-					return this;
-				}
-
-			// HANDLE: $(expr, $(...))
-			} else if ( !context || context.jquery ) {
-				return ( context || rootjQuery ).find( selector );
-
-			// HANDLE: $(expr, context)
-			// (which is just equivalent to: $(context).find(expr)
-			} else {
-				return this.constructor( context ).find( selector );
-			}
-
-		// HANDLE: $(DOMElement)
-		} else if ( selector.nodeType ) {
-			this.context = this[0] = selector;
-			this.length = 1;
-			return this;
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) ) {
-			return rootjQuery.ready( selector );
-		}
-
-		if ( selector.selector !== undefined ) {
-			this.selector = selector.selector;
-			this.context = selector.context;
-		}
-
-		return jQuery.makeArray( selector, this );
-	},
 
 	// Start with an empty selector
 	selector: "",
@@ -229,19 +100,19 @@ jQuery.fn = jQuery.prototype = {
 	length: 0,
 
 	toArray: function() {
-		return core_slice.call( this );
+		return slice.call( this );
 	},
 
 	// Get the Nth element in the matched element set OR
 	// Get the whole matched element set as a clean array
 	get: function( num ) {
-		return num == null ?
+		return num != null ?
 
 			// Return a 'clean' array
-			this.toArray() :
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
 
 			// Return just the object
-			( num < 0 ? this[ this.length + num ] : this[ num ] );
+			slice.call( this );
 	},
 
 	// Take an array of elements and push it onto the stack
@@ -266,15 +137,14 @@ jQuery.fn = jQuery.prototype = {
 		return jQuery.each( this, callback, args );
 	},
 
-	ready: function( fn ) {
-		// Add the callback
-		jQuery.ready.promise().done( fn );
-
-		return this;
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
 	},
 
 	slice: function() {
-		return this.pushStack( core_slice.apply( this, arguments ) );
+		return this.pushStack( slice.apply( this, arguments ) );
 	},
 
 	first: function() {
@@ -291,26 +161,17 @@ jQuery.fn = jQuery.prototype = {
 		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
 	},
 
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function( elem, i ) {
-			return callback.call( elem, i, elem );
-		}));
-	},
-
 	end: function() {
 		return this.prevObject || this.constructor(null);
 	},
 
 	// For internal use only.
 	// Behaves like an Array's method, not like a jQuery method.
-	push: core_push,
-	sort: [].sort,
-	splice: [].splice
+	push: push,
+	sort: deletedIds.sort,
+	splice: deletedIds.splice
 };
 
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
 jQuery.extend = jQuery.fn.extend = function() {
 	var src, copyIsArray, copy, name, options, clone,
 		target = arguments[0] || {},
@@ -321,9 +182,10 @@ jQuery.extend = jQuery.fn.extend = function() {
 	// Handle a deep copy situation
 	if ( typeof target === "boolean" ) {
 		deep = target;
-		target = arguments[1] || {};
+
 		// skip the boolean and the target
-		i = 2;
+		target = arguments[ i ] || {};
+		i++;
 	}
 
 	// Handle case when target is a string or something (possible in deep copy)
@@ -332,9 +194,9 @@ jQuery.extend = jQuery.fn.extend = function() {
 	}
 
 	// extend jQuery itself if only one argument is passed
-	if ( length === i ) {
+	if ( i === length ) {
 		target = this;
-		--i;
+		i--;
 	}
 
 	for ( ; i < length; i++ ) {
@@ -377,66 +239,16 @@ jQuery.extend = jQuery.fn.extend = function() {
 
 jQuery.extend({
 	// Unique for each copy of jQuery on the page
-	// Non-digits removed to match rinlinejQuery
-	expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
-
-	noConflict: function( deep ) {
-		if ( window.$ === jQuery ) {
-			window.$ = _$;
-		}
-
-		if ( deep && window.jQuery === jQuery ) {
-			window.jQuery = _jQuery;
-		}
-
-		return jQuery;
-	},
-
-	// Is the DOM ready to be used? Set to true once it occurs.
-	isReady: false,
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
 
-	// A counter to track how many items to wait for before
-	// the ready event fires. See #6781
-	readyWait: 1,
+	// Assume jQuery is ready without the ready module
+	isReady: true,
 
-	// Hold (or release) the ready event
-	holdReady: function( hold ) {
-		if ( hold ) {
-			jQuery.readyWait++;
-		} else {
-			jQuery.ready( true );
-		}
+	error: function( msg ) {
+		throw new Error( msg );
 	},
 
-	// Handle when the DOM is ready
-	ready: function( wait ) {
-
-		// Abort if there are pending holds or we're already ready
-		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
-			return;
-		}
-
-		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
-		if ( !document.body ) {
-			return setTimeout( jQuery.ready );
-		}
-
-		// Remember that the DOM is ready
-		jQuery.isReady = true;
-
-		// If a normal DOM Ready event fired, decrement, and wait if need be
-		if ( wait !== true && --jQuery.readyWait > 0 ) {
-			return;
-		}
-
-		// If there are functions bound, to execute
-		readyList.resolveWith( document, [ jQuery ] );
-
-		// Trigger any bound ready events
-		if ( jQuery.fn.trigger ) {
-			jQuery( document ).trigger("ready").off("ready");
-		}
-	},
+	noop: function() {},
 
 	// See test/unit/core.js for details concerning isFunction.
 	// Since version 1.3, DOM methods and functions like alert
@@ -455,16 +267,18 @@ jQuery.extend({
 	},
 
 	isNumeric: function( obj ) {
-		return !isNaN( parseFloat(obj) ) && isFinite( obj );
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		return obj - parseFloat( obj ) >= 0;
 	},
 
-	type: function( obj ) {
-		if ( obj == null ) {
-			return String( obj );
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
 		}
-		return typeof obj === "object" || typeof obj === "function" ?
-			class2type[ core_toString.call(obj) ] || "object" :
-			typeof obj;
+		return true;
 	},
 
 	isPlainObject: function( obj ) {
@@ -480,8 +294,8 @@ jQuery.extend({
 		try {
 			// Not own constructor property must be Object
 			if ( obj.constructor &&
-				!core_hasOwn.call(obj, "constructor") &&
-				!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
 				return false;
 			}
 		} catch ( e ) {
@@ -491,9 +305,9 @@ jQuery.extend({
 
 		// Support: IE<9
 		// Handle iteration over inherited properties before own properties.
-		if ( jQuery.support.ownLast ) {
+		if ( support.ownLast ) {
 			for ( key in obj ) {
-				return core_hasOwn.call( obj, key );
+				return hasOwn.call( obj, key );
 			}
 		}
 
@@ -501,135 +315,48 @@ jQuery.extend({
 		// if last one is own, then all properties are own.
 		for ( key in obj ) {}
 
-		return key === undefined || core_hasOwn.call( obj, key );
+		return key === undefined || hasOwn.call( obj, key );
 	},
 
-	isEmptyObject: function( obj ) {
-		var name;
-		for ( name in obj ) {
-			return false;
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
 		}
-		return true;
-	},
-
-	error: function( msg ) {
-		throw new Error( msg );
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
 	},
 
-	// data: string of html
-	// context (optional): If specified, the fragment will be created in this context, defaults to document
-	// keepScripts (optional): If true, will include scripts passed in the html string
-	parseHTML: function( data, context, keepScripts ) {
-		if ( !data || typeof data !== "string" ) {
-			return null;
-		}
-		if ( typeof context === "boolean" ) {
-			keepScripts = context;
-			context = false;
-		}
-		context = context || document;
-
-		var parsed = rsingleTag.exec( data ),
-			scripts = !keepScripts && [];
-
-		// Single tag
-		if ( parsed ) {
-			return [ context.createElement( parsed[1] ) ];
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && jQuery.trim( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
 		}
+	},
 
-		parsed = jQuery.buildFragment( [ data ], context, scripts );
-		if ( scripts ) {
-			jQuery( scripts ).remove();
-		}
-		return jQuery.merge( [], parsed.childNodes );
+	// Convert dashed to camelCase; used by the css and data modules
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
 	},
 
-	parseJSON: function( data ) {
-		// Attempt to parse using the native JSON parser first
-		if ( window.JSON && window.JSON.parse ) {
-			return window.JSON.parse( data );
-		}
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
 
-		if ( data === null ) {
-			return data;
-		}
-
-		if ( typeof data === "string" ) {
-
-			// Make sure leading/trailing whitespace is removed (IE can't handle it)
-			data = jQuery.trim( data );
-
-			if ( data ) {
-				// Make sure the incoming data is actual JSON
-				// Logic borrowed from http://json.org/json2.js
-				if ( rvalidchars.test( data.replace( rvalidescape, "@" )
-					.replace( rvalidtokens, "]" )
-					.replace( rvalidbraces, "")) ) {
-
-					return ( new Function( "return " + data ) )();
-				}
-			}
-		}
-
-		jQuery.error( "Invalid JSON: " + data );
-	},
-
-	// Cross-browser xml parsing
-	parseXML: function( data ) {
-		var xml, tmp;
-		if ( !data || typeof data !== "string" ) {
-			return null;
-		}
-		try {
-			if ( window.DOMParser ) { // Standard
-				tmp = new DOMParser();
-				xml = tmp.parseFromString( data , "text/xml" );
-			} else { // IE
-				xml = new ActiveXObject( "Microsoft.XMLDOM" );
-				xml.async = "false";
-				xml.loadXML( data );
-			}
-		} catch( e ) {
-			xml = undefined;
-		}
-		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
-			jQuery.error( "Invalid XML: " + data );
-		}
-		return xml;
-	},
-
-	noop: function() {},
-
-	// Evaluates a script in a global context
-	// Workarounds based on findings by Jim Driscoll
-	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
-	globalEval: function( data ) {
-		if ( data && jQuery.trim( data ) ) {
-			// We use execScript on Internet Explorer
-			// We use an anonymous function so that context is window
-			// rather than jQuery in Firefox
-			( window.execScript || function( data ) {
-				window[ "eval" ].call( window, data );
-			} )( data );
-		}
-	},
-
-	// Convert dashed to camelCase; used by the css and data modules
-	// Microsoft forgot to hump their vendor prefix (#9572)
-	camelCase: function( string ) {
-		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
-	},
-
-	// args is for internal usage only
-	each: function( obj, callback, args ) {
-		var value,
-			i = 0,
-			length = obj.length,
-			isArray = isArraylike( obj );
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
 
 		if ( args ) {
 			if ( isArray ) {
@@ -675,11 +402,11 @@ jQuery.extend({
 	},
 
 	// Use native String.trim function wherever possible
-	trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
+	trim: trim && !trim.call("\uFEFF\xA0") ?
 		function( text ) {
 			return text == null ?
 				"" :
-				core_trim.call( text );
+				trim.call( text );
 		} :
 
 		// Otherwise use our own trimming functionality
@@ -700,7 +427,7 @@ jQuery.extend({
 					[ arr ] : arr
 				);
 			} else {
-				core_push.call( ret, arr );
+				push.call( ret, arr );
 			}
 		}
 
@@ -711,8 +438,8 @@ jQuery.extend({
 		var len;
 
 		if ( arr ) {
-			if ( core_indexOf ) {
-				return core_indexOf.call( arr, elem, i );
+			if ( indexOf ) {
+				return indexOf.call( arr, elem, i );
 			}
 
 			len = arr.length;
@@ -730,15 +457,17 @@ jQuery.extend({
 	},
 
 	merge: function( first, second ) {
-		var l = second.length,
-			i = first.length,
-			j = 0;
+		var len = +second.length,
+			j = 0,
+			i = first.length;
 
-		if ( typeof l === "number" ) {
-			for ( ; j < l; j++ ) {
-				first[ i++ ] = second[ j ];
-			}
-		} else {
+		while ( j < len ) {
+			first[ i++ ] = second[ j++ ];
+		}
+
+		// Support: IE<9
+		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+		if ( len !== len ) {
 			while ( second[j] !== undefined ) {
 				first[ i++ ] = second[ j++ ];
 			}
@@ -749,23 +478,23 @@ jQuery.extend({
 		return first;
 	},
 
-	grep: function( elems, callback, inv ) {
-		var retVal,
-			ret = [],
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
 			i = 0,
-			length = elems.length;
-		inv = !!inv;
+			length = elems.length,
+			callbackExpect = !invert;
 
 		// Go through the array, only saving the items
 		// that pass the validator function
 		for ( ; i < length; i++ ) {
-			retVal = !!callback( elems[ i ], i );
-			if ( inv !== retVal ) {
-				ret.push( elems[ i ] );
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
 			}
 		}
 
-		return ret;
+		return matches;
 	},
 
 	// arg is for internal usage only
@@ -776,13 +505,13 @@ jQuery.extend({
 			isArray = isArraylike( elems ),
 			ret = [];
 
-		// Go through the array, translating each of the items to their
+		// Go through the array, translating each of the items to their new values
 		if ( isArray ) {
 			for ( ; i < length; i++ ) {
 				value = callback( elems[ i ], i, arg );
 
 				if ( value != null ) {
-					ret[ ret.length ] = value;
+					ret.push( value );
 				}
 			}
 
@@ -792,13 +521,13 @@ jQuery.extend({
 				value = callback( elems[ i ], i, arg );
 
 				if ( value != null ) {
-					ret[ ret.length ] = value;
+					ret.push( value );
 				}
 			}
 		}
 
 		// Flatten any nested arrays
-		return core_concat.apply( [], ret );
+		return concat.apply( [], ret );
 	},
 
 	// A global GUID counter for objects
@@ -822,9 +551,9 @@ jQuery.extend({
 		}
 
 		// Simulated bind
-		args = core_slice.call( arguments, 2 );
+		args = slice.call( arguments, 2 );
 		proxy = function() {
-			return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
 		};
 
 		// Set the guid of unique handler to the same of original handler, so it can be removed
@@ -833,148 +562,15 @@ jQuery.extend({
 		return proxy;
 	},
 
-	// Multifunctional method to get and set values of a collection
-	// The value/s can optionally be executed if it's a function
-	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
-		var i = 0,
-			length = elems.length,
-			bulk = key == null;
-
-		// Sets many values
-		if ( jQuery.type( key ) === "object" ) {
-			chainable = true;
-			for ( i in key ) {
-				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
-			}
-
-		// Sets one value
-		} else if ( value !== undefined ) {
-			chainable = true;
-
-			if ( !jQuery.isFunction( value ) ) {
-				raw = true;
-			}
-
-			if ( bulk ) {
-				// Bulk operations run against the entire set
-				if ( raw ) {
-					fn.call( elems, value );
-					fn = null;
-
-				// ...except when executing function values
-				} else {
-					bulk = fn;
-					fn = function( elem, key, value ) {
-						return bulk.call( jQuery( elem ), value );
-					};
-				}
-			}
-
-			if ( fn ) {
-				for ( ; i < length; i++ ) {
-					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
-				}
-			}
-		}
-
-		return chainable ?
-			elems :
-
-			// Gets
-			bulk ?
-				fn.call( elems ) :
-				length ? fn( elems[0], key ) : emptyGet;
-	},
-
 	now: function() {
-		return ( new Date() ).getTime();
+		return +( new Date() );
 	},
 
-	// A method for quickly swapping in/out CSS properties to get correct calculations.
-	// Note: this method belongs to the css module but it's needed here for the support module.
-	// If support gets modularized, this method should be moved back to the css module.
-	swap: function( elem, options, callback, args ) {
-		var ret, name,
-			old = {};
-
-		// Remember the old values, and insert the new ones
-		for ( name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		ret = callback.apply( elem, args || [] );
-
-		// Revert the old values
-		for ( name in options ) {
-			elem.style[ name ] = old[ name ];
-		}
-
-		return ret;
-	}
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
 });
 
-jQuery.ready.promise = function( obj ) {
-	if ( !readyList ) {
-
-		readyList = jQuery.Deferred();
-
-		// Catch cases where $(document).ready() is called after the browser event has already occurred.
-		// we once tried to use readyState "interactive" here, but it caused issues like the one
-		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
-		if ( document.readyState === "complete" ) {
-			// Handle it asynchronously to allow scripts the opportunity to delay ready
-			setTimeout( jQuery.ready );
-
-		// Standards-based browsers support DOMContentLoaded
-		} else if ( document.addEventListener ) {
-			// Use the handy event callback
-			document.addEventListener( "DOMContentLoaded", completed, false );
-
-			// A fallback to window.onload, that will always work
-			window.addEventListener( "load", completed, false );
-
-		// If IE event model is used
-		} else {
-			// Ensure firing before onload, maybe late but safe also for iframes
-			document.attachEvent( "onreadystatechange", completed );
-
-			// A fallback to window.onload, that will always work
-			window.attachEvent( "onload", completed );
-
-			// If IE and not a frame
-			// continually check to see if the document is ready
-			var top = false;
-
-			try {
-				top = window.frameElement == null && document.documentElement;
-			} catch(e) {}
-
-			if ( top && top.doScroll ) {
-				(function doScrollCheck() {
-					if ( !jQuery.isReady ) {
-
-						try {
-							// Use the trick by Diego Perini
-							// http://javascript.nwbox.com/IEContentLoaded/
-							top.doScroll("left");
-						} catch(e) {
-							return setTimeout( doScrollCheck, 50 );
-						}
-
-						// detach all dom ready events
-						detach();
-
-						// and execute any waiting functions
-						jQuery.ready();
-					}
-				})();
-			}
-		}
-	}
-	return readyList.promise( obj );
-};
-
 // Populate the class2type map
 jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
 	class2type[ "[object " + name + "]" ] = name.toLowerCase();
@@ -984,7 +580,7 @@ function isArraylike( obj ) {
 	var length = obj.length,
 		type = jQuery.type( obj );
 
-	if ( jQuery.isWindow( obj ) ) {
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
 		return false;
 	}
 
@@ -992,34 +588,31 @@ function isArraylike( obj ) {
 		return true;
 	}
 
-	return type === "array" || type !== "function" &&
-		( length === 0 ||
-		typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
 }
-
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
+var Sizzle =
 /*!
- * Sizzle CSS Selector Engine v1.10.2
+ * Sizzle CSS Selector Engine v1.10.16
  * http://sizzlejs.com/
  *
  * Copyright 2013 jQuery Foundation, Inc. and other contributors
  * Released under the MIT license
  * http://jquery.org/license
  *
- * Date: 2013-07-03
+ * Date: 2014-01-13
  */
-(function( window, undefined ) {
+(function( window ) {
 
 var i,
 	support,
-	cachedruns,
 	Expr,
 	getText,
 	isXML,
 	compile,
 	outermostContext,
 	sortInput,
+	hasDuplicate,
 
 	// Local document vars
 	setDocument,
@@ -1039,11 +632,9 @@ var i,
 	classCache = createCache(),
 	tokenCache = createCache(),
 	compilerCache = createCache(),
-	hasDuplicate = false,
 	sortOrder = function( a, b ) {
 		if ( a === b ) {
 			hasDuplicate = true;
-			return 0;
 		}
 		return 0;
 	},
@@ -1103,8 +694,7 @@ var i,
 	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
 	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
 
-	rsibling = new RegExp( whitespace + "*[+~]" ),
-	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
 
 	rpseudo = new RegExp( pseudos ),
 	ridentifier = new RegExp( "^" + identifier + "$" ),
@@ -1125,14 +715,15 @@ var i,
 			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
 	},
 
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
 	rnative = /^[^{]+\{\s*\[native \w/,
 
 	// Easily-parseable/retrievable ID or TAG or CLASS selectors
 	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
 
-	rinputs = /^(?:input|select|textarea|button)$/i,
-	rheader = /^h\d$/i,
-
+	rsibling = /[+~]/,
 	rescape = /'|\\/g,
 
 	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
@@ -1144,8 +735,8 @@ var i,
 		// Workaround erroneous numeric interpretation of +"0x"
 		return high !== high || escapedWhitespace ?
 			escaped :
-			// BMP codepoint
 			high < 0 ?
+				// BMP codepoint
 				String.fromCharCode( high + 0x10000 ) :
 				// Supplemental Plane codepoint (surrogate pair)
 				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
@@ -1209,7 +800,7 @@ function Sizzle( selector, context, results, seed ) {
 				if ( nodeType === 9 ) {
 					elem = context.getElementById( m );
 					// Check parentNode to catch when Blackberry 4.6 returns
-					// nodes that are no longer in the document #6963
+					// nodes that are no longer in the document (jQuery #6963)
 					if ( elem && elem.parentNode ) {
 						// Handle the case where IE, Opera, and Webkit return items
 						// by name instead of ID
@@ -1265,7 +856,7 @@ function Sizzle( selector, context, results, seed ) {
 				while ( i-- ) {
 					groups[i] = nid + toSelector( groups[i] );
 				}
-				newContext = rsibling.test( selector ) && context.parentNode || context;
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
 				newSelector = groups.join(",");
 			}
 
@@ -1300,11 +891,11 @@ function createCache() {
 
 	function cache( key, value ) {
 		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
-		if ( keys.push( key += " " ) > Expr.cacheLength ) {
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
 			// Only keep the most recent entries
 			delete cache[ keys.shift() ];
 		}
-		return (cache[ key ] = value);
+		return (cache[ key + " " ] = value);
 	}
 	return cache;
 }
@@ -1427,8 +1018,21 @@ function createPositionalPseudo( fn ) {
 }
 
 /**
- * Detect xml
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== strundefined && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
  * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
  */
 isXML = Sizzle.isXML = function( elem ) {
 	// documentElement is verified for cases where it doesn't yet exist
@@ -1437,16 +1041,14 @@ isXML = Sizzle.isXML = function( elem ) {
 	return documentElement ? documentElement.nodeName !== "HTML" : false;
 };
 
-// Expose support vars for convenience
-support = Sizzle.support = {};
-
 /**
  * Sets document-related variables once based on the current document
  * @param {Element|Object} [doc] An element or document object to use to set the document
  * @returns {Object} Returns the current document
  */
 setDocument = Sizzle.setDocument = function( node ) {
-	var doc = node ? node.ownerDocument || node : preferredDoc,
+	var hasCompare,
+		doc = node ? node.ownerDocument || node : preferredDoc,
 		parent = doc.defaultView;
 
 	// If no document and documentElement is available, return
@@ -1465,10 +1067,17 @@ setDocument = Sizzle.setDocument = function( node ) {
 	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
 	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
 	// IE6-8 do not support the defaultView property so parent will be undefined
-	if ( parent && parent.attachEvent && parent !== parent.top ) {
-		parent.attachEvent( "onbeforeunload", function() {
-			setDocument();
-		});
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", function() {
+				setDocument();
+			}, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", function() {
+				setDocument();
+			});
+		}
 	}
 
 	/* Attributes
@@ -1491,7 +1100,7 @@ setDocument = Sizzle.setDocument = function( node ) {
 	});
 
 	// Check if getElementsByClassName can be trusted
-	support.getElementsByClassName = assert(function( div ) {
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
 		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
 
 		// Support: Safari<4
@@ -1598,7 +1207,13 @@ setDocument = Sizzle.setDocument = function( node ) {
 			// setting a boolean content attribute,
 			// since its presence should be enough
 			// http://bugs.jquery.com/ticket/12359
-			div.innerHTML = "<select><option selected=''></option></select>";
+			div.innerHTML = "<select t=''><option selected=''></option></select>";
+
+			// Support: IE8, Opera 10-12
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			if ( div.querySelectorAll("[t^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
 
 			// Support: IE8
 			// Boolean attributes and "value" are not treated correctly
@@ -1615,18 +1230,16 @@ setDocument = Sizzle.setDocument = function( node ) {
 		});
 
 		assert(function( div ) {
-
-			// Support: Opera 10-12/IE8
-			// ^= $= *= and empty values
-			// Should not select anything
 			// Support: Windows 8 Native Apps
-			// The type attribute is restricted during .innerHTML assignment
+			// The type and name attributes are restricted during .innerHTML assignment
 			var input = doc.createElement("input");
 			input.setAttribute( "type", "hidden" );
-			div.appendChild( input ).setAttribute( "t", "" );
+			div.appendChild( input ).setAttribute( "name", "D" );
 
-			if ( div.querySelectorAll("[t^='']").length ) {
-				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
 			}
 
 			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
@@ -1663,11 +1276,12 @@ setDocument = Sizzle.setDocument = function( node ) {
 
 	/* Contains
 	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
 
 	// Element contains another
 	// Purposefully does not implement inclusive descendent
 	// As in, an element does not contain itself
-	contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
+	contains = hasCompare || rnative.test( docElem.contains ) ?
 		function( a, b ) {
 			var adown = a.nodeType === 9 ? a.documentElement : a,
 				bup = b && b.parentNode;
@@ -1692,7 +1306,7 @@ setDocument = Sizzle.setDocument = function( node ) {
 	---------------------------------------------------------------------- */
 
 	// Document order sorting
-	sortOrder = docElem.compareDocumentPosition ?
+	sortOrder = hasCompare ?
 	function( a, b ) {
 
 		// Flag for duplicate removal
@@ -1701,34 +1315,46 @@ setDocument = Sizzle.setDocument = function( node ) {
 			return 0;
 		}
 
-		var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
-
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
 		if ( compare ) {
-			// Disconnected nodes
-			if ( compare & 1 ||
-				(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+			return compare;
+		}
 
-				// Choose the first element that is related to our preferred document
-				if ( a === doc || contains(preferredDoc, a) ) {
-					return -1;
-				}
-				if ( b === doc || contains(preferredDoc, b) ) {
-					return 1;
-				}
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
 
-				// Maintain original order
-				return sortInput ?
-					( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
-					0;
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
 			}
 
-			return compare & 4 ? -1 : 1;
+			// Maintain original order
+			return sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
 		}
 
-		// Not directly comparable, sort on existence of method
-		return a.compareDocumentPosition ? -1 : 1;
+		return compare & 4 ? -1 : 1;
 	} :
 	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
 		var cur,
 			i = 0,
 			aup = a.parentNode,
@@ -1736,13 +1362,8 @@ setDocument = Sizzle.setDocument = function( node ) {
 			ap = [ a ],
 			bp = [ b ];
 
-		// Exit early if the nodes are identical
-		if ( a === b ) {
-			hasDuplicate = true;
-			return 0;
-
 		// Parentless nodes are either documents or disconnected
-		} else if ( !aup || !bup ) {
+		if ( !aup || !bup ) {
 			return a === doc ? -1 :
 				b === doc ? 1 :
 				aup ? -1 :
@@ -1837,13 +1458,13 @@ Sizzle.attr = function( elem, name ) {
 			fn( elem, name, !documentIsHTML ) :
 			undefined;
 
-	return val === undefined ?
+	return val !== undefined ?
+		val :
 		support.attributes || !documentIsHTML ?
 			elem.getAttribute( name ) :
 			(val = elem.getAttributeNode(name)) && val.specified ?
 				val.value :
-				null :
-		val;
+				null;
 };
 
 Sizzle.error = function( msg ) {
@@ -1876,6 +1497,10 @@ Sizzle.uniqueSort = function( results ) {
 		}
 	}
 
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
 	return results;
 };
 
@@ -1891,13 +1516,13 @@ getText = Sizzle.getText = function( elem ) {
 
 	if ( !nodeType ) {
 		// If no nodeType, this is expected to be an array
-		for ( ; (node = elem[i]); i++ ) {
+		while ( (node = elem[i++]) ) {
 			// Do not traverse comment nodes
 			ret += getText( node );
 		}
 	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
 		// Use textContent for elements
-		// innerText usage removed for consistency of new lines (see #11153)
+		// innerText usage removed for consistency of new lines (jQuery #11153)
 		if ( typeof elem.textContent === "string" ) {
 			return elem.textContent;
 		} else {
@@ -2294,12 +1919,11 @@ Expr = Sizzle.selectors = {
 		// Contents
 		"empty": function( elem ) {
 			// http://www.w3.org/TR/selectors/#empty-pseudo
-			// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
-			//   not comment, processing instructions, or others
-			// Thanks to Diego Perini for the nodeName shortcut
-			//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
 			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
-				if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+				if ( elem.nodeType < 6 ) {
 					return false;
 				}
 			}
@@ -2326,11 +1950,12 @@ Expr = Sizzle.selectors = {
 
 		"text": function( elem ) {
 			var attr;
-			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
-			// use getAttribute instead to test this case
 			return elem.nodeName.toLowerCase() === "input" &&
 				elem.type === "text" &&
-				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
 		},
 
 		// Position-in-collection
@@ -2416,7 +2041,7 @@ function tokenize( selector, parseOnly ) {
 				// Don't consume trailing commas as valid
 				soFar = soFar.slice( match[0].length ) || soFar;
 			}
-			groups.push( tokens = [] );
+			groups.push( (tokens = []) );
 		}
 
 		matched = false;
@@ -2489,8 +2114,8 @@ function addCombinator( matcher, combinator, base ) {
 
 		// Check against all ancestor/preceding elements
 		function( elem, context, xml ) {
-			var data, cache, outerCache,
-				dirkey = dirruns + " " + doneName;
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
 
 			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
 			if ( xml ) {
@@ -2505,14 +2130,17 @@ function addCombinator( matcher, combinator, base ) {
 				while ( (elem = elem[ dir ]) ) {
 					if ( elem.nodeType === 1 || checkNonElements ) {
 						outerCache = elem[ expando ] || (elem[ expando ] = {});
-						if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
-							if ( (data = cache[1]) === true || data === cachedruns ) {
-								return data === true;
-							}
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
 						} else {
-							cache = outerCache[ dir ] = [ dirkey ];
-							cache[1] = matcher( elem, context, xml ) || cachedruns;
-							if ( cache[1] === true ) {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
 								return true;
 							}
 						}
@@ -2706,31 +2334,30 @@ function matcherFromTokens( tokens ) {
 }
 
 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
-	// A counter to specify which element is currently being matched
-	var matcherCachedRuns = 0,
-		bySet = setMatchers.length > 0,
+	var bySet = setMatchers.length > 0,
 		byElement = elementMatchers.length > 0,
-		superMatcher = function( seed, context, xml, results, expandContext ) {
+		superMatcher = function( seed, context, xml, results, outermost ) {
 			var elem, j, matcher,
-				setMatched = [],
 				matchedCount = 0,
 				i = "0",
 				unmatched = seed && [],
-				outermost = expandContext != null,
+				setMatched = [],
 				contextBackup = outermostContext,
-				// We must always have either seed elements or context
-				elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
 				// Use integer dirruns iff this is the outermost matcher
-				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
 
 			if ( outermost ) {
 				outermostContext = context !== document && context;
-				cachedruns = matcherCachedRuns;
 			}
 
 			// Add elements passing elementMatchers directly to results
 			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
-			for ( ; (elem = elems[i]) != null; i++ ) {
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
 				if ( byElement && elem ) {
 					j = 0;
 					while ( (matcher = elementMatchers[j++]) ) {
@@ -2741,7 +2368,6 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
 					}
 					if ( outermost ) {
 						dirruns = dirrunsUnique;
-						cachedruns = ++matcherCachedRuns;
 					}
 				}
 
@@ -2876,7 +2502,7 @@ function select( selector, context, results, seed ) {
 					// Search, expanding context for leading sibling combinators
 					if ( (seed = find(
 						token.matches[0].replace( runescape, funescape ),
-						rsibling.test( tokens[0].type ) && context.parentNode || context
+						rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
 					)) ) {
 
 						// If seed is empty or no tokens remain, we can return early
@@ -2901,7 +2527,7 @@ function select( selector, context, results, seed ) {
 		context,
 		!documentIsHTML,
 		results,
-		rsibling.test( selector )
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
 	);
 	return results;
 }
@@ -2913,7 +2539,7 @@ support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
 
 // Support: Chrome<14
 // Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = hasDuplicate;
+support.detectDuplicates = !!hasDuplicate;
 
 // Initialize against the default document
 setDocument();
@@ -2961,13 +2587,20 @@ if ( !assert(function( div ) {
 	addHandle( booleans, function( elem, name, isXML ) {
 		var val;
 		if ( !isXML ) {
-			return (val = elem.getAttributeNode( name )) && val.specified ?
-				val.value :
-				elem[ name ] === true ? name.toLowerCase() : null;
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
 		}
 	});
 }
 
+return Sizzle;
+
+})( window );
+
+
+
 jQuery.find = Sizzle;
 jQuery.expr = Sizzle.selectors;
 jQuery.expr[":"] = jQuery.expr.pseudos;
@@ -2977,157 +2610,575 @@ jQuery.isXMLDoc = Sizzle.isXML;
 jQuery.contains = Sizzle.contains;
 
 
-})( window );
-// String to Object options format cache
-var optionsCache = {};
 
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
-	var object = optionsCache[ options ] = {};
-	jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
-		object[ flag ] = true;
-	});
-	return object;
-}
+var rneedsContext = jQuery.expr.match.needsContext;
 
-/*
- * Create a callback list using the following parameters:
- *
- *	options: an optional list of space-separated options that will change how
- *			the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- *	once:			will ensure the callback list can only be fired once (like a Deferred)
- *
- *	memory:			will keep track of previous values and will call any callback added
- *					after the list has been fired right away with the latest "memorized"
- *					values (like a Deferred)
- *
- *	unique:			will ensure a callback can only be added once (no duplicate in the list)
- *
- *	stopOnFalse:	interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
 
-	// Convert options from String-formatted to Object-formatted if needed
-	// (we check in cache first)
-	options = typeof options === "string" ?
-		( optionsCache[ options ] || createOptions( options ) ) :
-		jQuery.extend( {}, options );
 
-	var // Flag to know if list is currently firing
-		firing,
-		// Last fire value (for non-forgettable lists)
-		memory,
-		// Flag to know if list was already fired
-		fired,
-		// End of the loop when firing
-		firingLength,
-		// Index of currently firing callback (modified by remove if needed)
-		firingIndex,
-		// First callback to fire (used internally by add and fireWith)
-		firingStart,
-		// Actual callback list
-		list = [],
-		// Stack of fire calls for repeatable lists
-		stack = !options.once && [],
-		// Fire callbacks
-		fire = function( data ) {
-			memory = options.memory && data;
-			fired = true;
-			firingIndex = firingStart || 0;
-			firingStart = 0;
-			firingLength = list.length;
-			firing = true;
-			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
-				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
-					memory = false; // To prevent further calls using add
-					break;
-				}
-			}
-			firing = false;
-			if ( list ) {
-				if ( stack ) {
-					if ( stack.length ) {
-						fire( stack.shift() );
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			ret = [],
+			self = this,
+			len = self.length;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
 					}
-				} else if ( memory ) {
-					list = [];
-				} else {
-					self.disable();
 				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
 			}
-		},
-		// Actual Callbacks object
-		self = {
-			// Add a callback or a collection of callbacks to the list
-			add: function() {
-				if ( list ) {
-					// First, we save the current length
-					var start = list.length;
-					(function add( args ) {
-						jQuery.each( args, function( _, arg ) {
-							var type = jQuery.type( arg );
-							if ( type === "function" ) {
-								if ( !options.unique || !self.has( arg ) ) {
-									list.push( arg );
-								}
-							} else if ( arg && arg.length && type !== "string" ) {
-								// Inspect recursively
-								add( arg );
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
 							}
-						});
-					})( arguments );
-					// Do we need to add the callbacks to the
-					// current firing batch?
-					if ( firing ) {
-						firingLength = list.length;
-					// With memory, if we're not firing then
-					// we should call right away
-					} else if ( memory ) {
-						firingStart = start;
-						fire( memory );
+						}
 					}
-				}
-				return this;
-			},
-			// Remove a callback from the list
-			remove: function() {
-				if ( list ) {
-					jQuery.each( arguments, function( _, arg ) {
-						var index;
-						while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
-							list.splice( index, 1 );
-							// Handle firing indexes
-							if ( firing ) {
-								if ( index <= firingLength ) {
-									firingLength--;
-								}
-								if ( index <= firingIndex ) {
-									firingIndex--;
-								}
-							}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
 						}
-					});
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var i,
+			targets = jQuery( target, this ),
+			len = targets.length;
+
+		return this.filter(function() {
+			for ( i = 0; i < len; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// index in selector
+		if ( typeof elem === "string" ) {
+			return jQuery.inArray( this[0], jQuery( elem ) );
+		}
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	do {
+		cur = cur[ dir ];
+	} while ( cur && cur.nodeType !== 1 );
+
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				ret = jQuery.unique( ret );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				ret = ret.reverse();
+			}
+		}
+
+		return this.pushStack( ret );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Flag to know if list is currently firing
+		firing,
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
 				}
 				return this;
 			},
-			// Check if a given callback is in the list.
-			// If no argument is given, return whether or not list has callbacks attached.
-			has: function( fn ) {
-				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
-			},
-			// Remove all callbacks from the list
-			empty: function() {
-				list = [];
-				firingLength = 0;
-				return this;
-			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
 			// Have the list do nothing anymore
 			disable: function() {
 				list = stack = memory = undefined;
@@ -3160,6442 +3211,6866 @@ jQuery.Callbacks = function( options ) {
 						fire( args );
 					}
 				}
-				return this;
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
 			},
-			// Call all the callbacks with the given arguments
-			fire: function() {
-				self.fireWith( this, arguments );
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
 				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+
+					} else if ( !(--remaining) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
 			},
-			// To know if the callbacks have already been called at least once
-			fired: function() {
-				return !!fired;
+
+			progressValues, progressContexts, resolveContexts;
+
+		// add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
 			}
-		};
+		}
+
+		// if we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( !document.body ) {
+			return setTimeout( jQuery.ready );
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.trigger ) {
+			jQuery( document ).trigger("ready").off("ready");
+		}
+	}
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+	if ( document.addEventListener ) {
+		document.removeEventListener( "DOMContentLoaded", completed, false );
+		window.removeEventListener( "load", completed, false );
+
+	} else {
+		document.detachEvent( "onreadystatechange", completed );
+		window.detachEvent( "onload", completed );
+	}
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	// readyState === "complete" is good enough for us to call the dom ready in oldIE
+	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+		detach();
+		jQuery.ready();
+	}
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// we once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		// Standards-based browsers support DOMContentLoaded
+		} else if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+
+		// If IE event model is used
+		} else {
+			// Ensure firing before onload, maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", completed );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", completed );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var top = false;
+
+			try {
+				top = window.frameElement == null && document.documentElement;
+			} catch(e) {}
+
+			if ( top && top.doScroll ) {
+				(function doScrollCheck() {
+					if ( !jQuery.isReady ) {
+
+						try {
+							// Use the trick by Diego Perini
+							// http://javascript.nwbox.com/IEContentLoaded/
+							top.doScroll("left");
+						} catch(e) {
+							return setTimeout( doScrollCheck, 50 );
+						}
+
+						// detach all dom ready events
+						detach();
+
+						// and execute any waiting functions
+						jQuery.ready();
+					}
+				})();
+			}
+		}
+	}
+	return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+	break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+jQuery(function() {
+	// We need to execute this one support test ASAP because we need to know
+	// if body.style.zoom needs to be set.
+
+	var container, div,
+		body = document.getElementsByTagName("body")[0];
+
+	if ( !body ) {
+		// Return for frameset docs that don't have a body
+		return;
+	}
 
-	return self;
+	// Setup
+	container = document.createElement( "div" );
+	container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+	div = document.createElement( "div" );
+	body.appendChild( container ).appendChild( div );
+
+	if ( typeof div.style.zoom !== strundefined ) {
+		// Support: IE<8
+		// Check if natively block-level elements act like inline-block
+		// elements when setting their display to 'inline' and giving
+		// them layout
+		div.style.cssText = "border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1";
+
+		if ( (support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 )) ) {
+			// Prevent IE 6 from affecting layout for positioned elements #11048
+			// Prevent IE from shrinking the body in IE 7 mode #12869
+			// Support: IE<8
+			body.style.zoom = 1;
+		}
+	}
+
+	body.removeChild( container );
+
+	// Null elements to avoid leaks in IE
+	container = div = null;
+});
+
+
+
+
+(function() {
+	var div = document.createElement( "div" );
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+	var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+		nodeType = +elem.nodeType || 1;
+
+	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+	return nodeType !== 1 && nodeType !== 9 ?
+		false :
+
+		// Nodes accept data unless otherwise specified; rejection can be conditional
+		!noData || noData !== true && elem.getAttribute("classid") === noData;
 };
-jQuery.extend({
 
-	Deferred: function( func ) {
-		var tuples = [
-				// action, add listener, listener list, final state
-				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
-				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
-				[ "notify", "progress", jQuery.Callbacks("memory") ]
-			],
-			state = "pending",
-			promise = {
-				state: function() {
-					return state;
-				},
-				always: function() {
-					deferred.done( arguments ).fail( arguments );
-					return this;
-				},
-				then: function( /* fnDone, fnFail, fnProgress */ ) {
-					var fns = arguments;
-					return jQuery.Deferred(function( newDefer ) {
-						jQuery.each( tuples, function( i, tuple ) {
-							var action = tuple[ 0 ],
-								fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
-							// deferred[ done | fail | progress ] for forwarding actions to newDefer
-							deferred[ tuple[1] ](function() {
-								var returned = fn && fn.apply( this, arguments );
-								if ( returned && jQuery.isFunction( returned.promise ) ) {
-									returned.promise()
-										.done( newDefer.resolve )
-										.fail( newDefer.reject )
-										.progress( newDefer.notify );
-								} else {
-									newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
-								}
-							});
-						});
-						fns = null;
-					}).promise();
-				},
-				// Get a promise for this deferred
-				// If obj is provided, the promise aspect is added to the object
-				promise: function( obj ) {
-					return obj != null ? jQuery.extend( obj, promise ) : promise;
-				}
-			},
-			deferred = {};
 
-		// Keep pipe for back-compat
-		promise.pipe = promise.then;
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
 
-		// Add list-specific methods
-		jQuery.each( tuples, function( i, tuple ) {
-			var list = tuple[ 2 ],
-				stateString = tuple[ 3 ];
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
 
-			// promise[ done | fail | progress ] = list.add
-			promise[ tuple[1] ] = list.add;
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
 
-			// Handle state
-			if ( stateString ) {
-				list.add(function() {
-					// state = [ resolved | rejected ]
-					state = stateString;
+		data = elem.getAttribute( name );
 
-				// [ reject_list | resolve_list ].disable; progress_list.lock
-				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
-			}
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
 
-			// deferred[ resolve | reject | notify ]
-			deferred[ tuple[0] ] = function() {
-				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
-				return this;
-			};
-			deferred[ tuple[0] + "With" ] = list.fireWith;
-		});
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
 
-		// Make the deferred a promise
-		promise.promise( deferred );
+		} else {
+			data = undefined;
+		}
+	}
 
-		// Call given func if any
-		if ( func ) {
-			func.call( deferred, deferred );
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	var name;
+	for ( name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
 		}
+	}
 
-		// All done!
-		return deferred;
-	},
+	return true;
+}
 
-	// Deferred helper
-	when: function( subordinate /* , ..., subordinateN */ ) {
-		var i = 0,
-			resolveValues = core_slice.call( arguments ),
-			length = resolveValues.length,
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
 
-			// the count of uncompleted subordinates
-			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+	var ret, thisCache,
+		internalKey = jQuery.expando,
+
+		// We have to handle DOM nodes and JS objects differently because IE6-7
+		// can't GC object references properly across the DOM-JS boundary
+		isNode = elem.nodeType,
+
+		// Only DOM nodes need the global jQuery cache; JS object data is
+		// attached directly to the object so GC can occur automatically
+		cache = isNode ? jQuery.cache : elem,
+
+		// Only defining an ID for JS objects if its cache already exists allows
+		// the code to shortcut on the same path as a DOM node with no cache
+		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+	// Avoid doing any more work than we need to when trying to get data on an
+	// object that has no data at all
+	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+		return;
+	}
+
+	if ( !id ) {
+		// Only DOM nodes need a new unique ID for each element since their data
+		// ends up in the global cache
+		if ( isNode ) {
+			id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+		} else {
+			id = internalKey;
+		}
+	}
+
+	if ( !cache[ id ] ) {
+		// Avoid exposing jQuery metadata on plain JS objects when the object
+		// is serialized using JSON.stringify
+		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+	}
+
+	// An object can be passed to jQuery.data instead of a key/value pair; this gets
+	// shallow copied over onto the existing cache
+	if ( typeof name === "object" || typeof name === "function" ) {
+		if ( pvt ) {
+			cache[ id ] = jQuery.extend( cache[ id ], name );
+		} else {
+			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+		}
+	}
+
+	thisCache = cache[ id ];
+
+	// jQuery data() is stored in a separate object inside the object's internal data
+	// cache in order to avoid key collisions between internal data and user-defined
+	// data.
+	if ( !pvt ) {
+		if ( !thisCache.data ) {
+			thisCache.data = {};
+		}
+
+		thisCache = thisCache.data;
+	}
+
+	if ( data !== undefined ) {
+		thisCache[ jQuery.camelCase( name ) ] = data;
+	}
+
+	// Check for both converted-to-camel and non-converted data property names
+	// If a data property was specified
+	if ( typeof name === "string" ) {
+
+		// First Try to find as-is property data
+		ret = thisCache[ name ];
+
+		// Test for null|undefined property data
+		if ( ret == null ) {
+
+			// Try to find the camelCased property
+			ret = thisCache[ jQuery.camelCase( name ) ];
+		}
+	} else {
+		ret = thisCache;
+	}
+
+	return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var thisCache, i,
+		isNode = elem.nodeType,
+
+		// See jQuery.data for more information
+		cache = isNode ? jQuery.cache : elem,
+		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+	// If there is already no cache entry for this object, there is no
+	// purpose in continuing
+	if ( !cache[ id ] ) {
+		return;
+	}
+
+	if ( name ) {
+
+		thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+		if ( thisCache ) {
+
+			// Support array or space separated string names for data keys
+			if ( !jQuery.isArray( name ) ) {
 
-			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
-			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+				// try the string as a key before any manipulation
+				if ( name in thisCache ) {
+					name = [ name ];
+				} else {
 
-			// Update function for both resolve and progress values
-			updateFunc = function( i, contexts, values ) {
-				return function( value ) {
-					contexts[ i ] = this;
-					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
-					if( values === progressValues ) {
-						deferred.notifyWith( contexts, values );
-					} else if ( !( --remaining ) ) {
-						deferred.resolveWith( contexts, values );
+					// split the camel cased version by spaces unless a key with the spaces exists
+					name = jQuery.camelCase( name );
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+						name = name.split(" ");
 					}
-				};
-			},
+				}
+			} else {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+			}
 
-			progressValues, progressContexts, resolveContexts;
+			i = name.length;
+			while ( i-- ) {
+				delete thisCache[ name[i] ];
+			}
 
-		// add listeners to Deferred subordinates; treat others as resolved
-		if ( length > 1 ) {
-			progressValues = new Array( length );
-			progressContexts = new Array( length );
-			resolveContexts = new Array( length );
-			for ( ; i < length; i++ ) {
-				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
-					resolveValues[ i ].promise()
-						.done( updateFunc( i, resolveContexts, resolveValues ) )
-						.fail( deferred.reject )
-						.progress( updateFunc( i, progressContexts, progressValues ) );
-				} else {
-					--remaining;
-				}
+			// If there is no data left in the cache, we want to continue
+			// and let the cache object itself get destroyed
+			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+				return;
 			}
 		}
+	}
 
-		// if we're not waiting on anything, resolve the master
-		if ( !remaining ) {
-			deferred.resolveWith( resolveContexts, resolveValues );
-		}
+	// See jQuery.data for more information
+	if ( !pvt ) {
+		delete cache[ id ].data;
 
-		return deferred.promise();
+		// Don't destroy the parent cache unless the internal data object
+		// had been the only thing left in it
+		if ( !isEmptyDataObject( cache[ id ] ) ) {
+			return;
+		}
 	}
-});
-jQuery.support = (function( suppo

<TRUNCATED>

[19/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Testing and improvements


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/ae051090
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/ae051090
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/ae051090

Branch: refs/heads/import-master
Commit: ae051090e73d53898e21cffbbbcf804de0ef5f80
Parents: 015829c
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Jan 14 11:49:35 2014 +0200
Committer: suelockwood <de...@apache.org>
Committed: Tue Jan 14 10:45:56 2014 -0500

----------------------------------------------------------------------
 app/api.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/ae051090/app/api.js
----------------------------------------------------------------------
diff --git a/app/api.js b/app/api.js
index 6d450de..9ac895e 100644
--- a/app/api.js
+++ b/app/api.js
@@ -333,7 +333,7 @@ function(app, Fauxton) {
           triggerBroadcast('beforeRender', view, selector);
           var viewPromise = view.establish();
           routeObject.addPromise(viewPromise);
-          FauxtonAPI.when(view.establish()).then(function(resp) {
+          FauxtonAPI.when(viewPromise).then(function(resp) {
             masterLayout.setView(selector, view);
 
             masterLayout.renderView(selector);


[48/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Add more caching locations


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/4b5735c7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/4b5735c7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/4b5735c7

Branch: refs/heads/import-master
Commit: 4b5735c7d4b456acbe457d3c7da675b8a0be0d20
Parents: f111540
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Feb 5 19:23:12 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Feb 5 19:23:12 2014 +0200

----------------------------------------------------------------------
 app/addons/databases/resources.js |  5 +++++
 app/addons/databases/routes.js    |  2 +-
 app/addons/databases/views.js     |  2 +-
 app/addons/documents/views.js     | 21 +++------------------
 app/core/base.js                  | 21 ++++++++++++++++++---
 app/core/couchdbSession.js        | 11 +++++++++--
 6 files changed, 37 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index 5fa931b..ea1aed2 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -171,6 +171,11 @@ function(app, FauxtonAPI, Documents) {
     documentation: function(){
       return "all_dbs";
     },
+
+    cache: {
+      expires: 60
+    },
+
     url: function(context) {
       if (context === "apiurl") { 
         return window.location.origin + "/_all_dbs";

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/addons/databases/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/routes.js b/app/addons/databases/routes.js
index c413018..131abf9 100644
--- a/app/addons/databases/routes.js
+++ b/app/addons/databases/routes.js
@@ -59,7 +59,7 @@ function(app, FauxtonAPI, Databases, Views) {
     },
 
     establish: function() {
-     return [this.databases.fetch()];
+     return [this.databases.fetchOnce()];
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
index afe2d1c..7f23d65 100644
--- a/app/addons/databases/views.js
+++ b/app/addons/databases/views.js
@@ -61,7 +61,7 @@ function(app, Components, FauxtonAPI, Databases) {
       var deferred = FauxtonAPI.Deferred();
 
       FauxtonAPI.when(currentDBs.map(function(database) {
-        return database.status.fetch();
+        return database.status.fetchOnce();
       })).always(function(resp) {
         //make this always so that even if a user is not allowed access to a database
         //they will still see a list of all databases

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 5476203..13cbacb 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1804,30 +1804,15 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     template: "addons/documents/templates/changes",
 
     initialize: function () {
-      var that = this;
-      this.listenTo( this.model.changes, 'change', function () {
-        console.log('render on change'); 
-        that.render();
-      });
-      this.listenTo( this.model.changes, 'cachesync', function () {
-        console.log('render on cachesync'); 
-        that.render();
-      });
+      this.listenTo( this.model.changes, 'sync', this.render);
+      this.listenTo( this.model.changes, 'cachesync', this.render);
     },
 
     establish: function() {
-      return [ this.model.changes.fetchOnce({prefill: true,
-        success: function () {
-          console.log('hi ajax success');
-        },
-        prefillSuccess: function () {
-          console.log('hi prefill success');
-        }
-      })];
+      return [ this.model.changes.fetchOnce({prefill: true})];
     },
 
     serialize: function () {
-      console.log('ss');
       return {
         changes: this.model.changes.toJSON(),
         database: this.model

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 6fe3261..24b89cf 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -17,7 +17,6 @@ define([
 ],
 
 function(Backbone, LayoutManager, BackboneCache) {
-  console.log(BackboneCache);
   var FauxtonAPI = {
     //add default objects
     router: {
@@ -81,8 +80,24 @@ function(Backbone, LayoutManager, BackboneCache) {
   var caching = {
     fetchOnce: function (opts) {
       var options = _.defaults(opts || {}, this.cache, {cache: true});
-      console.log('opts', options);
-      return this.fetch(options);
+
+      if (opts && !opts.cache) {
+        delete options.cache;
+      }
+
+      if (!options.prefill) {
+        return this.fetch(options);
+      }
+
+      //With Prefill, the Caching with resolve with whatever is in the cache for that model/collection
+      //and at the sametime it will fetch from the server the latest. 
+      var promise = FauxtonAPI.Deferred(),
+          fetchPromise = this.fetch(options);
+
+      fetchPromise.progress(promise.resolveWith); // Fires when the cache hit happens
+      fetchPromise.then(promise.resolveWith); // Fires after the AJAX call
+
+      return promise;
     }
   };
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4b5735c7/app/core/couchdbSession.js
----------------------------------------------------------------------
diff --git a/app/core/couchdbSession.js b/app/core/couchdbSession.js
index 93bfd8a..b70ddf3 100644
--- a/app/core/couchdbSession.js
+++ b/app/core/couchdbSession.js
@@ -29,9 +29,16 @@ function (FauxtonAPI) {
 
       fetchUser: function (opt) {
         var that = this,
-        currentUser = this.user();
+            options = opt || {},
+        currentUser = this.user(),
+        fetch = this.fetchOnce;
 
-        return this.fetchOnce(opt).then(function () {
+        if (options.forceFetch) {
+          fetch = this.fetch;
+          Backbone.fetchCache.clearItem(_.result(this.url));
+        }
+
+        return this.fetch(opt).then(function () {
           var user = that.user();
 
           // Notify anyone listening on these events that either a user has changed


[36/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Modal instead of prompt for delete

Display a modal asking for database name instead of a simple prompt.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/470cdd56
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/470cdd56
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/470cdd56

Branch: refs/heads/import-master
Commit: 470cdd56deb9f556dfd9e1616ea35ba3da8b9815
Parents: 24ce023
Author: Simon Metson <si...@cloudant.com>
Authored: Sun Jan 26 19:06:18 2014 +0000
Committer: suelockwood <de...@apache.org>
Committed: Wed Jan 29 10:34:29 2014 -0500

----------------------------------------------------------------------
 .../templates/delete_database_modal.html        |  37 ++++++
 app/addons/documents/templates/sidebar.html     |   1 +
 app/addons/documents/views.js                   | 114 +++++++++++++------
 3 files changed, 119 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/470cdd56/app/addons/documents/templates/delete_database_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/delete_database_modal.html b/app/addons/documents/templates/delete_database_modal.html
new file mode 100644
index 0000000..024f7c9
--- /dev/null
+++ b/app/addons/documents/templates/delete_database_modal.html
@@ -0,0 +1,37 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="modal hide fade">
+  <div class="modal-header">
+    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+    <h3>Delete Database</h3>
+  </div>
+  <div class="modal-body">
+    <form id="delete-db-check" class="form" method="post">
+      <p>
+      You've asked to <b>permanently delete</b> <code><%= database.id %></code>.
+      Please enter the database name below to confirm the deletion of the
+      database and all documents and attachments within.
+      </p>
+      <input class="input-block-level" type="text" name="db_name" id="db_name"></input>
+      <br/>
+      <div id="modal-error" class="alert alert-error hide" style="font-size: 16px;"></div>
+    </form>
+  </div>
+  <div class="modal-footer">
+    <a href="#" data-dismiss="modal" data-bypass="true" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
+    <a href="#" id="delete-db-btn" data-bypass="true" class="btn btn-primary button red save fonticon-circle-check">Delete</a>
+  </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/470cdd56/app/addons/documents/templates/sidebar.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/sidebar.html b/app/addons/documents/templates/sidebar.html
index 8a73ae9..c8ce511 100644
--- a/app/addons/documents/templates/sidebar.html
+++ b/app/addons/documents/templates/sidebar.html
@@ -64,4 +64,5 @@ the License.
     </ul>
     <div id="extension-navs"></div>
   </nav>
+  <div id="delete-db-modal"> </div>
 </div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/470cdd56/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index fd7d034..455bfda 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -113,6 +113,76 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     }
   });
 
+  Views.DeleteDBModal = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/delete_database_modal",
+
+    disableLoader: true,
+
+    initialize: function (options) {
+      _.bindAll(this);
+    },
+
+    events: {
+      "click a#delete-db-btn": "deleteDatabase",
+      "submit #delete-db-check": "deleteDatabase"
+    },
+
+    deleteDatabase: function (event) {
+      event.preventDefault();
+      var enterredName = this.$('#db_name')[0].value;
+      if (this.database.id != enterredName) {
+        this.set_error_msg(enterredName + " does not match database id - are you sure you want to delete " + this.database.id + "?");
+        return;
+      }
+      this.hideModal();
+      var databaseName = this.database.id;
+      FauxtonAPI.addNotification({
+        msg: "Deleting your database...",
+        type: "error",
+        clear: true
+      });
+
+      this.database.destroy().then(function () {
+        FauxtonAPI.navigate('#/_all_dbs');
+        FauxtonAPI.addNotification({
+          msg: 'The database <code>' + databaseName + '</code> has been deleted.',
+          clear: true
+        });
+      }).fail(function (rsp, error, msg) {
+        FauxtonAPI.addNotification({
+          msg: 'Could not delete the database, reason ' + msg + '.',
+          type: 'error',
+          clear: true
+        });
+      });
+    },
+
+    showModal: function () {
+      this.clear_error_msg();
+      this.$('.modal').modal();
+      // hack to get modal visible
+      $('.modal-backdrop').css('z-index',1025);
+    },
+
+    hideModal: function () {
+      this.$('.modal').modal('hide');
+    },
+
+    set_error_msg: function (msg) {
+      var text;
+      if (typeof(msg) == 'string') {
+        text = msg;
+      } else {
+        text = JSON.parse(msg.responseText).reason;
+      }
+      this.$('#modal-error').text(text).removeClass('hide');
+    },
+
+    clear_error_msg: function () {
+      this.$('#modal-error').text(' ').addClass('hide');
+    }
+  });
+
   Views.UploadModal = FauxtonAPI.View.extend({
     template: "addons/documents/templates/upload_modal",
 
@@ -411,7 +481,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         ddoc: this.ddoc,
         database: this.database,
         index_clean: app.utils.removeSpecialCharacters(this.index),
-        ddoc_clean: app.utils.removeSpecialCharacters(this.ddoc), 
+        ddoc_clean: app.utils.removeSpecialCharacters(this.ddoc),
         index_encoded: app.utils.safeURLName(this.index),
         ddoc_encoded: app.utils.safeURLName(this.ddoc),
         database_encoded: app.utils.safeURLName(this.database),
@@ -1393,7 +1463,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
           });
 
           if (that.newView || viewNameChange) {
-            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName); 
+            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName);
 
             FauxtonAPI.navigate(fragment, {trigger: false});
             that.newView = false;
@@ -1507,7 +1577,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
        }
 
       promise.then(function () {
-        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
+        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');});
         var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
         queryPromise.then(function (results) {
           FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
@@ -1534,7 +1604,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     reduceVal: function() {
       var reduceOption = this.$('#reduce-function-selector :selected').val(),
       reduceVal = "";
-      
+
       if (reduceOption === 'CUSTOM') {
         if (!this.reduceEditor) { this.createReduceEditor(); }
         reduceVal = this.reduceEditor.getValue();
@@ -1732,7 +1802,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   Views.Sidebar = FauxtonAPI.View.extend({
     template: "addons/documents/templates/sidebar",
     events: {
-      "click button#delete-database": "deleteDatabase"
+      "click button#delete-database": "showDeleteDatabaseModal"
     },
 
     initialize: function(options) {
@@ -1742,33 +1812,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         this.currView = options.ddocInfo.currView;
       }
     },
-
-    deleteDatabase: function (event) {
-      event.preventDefault();
-
-      var result = confirm('Are you sure you want to delete this database?');
-
-      if (!result) { return; }
-      var databaseName = this.database.id;
-      FauxtonAPI.addNotification({
-        msg: "Deleting your database...",
-        type: "error",
-        clear: true
-      });
-
-      this.database.destroy().then(function () {
-        FauxtonAPI.navigate('#/_all_dbs');
-        FauxtonAPI.addNotification({
-          msg: 'The database <code>' + databaseName + '</code> has been deleted.',
-          clear: true
-        });
-      }).fail(function (rsp, error, msg) {
-        FauxtonAPI.addNotification({
-          msg: 'Could not delete the database, reason ' + msg + '.',
-          type: 'error',
-          clear: true
-        });
-      });
+    showDeleteDatabaseModal: function(event){
+      this.deleteDBModal.showModal();
     },
 
     serialize: function() {
@@ -1803,6 +1848,10 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     },
 
     beforeRender: function(manage) {
+      this.deleteDBModal = this.setView(
+        '#delete-db-modal',
+        new Views.DeleteDBModal({database: this.database})
+      );
 
       var sidebarListViews = FauxtonAPI.getExtensions('sidebar:list');
       _.each(sidebarListViews, function (view) {
@@ -1811,7 +1860,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         extension.render();
       }, this);
 
-
       this.collection.each(function(design) {
         if (design.has('doc')){
           var ddoc = design.id.replace(/^_design\//,"");


[17/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Bug fixes

* Fix failing tests
* Fix pagination not showing correct number when docs less than limit
* Fix create new view failing with new design doc
* Add Fauxton logo for grunt couchserver


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/921ff62f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/921ff62f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/921ff62f

Branch: refs/heads/import-master
Commit: 921ff62f4ead5716d5afaa56ddd761a1284a1daf
Parents: 7e2c615
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Jan 14 14:34:20 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Jan 14 14:34:20 2014 +0200

----------------------------------------------------------------------
 .../documents/templates/index_row_docular.html    |  2 +-
 app/addons/documents/views.js                     |  3 ++-
 app/addons/fauxton/components.js                  |  4 ++++
 app/addons/permissions/tests/viewsSpec.js         |  2 +-
 tasks/couchserver.js                              | 18 +++++++++++++++++-
 5 files changed, 25 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/921ff62f/app/addons/documents/templates/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html
index 446a031..e8973ad 100644
--- a/app/addons/documents/templates/index_row_docular.html
+++ b/app/addons/documents/templates/index_row_docular.html
@@ -19,7 +19,7 @@ the License.
     <pre class="prettyprint"><%- doc.prettyJSON() %></pre>
 
       <div class="btn-group">
-        <a href="#<%= doc.url('app') %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
+        <a href="#<%= url %>" class="btn btn-small edits">Edit <%= doc.docType() %></a>
         <% if (doc.isEditable()) { %>
           <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button>
         <% } %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/921ff62f/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 0139eca..9902541 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -405,7 +405,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
     serialize: function() {
       return {
-        doc: this.model
+        doc: this.model,
+        url: this.model.url('app')
       };
     }
   });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/921ff62f/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index a9f45ad..cda61c5 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -123,6 +123,10 @@ function(app, FauxtonAPI, ace) {
     },
 
     pageEnd: function () {
+      if (this.collection.length < this.pageLimit()) {
+        return this.collection.length;
+      }
+
       return (this.previousParams.length * this.pageLimit()) + this.pageLimit();
     }
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/921ff62f/app/addons/permissions/tests/viewsSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/permissions/tests/viewsSpec.js b/app/addons/permissions/tests/viewsSpec.js
index e5330c0..27abca4 100644
--- a/app/addons/permissions/tests/viewsSpec.js
+++ b/app/addons/permissions/tests/viewsSpec.js
@@ -25,7 +25,7 @@ define([
         'names': ['_user'],
         'roles': []
       }
-      }, {database: 'fakedb'});
+      }, {database: {id: 'fakedb', safeID: function () { return this.id; }}});
 
       section = new Views.Permissions({
         database: 'fakedb',

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/921ff62f/tasks/couchserver.js
----------------------------------------------------------------------
diff --git a/tasks/couchserver.js b/tasks/couchserver.js
index b9ff3ef..5ccbfe1 100644
--- a/tasks/couchserver.js
+++ b/tasks/couchserver.js
@@ -19,7 +19,8 @@ module.exports = function (grunt) {
         http = require("http"),
         httpProxy = require('http-proxy'),
         send = require('send'),
-        options = grunt.config('couchserver');
+        options = grunt.config('couchserver'),
+        _ = grunt.util._;
 
     // Options
     var dist_dir = options.dist || './dist/debug/',
@@ -98,6 +99,21 @@ module.exports = function (grunt) {
     watch.stdout.pipe(process.stdout);
     watch.stderr.pipe(process.stderr);
 
+    var logo = [
+      [""],
+      [" ______                        _                   "],
+      ["|  ____|                      | |                  "],
+      ["| |__    __ _   _   _  __  __ | |_    ___    _ __  "],
+      ["|  __|  / _` | | | | | \\ \\/ / | __|  / _ \\  | '_ \\ "],
+      ["| |    | (_| | | |_| |  >  <  | |_  | (_) | | | | |"],
+      ["|_|     \\__,_|  \\__,_| /_/\\_\\  \\__|  \\___/  |_| |_|"],
+      [""]
+   ];
+
+    _.each(logo, function (line) {
+      console.log(line.toString());
+    });
+
     log.writeln('Listening on ' + port);
   });
 


[15/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix Permissions model url


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/fb900498
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/fb900498
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/fb900498

Branch: refs/heads/import-master
Commit: fb9004980558963776f5d1dc43819d24a6c09659
Parents: bfd419b
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 15:58:35 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 15:58:35 2014 -0500

----------------------------------------------------------------------
 app/addons/permissions/resources.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/fb900498/app/addons/permissions/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/permissions/resources.js b/app/addons/permissions/resources.js
index 8acaddd..4ddd3ae 100644
--- a/app/addons/permissions/resources.js
+++ b/app/addons/permissions/resources.js
@@ -39,7 +39,7 @@ function (app, FauxtonAPI ) {
     },
 
     url: function () {
-      return app.host + this.database.id + '/_security';
+      return window.location.origin +"/"+ this.database.safeID() + '/_security';
     },
 
     addItem: function (value, type, section) {


[21/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: update api bar with view query updates


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/a210c875
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/a210c875
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/a210c875

Branch: refs/heads/import-master
Commit: a210c875dc85cb303941f7b93a400f55611a2518
Parents: 60561d6
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Jan 15 17:32:52 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Jan 15 17:32:52 2014 +0200

----------------------------------------------------------------------
 app/addons/documents/routes.js | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a210c875/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 6786edf..1510485 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -304,6 +304,7 @@ function(app, FauxtonAPI, Documents, Databases) {
         this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
           collection: this.data.database.allDocs
         }));
+        //this.apiUrl = [this.data.database.allDocs.url("apiurl"), this.data.database.allDocs.documentation() ];
         return;
       }
 
@@ -320,6 +321,8 @@ function(app, FauxtonAPI, Documents, Databases) {
         nestedView: Documents.Views.Row,
         viewList: true
       }));
+
+      this.apiUrl = [this.data.indexedDocs.url("apiurl"), "docs"];
     },
 
     updateAllDocsFromPreview: function (event) {


[25/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Set default reduce to none not _sum


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/2123e61c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/2123e61c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/2123e61c

Branch: refs/heads/import-master
Commit: 2123e61cb93f68b0abfe85bb447912ac7ec4cd15
Parents: 4d80b7f
Author: suelockwood <de...@apache.org>
Authored: Thu Jan 16 14:12:51 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Thu Jan 16 14:13:09 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/views.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/2123e61c/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index bde08f8..ba7e7d7 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1593,7 +1593,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     beforeRender: function () {
 
       if (this.newView) {
-        this.reduceFunStr = '_sum';
+        this.reduceFunStr = '';
         if (this.ddocs.length === 0) {
           this.model = new Documents.Doc(null, {database: this.database});
         } else {


[27/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Fix rename view shows in sidebar


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/04808692
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/04808692
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/04808692

Branch: refs/heads/import-master
Commit: 04808692cc5297210cbdc53493ffd2fee7ed13a3
Parents: 8fda790
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Jan 21 15:30:46 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Jan 21 15:30:46 2014 +0200

----------------------------------------------------------------------
 app/addons/compaction/views.js |  1 -
 app/addons/documents/views.js  | 13 ++++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/04808692/app/addons/compaction/views.js
----------------------------------------------------------------------
diff --git a/app/addons/compaction/views.js b/app/addons/compaction/views.js
index 06a1300..f5469cf 100644
--- a/app/addons/compaction/views.js
+++ b/app/addons/compaction/views.js
@@ -52,7 +52,6 @@ function (app, FauxtonAPI, Compaction) {
           msg: 'Database compaction has started. Visit <a href="#activetasks">Active Tasks</a> to view the compaction progress.',
         });
       }, function (xhr, error, reason) {
-        console.log(arguments);
         FauxtonAPI.addNotification({
           type: 'error',
           msg: 'Error: ' + JSON.parse(xhr.responseText).reason

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/04808692/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index ba7e7d7..d5319f3 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1344,9 +1344,14 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
         reduceVal = this.reduceVal(),
         viewName = this.$('#index-name').val(),
         ddoc = this.getCurrentDesignDoc(),
-        ddocName = ddoc.id;
+        ddocName = ddoc.id,
+        viewNameChange = false;
 
-        this.viewName = viewName;
+        if (this.viewName !== viewName) {
+          ddoc.removeDdocView(this.viewName);
+          this.viewName = viewName;
+          viewNameChange = true;
+        }
 
         notification = FauxtonAPI.addNotification({
           msg: "Saving document.",
@@ -1369,7 +1374,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
             clear: true
           });
 
-          if (that.newView) {
+          if (that.newView || viewNameChange) {
             var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName); 
 
             FauxtonAPI.navigate(fragment, {trigger: false});
@@ -1485,8 +1490,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
       promise.then(function () {
         params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
-
-        console.log('p', params, paramsInfo);
         var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
         queryPromise.then(function (results) {
           FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});


[40/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Include layout manager in base.js for release builds
Remove Console log


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/040e38d5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/040e38d5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/040e38d5

Branch: refs/heads/import-master
Commit: 040e38d5f63b17f57a9192047214261a6a4f70be
Parents: b526f00
Author: suelockwood <de...@apache.org>
Authored: Thu Jan 30 13:08:52 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Thu Jan 30 13:12:08 2014 -0500

----------------------------------------------------------------------
 app/addons/databases/views.js | 2 +-
 app/core/base.js              | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/040e38d5/app/addons/databases/views.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/views.js b/app/addons/databases/views.js
index 56001db..afe2d1c 100644
--- a/app/addons/databases/views.js
+++ b/app/addons/databases/views.js
@@ -28,7 +28,7 @@ function(app, Components, FauxtonAPI, Databases) {
       return [this.model.fetch()];
     },
     serialize: function() {
-      console.log('db', this.model);
+      
       return {
         encoded: app.utils.safeURLName(this.model.get("name")),
         database: this.model,

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/040e38d5/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 55a8d87..53316bc 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -11,7 +11,8 @@
 // the License.
 
 define([
-  "backbone"
+  "backbone",
+  "plugins/backbone.layoutmanager"
 ],
 
 function(Backbone) {
@@ -57,9 +58,8 @@ function(Backbone) {
     establish: function() {
       return null;
     },
-
     loaderClassname: 'loader',
-
+    manage: true,
     disableLoader: false,
 
     forceRender: function () {


[52/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: Improve spinners


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/d11b90b8
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/d11b90b8
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/d11b90b8

Branch: refs/heads/import-master
Commit: d11b90b8c383915b9764939d1dbd7d278f23e760
Parents: be87767
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Feb 11 10:12:21 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Feb 11 10:12:21 2014 +0200

----------------------------------------------------------------------
 app/addons/fauxton/components.js | 22 +++++++++++++++-------
 app/core/routeObject.js          |  1 -
 2 files changed, 15 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/d11b90b8/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index 1f5e4ad..8b21916 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -415,6 +415,8 @@ function(app, FauxtonAPI, ace, spin) {
         shadow: false // Whether to render a shadow
      };
 
+     if (routeObjectSpinner) { return; }
+
      if (!$('.spinner').length) {
        $('<div class="spinner"></div>')
         .appendTo('#app-container');
@@ -428,18 +430,22 @@ function(app, FauxtonAPI, ace, spin) {
   var removeRouteObjectSpinner = function () {
     if (routeObjectSpinner) {
       routeObjectSpinner.stop();
+      routeObjectSpinner = null;
       $('.spinner').remove();
     }
   };
 
-  var removeViewSpinner = function () {
+  var removeViewSpinner = function (selector) {
+    var viewSpinner = viewSpinners[selector];
+
     if (viewSpinner){
       viewSpinner.stop();
-      $('.spinner').remove();
+      $(selector).find('.spinner').remove();
+      delete viewSpinners[selector];
     }
   };
 
-  var viewSpinner;
+  var viewSpinners = {};
   FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
     removeRouteObjectSpinner();
 
@@ -455,19 +461,21 @@ function(app, FauxtonAPI, ace, spin) {
         shadow: false // Whether to render a shadow
       };
 
-      viewSpinner = new Spinner(opts).spin();
+      var viewSpinner = new Spinner(opts).spin();
       $('<div class="spinner"></div>')
         .appendTo(selector)
         .append(viewSpinner.el);
+
+      viewSpinners[selector] = viewSpinner;
     }
   });
 
   FauxtonAPI.RouteObject.on('afterRender', function (routeObject, view, selector) {
-    removeViewSpinner();
+    removeViewSpinner(selector);
   });
 
-  FauxtonAPI.RouteObject.on('viewHasRendered', function () {
-    removeViewSpinner();
+  FauxtonAPI.RouteObject.on('viewHasRendered', function (view, selector) {
+    removeViewSpinner(selector);
     removeRouteObjectSpinner();
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/d11b90b8/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
index 9f1067f..f8a238f 100644
--- a/app/core/routeObject.js
+++ b/app/core/routeObject.js
@@ -231,7 +231,6 @@ function(FauxtonAPI, Backbone) {
       if (_.isEmpty(promise)) { return; }
 
       if (!_.isArray(promise)) {
-        if (!promise.abort && !promise.reject) {
         return this._promises.push(promise);
       }
 


[32/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix for beautify to work with require.js


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/1be64cdd
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/1be64cdd
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/1be64cdd

Branch: refs/heads/import-master
Commit: 1be64cdd4eac99dedc34558c219f5249586d5e15
Parents: c9ad37b
Author: suelockwood <de...@apache.org>
Authored: Tue Jan 28 10:39:05 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Tue Jan 28 11:31:37 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/templates/view_editor.html |  4 ++--
 app/addons/documents/views.js                   |  4 ++--
 assets/js/plugins/beautify.js                   | 17 ++++-------------
 3 files changed, 8 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/1be64cdd/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
index bf31ba2..d02971e 100644
--- a/app/addons/documents/templates/view_editor.html
+++ b/app/addons/documents/templates/view_editor.html
@@ -41,7 +41,7 @@ the License.
             <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
             <% } else { %>
             <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
-            <button class="beautify beautify_map button hidden beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+            <button class="beautify beautify_map button hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 
@@ -64,7 +64,7 @@ the License.
             <div class="js-editor" id="reduce-function"><%= langTemplates.reduce %></div>
             <% } else { %>
             <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
-            <button class="beautify beautify_reduce button hidden beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
+            <button class="beautify beautify_reduce button hide beautify-tooltip" type="button" data-toggle="tooltip" title="Reformat your minified code to make edits to it.">beautify this code</button>
             <% } %>
           </div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/1be64cdd/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index e2f5578..9516355 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1630,7 +1630,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.reduceEditor.render();
 
       if (this.reduceEditor.getLines() === 1){
-        this.$('.beautify_reduce').removeClass("hidden");
+        this.$('.beautify_reduce').removeClass("hide");
         $('.beautify-tooltip').tooltip();
       }
     },
@@ -1709,7 +1709,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       this.reduceEditor && this.reduceEditor.editSaved();
 
       if (this.mapEditor.getLines() === 1){
-        this.$('.beautify_map').removeClass("hidden");
+        this.$('.beautify_map').removeClass("hide");
         $('.beautify-tooltip').tooltip();
       }
     },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/1be64cdd/assets/js/plugins/beautify.js
----------------------------------------------------------------------
diff --git a/assets/js/plugins/beautify.js b/assets/js/plugins/beautify.js
index e934fe3..07b6617 100644
--- a/assets/js/plugins/beautify.js
+++ b/assets/js/plugins/beautify.js
@@ -1611,19 +1611,10 @@
     }
 
 
-    if (typeof define === "function") {
-        // Add support for require.js
-        if (typeof define.amd === "undefined") {
-            define(function(require, exports, module) {
-                exports.js_beautify = js_beautify;
-            });
-        } else {
-            // if is AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
-            define([], function() {
-                return js_beautify;
-            });
-        }
-
+    if (typeof define === "function" && define.amd) {
+        define([], function() {
+            return js_beautify;
+        });
     } else if (typeof exports !== "undefined") {
         // Add support for CommonJS. Just put this file somewhere on your require.paths
         // and you will be able to `var js_beautify = require("beautify").js_beautify`.


[26/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
ignoring index.css in concat:index_css

Which is why it was showing up twice.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/8fda7907
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/8fda7907
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/8fda7907

Branch: refs/heads/import-master
Commit: 8fda790792bb1e912e8a8c90ca49ec5ce8e2c155
Parents: 2123e61
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Thu Jan 16 14:59:27 2014 -0500
Committer: Garren Smith <ga...@gmail.com>
Committed: Fri Jan 17 09:39:57 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/8fda7907/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index b42e6b5..32065b6 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -210,7 +210,7 @@ module.exports = function(grunt) {
       },
 
       index_css: {
-        src: ["dist/debug/css/*.css", 'assets/css/*.css'],
+        src: ["dist/debug/css/*.css", '!dist/debug/css/index.css', 'assets/css/*.css'],
         dest: 'dist/debug/css/index.css'
       },
 


[47/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Add backbone.fetch-cache


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/f1115406
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/f1115406
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/f1115406

Branch: refs/heads/import-master
Commit: f11154060a4662b6e06af293de0f89d64c6edb4f
Parents: ffda485
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Feb 4 16:47:54 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Feb 4 16:47:54 2014 +0200

----------------------------------------------------------------------
 app/addons/databases/resources.js         |   8 +-
 app/addons/documents/resources.js         |  14 +-
 app/addons/documents/routes.js            |   2 +-
 app/addons/documents/views.js             |  22 +-
 app/config.js                             |   3 +-
 app/core/base.js                          |  27 ++-
 assets/js/plugins/backbone.fetch-cache.js | 311 +++++++++++++++++++++++++
 7 files changed, 365 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index 1b55f88..5fa931b 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -24,7 +24,7 @@ function(app, FauxtonAPI, Documents) {
 
   Databases.DocLimit = 20;
 
-  Databases.Model = Backbone.Model.extend({
+  Databases.Model = FauxtonAPI.Model.extend({
     initialize: function(options) {
       this.status = new Databases.Status({
         database: this
@@ -82,7 +82,7 @@ function(app, FauxtonAPI, Documents) {
     }
   });
 
-  Databases.Changes = Backbone.Collection.extend({
+  Databases.Changes = FauxtonAPI.Collection.extend({
 
     initialize: function(options) {
       this.database = options.database;
@@ -110,7 +110,7 @@ function(app, FauxtonAPI, Documents) {
     }
   });
 
-  Databases.Status = Backbone.Model.extend({
+  Databases.Status = FauxtonAPI.Model.extend({
     url: function() {
       return app.host + "/" + this.database.safeID();
     },
@@ -166,7 +166,7 @@ function(app, FauxtonAPI, Documents) {
   });
 
   // TODO: shared databases - read from the user doc
-  Databases.List = Backbone.Collection.extend({
+  Databases.List = FauxtonAPI.Collection.extend({
     model: Databases.Model,
     documentation: function(){
       return "all_dbs";

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 831d5e3..adfee1f 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -18,7 +18,7 @@ define([
 function(app, FauxtonAPI) {
   var Documents = FauxtonAPI.addon();
 
-  Documents.Doc = Backbone.Model.extend({
+  Documents.Doc = FauxtonAPI.Model.extend({
     idAttribute: "_id",
     documentation: function(){
       return "docs";
@@ -194,7 +194,7 @@ function(app, FauxtonAPI) {
     }
   });
 
-  Documents.DdocInfo = Backbone.Model.extend({
+  Documents.DdocInfo = FauxtonAPI.Model.extend({
     idAttribute: "_id",
     documentation: function(){
       return "docs";
@@ -224,7 +224,7 @@ function(app, FauxtonAPI) {
 
   });
 
-  Documents.ViewRow = Backbone.Model.extend({
+  Documents.ViewRow = FauxtonAPI.Model.extend({
     // this is a hack so that backbone.collections doesn't group 
     // these by id and reduce the number of items returned.
     idAttribute: "_id",
@@ -272,7 +272,7 @@ function(app, FauxtonAPI) {
 
   });
 
-  Documents.AllDocs = Backbone.Collection.extend({
+  Documents.AllDocs = FauxtonAPI.Collection.extend({
     model: Documents.Doc,
     documentation: function(){
       return "docs";
@@ -397,7 +397,7 @@ function(app, FauxtonAPI) {
     }
   });
 
-  Documents.IndexCollection = Backbone.Collection.extend({
+  Documents.IndexCollection = FauxtonAPI.Collection.extend({
     model: Documents.ViewRow,
     documentation: function(){
       return "docs";
@@ -527,7 +527,7 @@ function(app, FauxtonAPI) {
     // we can get the request duration
     fetch: function () {
       this.startTime = new Date().getTime();
-      return Backbone.Collection.prototype.fetch.call(this);
+      return FauxtonAPI.Collection.prototype.fetch.call(this);
     },
 
     allDocs: function(){
@@ -568,7 +568,7 @@ function(app, FauxtonAPI) {
   });
 
   
-  Documents.PouchIndexCollection = Backbone.Collection.extend({
+  Documents.PouchIndexCollection = FauxtonAPI.Collection.extend({
     model: Documents.ViewRow,
     documentation: function(){
       return "docs";

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 1510485..be9ce2f 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -182,7 +182,7 @@ function(app, FauxtonAPI, Documents, Databases) {
     },
 
     establish: function () {
-      return this.data.designDocs.fetch();
+      return this.data.designDocs.fetchOnce();
     },
 
     allDocs: function(databaseName, options) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 298cfb4..5476203 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -1803,11 +1803,31 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
   Views.Changes = FauxtonAPI.View.extend({
     template: "addons/documents/templates/changes",
 
+    initialize: function () {
+      var that = this;
+      this.listenTo( this.model.changes, 'change', function () {
+        console.log('render on change'); 
+        that.render();
+      });
+      this.listenTo( this.model.changes, 'cachesync', function () {
+        console.log('render on cachesync'); 
+        that.render();
+      });
+    },
+
     establish: function() {
-      return [ this.model.changes.fetch()];
+      return [ this.model.changes.fetchOnce({prefill: true,
+        success: function () {
+          console.log('hi ajax success');
+        },
+        prefillSuccess: function () {
+          console.log('hi prefill success');
+        }
+      })];
     },
 
     serialize: function () {
+      console.log('ss');
       return {
         changes: this.model.changes.toJSON(),
         database: this.model

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/config.js
----------------------------------------------------------------------
diff --git a/app/config.js b/app/config.js
index 98be9c6..a5d764f 100644
--- a/app/config.js
+++ b/app/config.js
@@ -30,7 +30,8 @@ require.config({
     spin: "../assets/js/libs/spin.min",
     d3: "../assets/js/libs/d3",
     "nv.d3": "../assets/js/libs/nv.d3",
-    "ace":"../assets/js/libs/ace"
+    "ace":"../assets/js/libs/ace",
+    "backbone.fetch-cache": "../assets/js/plugins/backbone.fetch-cache"
   },
 
   baseUrl: '/',

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 53316bc..6fe3261 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -12,10 +12,12 @@
 
 define([
   "backbone",
-  "plugins/backbone.layoutmanager"
+  "plugins/backbone.layoutmanager",
+  "backbone.fetch-cache"
 ],
 
-function(Backbone) {
+function(Backbone, LayoutManager, BackboneCache) {
+  console.log(BackboneCache);
   var FauxtonAPI = {
     //add default objects
     router: {
@@ -67,16 +69,25 @@ function(Backbone) {
     }
   });
 
+
   FauxtonAPI.Model = Backbone.Model.extend({
-    fetchOnce: function (opt) {
-      var options = _.extend({}, opt);
 
-      if (!this._deferred || this._deferred.state() === "rejected" || options.forceFetch ) {
-        this._deferred = this.fetch();
-      }
+  });
+
+  FauxtonAPI.Collection = Backbone.Collection.extend({
 
-      return this._deferred;
+  });
+
+  var caching = {
+    fetchOnce: function (opts) {
+      var options = _.defaults(opts || {}, this.cache, {cache: true});
+      console.log('opts', options);
+      return this.fetch(options);
     }
+  };
+
+  _.each([FauxtonAPI.Collection, FauxtonAPI.Model], function (ctor) {
+    _.extend(ctor.prototype, caching);
   });
 
   var extensions = _.extend({}, Backbone.Events);

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f1115406/assets/js/plugins/backbone.fetch-cache.js
----------------------------------------------------------------------
diff --git a/assets/js/plugins/backbone.fetch-cache.js b/assets/js/plugins/backbone.fetch-cache.js
new file mode 100644
index 0000000..c86a8b9
--- /dev/null
+++ b/assets/js/plugins/backbone.fetch-cache.js
@@ -0,0 +1,311 @@
+/*!
+  backbone.fetch-cache v1.3.0
+  by Andy Appleton - https://github.com/mrappleton/backbone-fetch-cache.git
+ */
+
+// AMD wrapper from https://github.com/umdjs/umd/blob/master/amdWebGlobal.js
+
+(function (root, factory) {
+  if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module and set browser global
+    define(['underscore', 'backbone', 'jquery'], function (_, Backbone, $) {
+      return (root.Backbone = factory(_, Backbone, $));
+    });
+  } else {
+    // Browser globals
+    root.Backbone = factory(root._, root.Backbone, root.jQuery);
+  }
+}(this, function (_, Backbone, $) {
+
+  // Setup
+  var superMethods = {
+    modelFetch: Backbone.Model.prototype.fetch,
+    modelSync: Backbone.Model.prototype.sync,
+    collectionFetch: Backbone.Collection.prototype.fetch
+  },
+  supportLocalStorage = (function() {
+    var supported = typeof window.localStorage !== 'undefined';
+    if (supported) {
+      try {
+        // impossible to write on some platforms when private browsing is on and
+        // throws an exception = local storage not supported.
+        localStorage.setItem("test_support", "test_support");
+        localStorage.removeItem("test_support");
+      } catch (e) {
+        supported = false;
+      }
+    }
+    return supported;
+  })();
+
+  Backbone.fetchCache = (Backbone.fetchCache || {});
+  Backbone.fetchCache._cache = (Backbone.fetchCache._cache || {});
+
+  Backbone.fetchCache.priorityFn = function(a, b) {
+    if (!a || !a.expires || !b || !b.expires) {
+      return a;
+    }
+
+    return a.expires - b.expires;
+  };
+
+  Backbone.fetchCache._prioritize = function() {
+    var sorted = _.values(this._cache).sort(this.priorityFn);
+    var index = _.indexOf(_.values(this._cache), sorted[0]);
+    return _.keys(this._cache)[index];
+  };
+
+  Backbone.fetchCache._deleteCacheWithPriority = function() {
+    Backbone.fetchCache._cache[this._prioritize()] = null;
+    delete Backbone.fetchCache._cache[this._prioritize()];
+    Backbone.fetchCache.setLocalStorage();
+  };
+
+  Backbone.fetchCache.getLocalStorageKey = function() {
+    return 'backboneCache';
+  };
+
+  if (typeof Backbone.fetchCache.localStorage === 'undefined') {
+    Backbone.fetchCache.localStorage = true;
+  }
+
+  // Shared methods
+  function getCacheKey(instance, opts) {
+    var url;
+
+    if(opts && opts.url) {
+      url = opts.url;
+    } else {
+      url = _.isFunction(instance.url) ? instance.url() : instance.url;
+    }
+
+    // Need url to use as cache key so return if we can't get it
+    if(!url) { return; }
+
+    if(opts && opts.data) {
+      return url + "?" + $.param(opts.data);
+    }
+    return url;
+  }
+
+  function setCache(instance, opts, attrs) {
+    opts = (opts || {});
+    var key = Backbone.fetchCache.getCacheKey(instance, opts),
+        expires = false;
+
+    // Need url to use as cache key so return if we can't get it
+    if (!key) { return; }
+
+    // Never set the cache if user has explicitly said not to
+    if (opts.cache === false) { return; }
+
+    // Don't set the cache unless cache: true or prefill: true option is passed
+    if (!(opts.cache || opts.prefill)) { return; }
+
+    if (opts.expires !== false) {
+      expires = (new Date()).getTime() + ((opts.expires || 5 * 60) * 1000);
+    }
+
+    Backbone.fetchCache._cache[key] = {
+      expires: expires,
+      value: attrs
+    };
+
+    Backbone.fetchCache.setLocalStorage();
+  }
+
+  function clearItem(key) {
+    if (_.isFunction(key)) { key = key(); }
+    delete Backbone.fetchCache._cache[key];
+    Backbone.fetchCache.setLocalStorage();
+  }
+
+  function setLocalStorage() {
+    if (!supportLocalStorage || !Backbone.fetchCache.localStorage) { return; }
+    try {
+      localStorage.setItem(Backbone.fetchCache.getLocalStorageKey(), JSON.stringify(Backbone.fetchCache._cache));
+    } catch (err) {
+      var code = err.code || err.number || err.message;
+      if (code === 22) {
+        this._deleteCacheWithPriority();
+      } else {
+        throw(err);
+      }
+    }
+  }
+
+  function getLocalStorage() {
+    if (!supportLocalStorage || !Backbone.fetchCache.localStorage) { return; }
+    var json = localStorage.getItem(Backbone.fetchCache.getLocalStorageKey()) || '{}';
+    Backbone.fetchCache._cache = JSON.parse(json);
+  }
+
+  function nextTick(fn) {
+    return window.setTimeout(fn, 0);
+  }
+
+  // Instance methods
+  Backbone.Model.prototype.fetch = function(opts) {
+    opts = _.defaults(opts || {}, { parse: true });
+    var key = Backbone.fetchCache.getCacheKey(this, opts),
+        data = Backbone.fetchCache._cache[key],
+        expired = false,
+        attributes = false,
+        deferred = new $.Deferred(),
+        self = this;
+
+    function setData() {
+      if (opts.parse) {
+        attributes = self.parse(attributes, opts);
+      }
+
+      self.set(attributes, opts);
+      if (_.isFunction(opts.prefillSuccess)) { opts.prefillSuccess(self, attributes, opts); }
+
+      // Trigger sync events
+      self.trigger('cachesync', self, attributes, opts);
+      self.trigger('sync', self, attributes, opts);
+
+      // Notify progress if we're still waiting for an AJAX call to happen...
+      if (opts.prefill) { deferred.notify(self); }
+      // ...finish and return if we're not
+      else {
+        if (_.isFunction(opts.success)) { opts.success(self, attributes, opts); }
+        deferred.resolve(self);
+      }
+    }
+
+    if (data) {
+      expired = data.expires;
+      expired = expired && data.expires < (new Date()).getTime();
+      attributes = data.value;
+    }
+
+    if (!expired && (opts.cache || opts.prefill) && attributes) {
+      // Ensure that cache resolution adhers to async option, defaults to true.
+      if (opts.async == null) { opts.async = true; }
+
+      if (opts.async) {
+        nextTick(setData);
+      } else {
+        setData();
+      }
+
+      if (!opts.prefill) {
+        return deferred.promise();
+      }
+    }
+
+    // Delegate to the actual fetch method and store the attributes in the cache
+    superMethods.modelFetch.apply(this, arguments)
+      // resolve the returned promise when the AJAX call completes
+      .done( _.bind(deferred.resolve, this, this) )
+      // Set the new data in the cache
+      .done( _.bind(Backbone.fetchCache.setCache, null, this, opts) )
+      // Reject the promise on fail
+      .fail( _.bind(deferred.reject, this, this) );
+
+    // return a promise which provides the same methods as a jqXHR object
+    return deferred.promise();
+  };
+
+  // Override Model.prototype.sync and try to clear cache items if it looks
+  // like they are being updated.
+  Backbone.Model.prototype.sync = function(method, model, options) {
+    // Only empty the cache if we're doing a create, update, patch or delete.
+    if (method === 'read') {
+      return superMethods.modelSync.apply(this, arguments);
+    }
+
+    var collection = model.collection,
+        keys = [],
+        i, len;
+
+    // Build up a list of keys to delete from the cache, starting with this
+    keys.push(Backbone.fetchCache.getCacheKey(model, options));
+
+    // If this model has a collection, also try to delete the cache for that
+    if (!!collection) {
+      keys.push(Backbone.fetchCache.getCacheKey(collection));
+    }
+
+    // Empty cache for all found keys
+    for (i = 0, len = keys.length; i < len; i++) { clearItem(keys[i]); }
+
+    return superMethods.modelSync.apply(this, arguments);
+  };
+
+  Backbone.Collection.prototype.fetch = function(opts) {
+    opts = _.defaults(opts || {}, { parse: true });
+    var key = Backbone.fetchCache.getCacheKey(this, opts),
+        data = Backbone.fetchCache._cache[key],
+        expired = false,
+        attributes = false,
+        deferred = new $.Deferred(),
+        self = this;
+
+    function setData() {
+      self[opts.reset ? 'reset' : 'set'](attributes, opts);
+      if (_.isFunction(opts.prefillSuccess)) { opts.prefillSuccess(self); }
+
+      // Trigger sync events
+      self.trigger('cachesync', self, attributes, opts);
+      self.trigger('sync', self, attributes, opts);
+
+      // Notify progress if we're still waiting for an AJAX call to happen...
+      if (opts.prefill) { deferred.notify(self); }
+      // ...finish and return if we're not
+      else {
+        if (_.isFunction(opts.success)) { opts.success(self, attributes, opts); }
+        deferred.resolve(self);
+      }
+    }
+
+    if (data) {
+      expired = data.expires;
+      expired = expired && data.expires < (new Date()).getTime();
+      attributes = data.value;
+    }
+
+    if (!expired && (opts.cache || opts.prefill) && attributes) {
+      // Ensure that cache resolution adhers to async option, defaults to true.
+      if (opts.async == null) { opts.async = true; }
+
+      if (opts.async) {
+        nextTick(setData);
+      } else {
+        setData();
+      }
+
+      if (!opts.prefill) {
+        return deferred.promise();
+      }
+    }
+
+    // Delegate to the actual fetch method and store the attributes in the cache
+    superMethods.collectionFetch.apply(this, arguments)
+      // resolve the returned promise when the AJAX call completes
+      .done( _.bind(deferred.resolve, this, this) )
+      // Set the new data in the cache
+      .done( _.bind(Backbone.fetchCache.setCache, null, this, opts) )
+      // Reject the promise on fail
+      .fail( _.bind(deferred.reject, this, this) );
+
+    // return a promise which provides the same methods as a jqXHR object
+    return deferred.promise();
+  };
+
+  // Prime the cache from localStorage on initialization
+  getLocalStorage();
+
+  // Exports
+
+  Backbone.fetchCache._superMethods = superMethods;
+  Backbone.fetchCache.setCache = setCache;
+  Backbone.fetchCache.getCacheKey = getCacheKey;
+  Backbone.fetchCache.clearItem = clearItem;
+  Backbone.fetchCache.setLocalStorage = setLocalStorage;
+  Backbone.fetchCache.getLocalStorage = getLocalStorage;
+
+  return Backbone;
+}));


[13/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
moving over post-addons refactor template changes


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/58f9e075
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/58f9e075
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/58f9e075

Branch: refs/heads/import-master
Commit: 58f9e075952419464f560baa2767ada6ba96d095
Parents: aa228e0
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Mon Jan 13 13:45:22 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 15:09:15 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/templates/advanced_options.html    | 5 +++--
 app/addons/documents/templates/all_docs_layout.html     | 2 +-
 app/addons/documents/templates/all_docs_number.html     | 4 +++-
 app/addons/documents/templates/duplicate_doc_modal.html | 2 +-
 app/addons/documents/templates/index_row_docular.html   | 5 +++--
 5 files changed, 11 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/58f9e075/app/addons/documents/templates/advanced_options.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/advanced_options.html b/app/addons/documents/templates/advanced_options.html
index 8e96574..e256325 100644
--- a/app/addons/documents/templates/advanced_options.html
+++ b/app/addons/documents/templates/advanced_options.html
@@ -67,8 +67,9 @@ the License.
           Limit:
           <select name="limit" class="input-small">
             <option>5</option>
-            <option selected="selected">10</option>
-            <option>25</option>
+            <option>10</option>
+            <option selected="selected">20</option>
+            <option>30</option>
             <option>50</option>
             <option>100</option>
           </select>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/58f9e075/app/addons/documents/templates/all_docs_layout.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_layout.html b/app/addons/documents/templates/all_docs_layout.html
index 526c200..6b4a31b 100644
--- a/app/addons/documents/templates/all_docs_layout.html
+++ b/app/addons/documents/templates/all_docs_layout.html
@@ -12,7 +12,7 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 <ul class="nav nav-tabs window-resizeable" id="db-views-tabs-nav">
-  <li><a id="toggle-query" class="fonticon-plus fonticon" href="#query" data-toggle="tab">Query Options</a></li>
+  <li><a id="toggle-query" class="fonticon-plus fonticon" href="#query" data-bypass="true" data-toggle="tab">Query Options</a></li>
 </ul>
 <div class="tab-content">
   <div class="tab-pane" id="query">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/58f9e075/app/addons/documents/templates/all_docs_number.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/all_docs_number.html b/app/addons/documents/templates/all_docs_number.html
index c4ea8f6..df8fe07 100644
--- a/app/addons/documents/templates/all_docs_number.html
+++ b/app/addons/documents/templates/all_docs_number.html
@@ -13,8 +13,10 @@ the License.
 -->
 <% if (totalRows === "unknown"){ %>
   Showing 0 documents. <a href="#/database/<%=database%>/new"> Create your first document.</a>
-<% } else { %>
+<% } else if (showNumbers) { %>
   Showing <%=offset%> - <%= numModels %> of <%= totalRows %> rows
+<% } else { %>
+  Showing <%=pageStart%> - <%= pageEnd %>
 <%}%>
 <% if (updateSeq) { %>
   -- Update Sequence: <%= updateSeq %>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/58f9e075/app/addons/documents/templates/duplicate_doc_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/duplicate_doc_modal.html b/app/addons/documents/templates/duplicate_doc_modal.html
index 3f374b6..dbb25bc 100644
--- a/app/addons/documents/templates/duplicate_doc_modal.html
+++ b/app/addons/documents/templates/duplicate_doc_modal.html
@@ -19,7 +19,7 @@ the License.
   </div>
   <div class="modal-body">
     <div id="modal-error" class="hide alert alert-error"/>
-    <form id="file-upload" class="form" method="post">
+    <form id="doc-duplicate" class="form" method="post">
       <p class="help-block">
       Set new documents ID:
       </p>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/58f9e075/app/addons/documents/templates/index_row_docular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html
index 3835453..f1b2217 100644
--- a/app/addons/documents/templates/index_row_docular.html
+++ b/app/addons/documents/templates/index_row_docular.html
@@ -11,8 +11,9 @@ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 License for the specific language governing permissions and limitations under
 the License.
 -->
-
-<td class="select"><input type="checkbox"></td>
+<% if (doc.isEditable()) { %>
+  <td class="select"><input type="checkbox"></td>
+<% } %>
 <td>
   <div>
     <pre class="prettyprint"><%- doc.prettyJSON() %></pre>


[49/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix failing grunt test


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/a668f210
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/a668f210
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/a668f210

Branch: refs/heads/import-master
Commit: a668f21043147a6256e78d4c5041b1020d547c48
Parents: 4b5735c
Author: Garren Smith <ga...@gmail.com>
Authored: Fri Feb 7 15:13:05 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Fri Feb 7 15:13:05 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a668f210/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index 9507a60..c087afa 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -426,7 +426,7 @@ module.exports = function(grunt) {
    */
   // clean out previous build artefactsa and lint
   grunt.registerTask('lint', ['clean', 'jshint']);
-  grunt.registerTask('test', ['lint', 'dependencies', 'test_inline']);
+  grunt.registerTask('test', ['lint', 'dependencies', 'gen_initialize:development', 'test_inline']);
   // lighter weight test task for use inside dev/watch
   grunt.registerTask('test_inline', ['mochaSetup','jst', 'concat:test_config_js','mocha_phantomjs']);
   // Fetch dependencies (from git or local dir), lint them and make load_addons


[45/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
fixed .css concat ordering in index.css

This change removes the loading of .css files
from /addons/**/assets/css/*.css. Putting those
back is an option, but since unused at present
I saw it as a separate case for adding back
if/when desired.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/c514de12
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/c514de12
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/c514de12

Branch: refs/heads/import-master
Commit: c514de12adeb4c070dbf199ce222ea80557e98a5
Parents: a15c507
Author: BigBlueHat <by...@bigbluehat.com>
Authored: Mon Feb 3 11:28:09 2014 -0500
Committer: BigBlueHat <by...@bigbluehat.com>
Committed: Mon Feb 3 11:29:00 2014 -0500

----------------------------------------------------------------------
 Gruntfile.js | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c514de12/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index 2c5a249..554eccb 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -64,7 +64,10 @@ module.exports = function(grunt) {
           "dist/debug/css/fauxton.css": "assets/less/fauxton.less"
         }
       },
-      img: ["assets/img/**"]
+      img: ["assets/img/**"],
+      // used in concat:index_css to keep file ordering intact
+      // fauxton.css should load first
+      css: ["dist/debug/css/fauxton.css"]
     };
     helper.processAddons(function(addon){
       // Less files from addons
@@ -75,6 +78,7 @@ module.exports = function(grunt) {
         theAssets.less.paths.push(lessPath);
         theAssets.less.files["dist/debug/css/" + addon.name + ".css"] =
           lessPath + "/" + addon.name + ".less";
+        theAssets.css.push("dist/debug/css/" + addon.name + ".css");
       }
       // Images
       root = addon.path || "app/addons/" + addon.name;
@@ -210,7 +214,7 @@ module.exports = function(grunt) {
       },
 
       index_css: {
-        src: ["dist/debug/css/*.css", '!dist/debug/css/index.css', 'assets/css/*.css'],
+        src: assets.css,
         dest: 'dist/debug/css/index.css'
       },
 


[07/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix css files for addon mode


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/13ef5d1f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/13ef5d1f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/13ef5d1f

Branch: refs/heads/import-master
Commit: 13ef5d1f886b2199d27e86020ef56a5ae544171b
Parents: 5ba0f8e
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 6 10:44:19 2014 -0500
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Jan 13 11:19:11 2014 +0200

----------------------------------------------------------------------
 app/addons/config/assets/less/config.less       |  3 ---
 app/addons/documents/assets/less/documents.less | 11 +++++++++++
 app/addons/fauxton/base.js                      | 19 +++++++++----------
 assets/less/fauxton.less                        |  6 +-----
 4 files changed, 21 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/13ef5d1f/app/addons/config/assets/less/config.less
----------------------------------------------------------------------
diff --git a/app/addons/config/assets/less/config.less b/app/addons/config/assets/less/config.less
index 8495b69..737beb4 100644
--- a/app/addons/config/assets/less/config.less
+++ b/app/addons/config/assets/less/config.less
@@ -10,14 +10,11 @@
  *  License for the specific language governing permissions and limitations under
  *  the License.
  */
-
 .config-item {
   height: 41px;
 
   .edit-button {
     float: right;
-    .btn;
-    .btn-mini;
     display:none;
   }
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/13ef5d1f/app/addons/documents/assets/less/documents.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
new file mode 100644
index 0000000..ff9e88c
--- /dev/null
+++ b/app/addons/documents/assets/less/documents.less
@@ -0,0 +1,11 @@
+/*ALL DOCS TABLE*/
+tr.all-docs-item{
+  border: none;
+  background: transparent;
+    .btn-group {
+        position: absolute;
+        right: 0;
+        top: 6px;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/13ef5d1f/app/addons/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js
index aa4c3d4..1811e84 100644
--- a/app/addons/fauxton/base.js
+++ b/app/addons/fauxton/base.js
@@ -11,19 +11,18 @@
 // the License.
 
 define([
-       "app",
-        // Libs
-       "backbone",
-	   "resizeColumns",
+  "app",
+  // Libs
+  "backbone",
+  "resizeColumns",
 ],
 
 function(app, Backbone, resizeColumns) {
 
-
   //resizeAnimation
   app.resizeColumns = new resizeColumns({});
   app.resizeColumns.onResizeHandler();
- 
+
   var Fauxton = {};
 
   Fauxton.Breadcrumbs = Backbone.View.extend({
@@ -136,7 +135,7 @@ function(app, Backbone, resizeColumns) {
           if(!$(e.target).is('a')){
             toggleMenu();
           }
-         }
+        }
       });
 
       function toggleMenu(){
@@ -147,8 +146,8 @@ function(app, Backbone, resizeColumns) {
 
       $('#primary-navbar').on("click", ".nav a", function(){
         if (!($selectorList.hasClass('closeMenu'))){
-        setTimeout(
-          function(){
+          setTimeout(
+            function(){
             $selectorList.addClass('closeMenu');
             app.resizeColumns.onResizeHandler();
           },3000);
@@ -266,6 +265,6 @@ function(app, Backbone, resizeColumns) {
     }
   });
 
-  
+
   return Fauxton;
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/13ef5d1f/assets/less/fauxton.less
----------------------------------------------------------------------
diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less
index d41780a..e1cfa06 100644
--- a/assets/less/fauxton.less
+++ b/assets/less/fauxton.less
@@ -911,11 +911,7 @@ pre.prettyprint {
   color: #333333;
 }
 
-/*ALL DOCS TABLE*/
-tr.all-docs-item{
-  border: none;
-  background: transparent;
-}
+
 
 /*logs*/
 #log-sidebar{


[16/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fix for the link to edit docs on reductions


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/7e2c615a
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/7e2c615a
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/7e2c615a

Branch: refs/heads/import-master
Commit: 7e2c615a43b399145b65c4bcde509000cbf6853c
Parents: fb90049
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 16:19:29 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 16:19:29 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/resources.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/7e2c615a/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 0fd99f1..831d5e3 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -238,8 +238,6 @@ function(app, FauxtonAPI) {
       return "docs";
     },
     url: function(context) {
-      if (!this.isEditable()) return false;
-
       return this.collection.database.url(context) + "/" + this.safeID();
     },
 
@@ -247,7 +245,9 @@ function(app, FauxtonAPI) {
       return this.docType() != "reduction";
     },
     safeID: function() {
-      return app.utils.safeURLName(this.id);
+      var id = this.id || this.get("id");
+
+      return app.utils.safeURLName(id);
     },
 
     prettyJSON: function() {


[04/52] [abbrv] Fauxton: move modules to addons

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/index_row_tabular.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/index_row_tabular.html b/app/addons/documents/templates/index_row_tabular.html
new file mode 100644
index 0000000..f5f68fa
--- /dev/null
+++ b/app/addons/documents/templates/index_row_tabular.html
@@ -0,0 +1,25 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<td class="select"><input type="checkbox"></td>
+<td>
+  <div>
+    <pre class="prettyprint"><%- JSON.stringify(doc.get("key")) %></pre>
+  </div>
+</td>
+<td>
+  <div>
+    <pre class="prettyprint"><%- JSON.stringify(doc.get("value")) %></pre>
+  </div>
+</td>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/jumpdoc.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/jumpdoc.html b/app/addons/documents/templates/jumpdoc.html
new file mode 100644
index 0000000..43fdb9c
--- /dev/null
+++ b/app/addons/documents/templates/jumpdoc.html
@@ -0,0 +1,19 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<form id="jump-to-doc" class="form-inline input-append" >
+  <input type="text" id="jump-to-doc-id" class="input-large" placeholder="Document ID"></input>
+
+  <button class="fonticon-search btn button red " type="submit"></button>
+</form>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/search.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/search.html b/app/addons/documents/templates/search.html
new file mode 100644
index 0000000..bb84891
--- /dev/null
+++ b/app/addons/documents/templates/search.html
@@ -0,0 +1,15 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<input id="searchbox" type="text" class="span12" placeholder="Search by doc id, view key or search index">
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/sidebar.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/sidebar.html b/app/addons/documents/templates/sidebar.html
new file mode 100644
index 0000000..8a73ae9
--- /dev/null
+++ b/app/addons/documents/templates/sidebar.html
@@ -0,0 +1,67 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div id="sidenav">
+  <header class="row-fluid">
+    <div class="span12">
+      <div class="btn-group">
+        <button class="btn dropdown-toggle dropdown-toggle-btn" data-toggle="dropdown">
+          Docs
+          <span class="caret"></span>
+        </button>
+        <ul class="dropdown-menu">
+          <!-- dropdown menu links -->
+          <li><a class="icon-file" href="<%= db_url %>">Docs</a></li>
+          <li><a class="icon-lock" href="<%= permissions_url %>">Permissions</a></li>
+          <li><a class="icon-forward" href="<%= changes_url %>">Changes</a></li>
+          <% _.each(docLinks, function (link) { %>
+          <li><a class="<%= link.icon %>" href="<%= database_url + '/' + link.url %>"><%= link.title %></a></li>
+          <% }); %>
+        </ul>
+      </div>
+
+      <div class="btn-group">
+        <button class="btn dropdown-toggle dropdown-toggle-btn" data-toggle="dropdown">
+          New
+          <span class="caret"></span>
+        </button>
+        <ul class="dropdown-menu">
+          <!-- dropdown menu links -->
+          <li>
+          <a id="doc" href="#<%= database.url('app') %>/new">Document</a>
+          </li>
+          <li>
+          <a href="#<%= database.url('app') %>/new_view">Secondary Index</a>
+           <% _.each(newLinks, function (item) { %>
+           <a href="#<%= database.url('app') %>/<%=item.url%>"> <%= item.name %></a>
+           <% }); %>
+          </li>
+        </ul>
+      </div>
+        <button id="delete-database" class="btn"><i class="icon-trash"></i> Database</button>
+    </div>
+  </header>
+
+  <nav>
+    <ul class="nav nav-list">
+      <li class="active"><a id="all-docs" href="#<%= database.url('index') %>?limit=<%= docLimit %>" class="toggle-view"> All documents</a></li>
+      <li><a id="design-docs" href='#<%= database.url("index") %>?limit=<%= docLimit %>&startkey="_design"&endkey="_e"'  class="toggle-view"> All design docs</a></li>
+    </ul>
+    <ul class="nav nav-list views">
+      <li class="nav-header">Secondary Indexes</li>
+      <li><a id="new-view" href="#<%= database.url('app') %>/new_view" class="new"><i class="icon-plus"></i> New</a></li>
+    </ul>
+    <div id="extension-navs"></div>
+  </nav>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/tabs.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/tabs.html b/app/addons/documents/templates/tabs.html
new file mode 100644
index 0000000..f8b0c4b
--- /dev/null
+++ b/app/addons/documents/templates/tabs.html
@@ -0,0 +1,18 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<ul class="nav nav-tabs">
+  <li class="active"><a href="<%= db_url %>">Docs</a></li>
+  <li id="changes"><a  href="<%= changes_url %>">Changes</a></li>
+</ul>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/upload_modal.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/upload_modal.html b/app/addons/documents/templates/upload_modal.html
new file mode 100644
index 0000000..9a5c5cd
--- /dev/null
+++ b/app/addons/documents/templates/upload_modal.html
@@ -0,0 +1,42 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="modal hide fade">
+  <div class="modal-header">
+    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+    <h3>Upload an Attachment</h3>
+  </div>
+  <div class="modal-body">
+    <div id="modal-error" class="alert alert-error hide" style="font-size: 16px;"> </div>
+    <form id="file-upload" class="form" method="post">
+      <p class="help-block">
+      Please select the file you want to upload as an attachment to this document. 
+      Please note that this will result in the immediate creation of a new revision of the document, 
+      so it's not necessary to save the document after the upload.
+      </p>
+      <input id="_attachments" type="file" name="_attachments">
+      <input id="_rev" type="hidden" name="_rev" value="" >
+      <br/>
+    </form>
+
+    <div class="progress progress-info">
+      <div class="bar" style="width: 0%"></div>
+    </div>
+  </div>
+  <div class="modal-footer">
+    <a href="#" data-dismiss="modal" data-bypass="true" class="btn button cancel-button outlineGray fonticon-circle-x">Cancel</a>
+    <a href="#" id="upload-btn" data-bypass="true" class="btn btn-primary button green save fonticon-circle-check">Upload</a>
+  </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/templates/view_editor.html
----------------------------------------------------------------------
diff --git a/app/addons/documents/templates/view_editor.html b/app/addons/documents/templates/view_editor.html
new file mode 100644
index 0000000..ddb5a0c
--- /dev/null
+++ b/app/addons/documents/templates/view_editor.html
@@ -0,0 +1,87 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+<div class="row">
+  <ul class="nav nav-tabs" id="db-views-tabs-nav">
+    <li class="active"> <a data-bypass="true" id="index-nav" class="fonticon-wrench fonticon" data-toggle="tab" href="#index"><% if (newView) { %>Create Index <% } else { %>Edit Index <% } %></a></li>
+    <% if (!newView) { %>
+    <li><a data-bypass="true" id="query-nav" class="fonticon-plus fonticon" href="#query" data-toggle="tab">Query Options</a></li>
+    <li><a data-bypass="true" id="meta-nav" href="#metadata" data-toggle="tab">Design Doc Metadata</a></li>
+    <% } %>
+  </ul>
+  <div class="all-docs-list errors-container"></div>
+  <div class="tab-content">
+    <div class="tab-pane active" id="index">
+      <div id="define-view" class="ddoc-alert well">
+        <div class="errors-container"></div>
+        <form class="form-horizontal view-query-save">
+
+          <div class="control-group design-doc-group">
+          </div>
+
+          <div class="control-group">
+            <label for="index-name">Index name <a href="<%=getDocUrl('view_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+            <input type="text" id="index-name" value="<%= viewName %>" placeholder="Index name" />
+          </div>
+
+
+          <div class="control-group">
+            <label for="map-function">Map function <a href="<%=getDocUrl('map_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+            <% if (newView) { %>
+            <div class="js-editor" id="map-function"><%= langTemplates.map %></div>
+            <% } else { %>
+            <div class="js-editor" id="map-function"><%- ddoc.get('views')[viewName].map %></div>
+            <% } %>
+          </div>
+
+
+          <div class="control-group">
+            <label for="reduce-function-selector">Reduce (optional) <a href="<%=getDocUrl('reduce_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+
+            <select id="reduce-function-selector">
+              <option value="" <%= !reduceFunStr ? 'selected="selected"' : '' %>>None</option>
+              <% _.each(["_sum", "_count", "_stats"], function(reduce) { %>
+              <option value="<%= reduce %>" <% if (reduce == reduceFunStr) { %>selected<% } %>><%= reduce %></option>
+              <% }) %>
+              <option value="CUSTOM" <% if (isCustomReduce) { %>selected<% } %>>Custom Reduce function</option>
+            </select>
+          </div>
+
+          <div class="control-group reduce-function">
+            <label for="reduce-function">Custom Reduce function</label>
+            <% if (newView) { %>
+            <div class="js-editor" id="reduce-function"><%= langTemplates.reduce %></div>
+            <% } else { %>
+            <div class="js-editor" id="reduce-function"><%- ddoc.get('views')[viewName].reduce %></div>
+            <% } %>
+          </div>
+
+          <div class="control-group">
+            <button class="button green save fonticon-circle-check">Save &amp; Build Index</button>
+            <button class="button btn-info preview">Preview</button>
+            <% if (!newView) { %>
+            <button class="button delete outlineGray fonticon-circle-x">Delete</button>
+            <% } %>
+          </div>
+          <div class="clearfix"></div>
+        </form>
+      </div>
+    </div>
+    <div class="tab-pane" id="metadata">
+      <div id="ddoc-info" class="well"> </div>
+    </div>
+    <div class="tab-pane" id="query">
+    </div>
+  </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/tests/resourcesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/resourcesSpec.js b/app/addons/documents/tests/resourcesSpec.js
new file mode 100644
index 0000000..380a4e4
--- /dev/null
+++ b/app/addons/documents/tests/resourcesSpec.js
@@ -0,0 +1,84 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+       'addons/documents/resources',
+      'testUtils'
+], function (Models, testUtils) {
+  var assert = testUtils.assert;
+
+  describe('IndexCollection', function () {
+    var collection;
+    beforeEach(function () {
+      collection = new Models.IndexCollection([{
+        id:'myId1',
+        doc: 'num1'
+      },
+      {
+        id:'myId2',
+        doc: 'num2'
+      }], {
+        database: {id: 'databaseId', safeID: function () { return this.id; }},
+        design: '_design/myDoc'
+      });
+
+    });
+
+    it('Should return urlNext', function () {
+      var url = collection.urlNextPage(20);
+
+      assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=21&reduce=false&startkey_docid=myId2&startkey=');
+
+    });
+
+    it('Should return urlPrevious', function () {
+      var url = collection.urlPreviousPage(20, {limit: 21, reduce: false,  startkey_docid: "myId1",startkey:"myId1"} );
+
+      assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=20&reduce=false&startkey_docid=myId1&startkey=myId1');
+
+    });
+
+  });
+
+  describe('AllDocs', function () {
+    var collection;
+    beforeEach(function () {
+      collection = new Models.AllDocs([{
+        _id:'myId1',
+        doc: 'num1'
+      },
+      {
+        _id:'myId2',
+        doc: 'num2'
+      }], {
+        database: {id: 'databaseId', safeID: function () { return this.id; }},
+        params: {limit: 20}
+      });
+
+    });
+
+    it('Should return urlNext', function () {
+      var url = collection.urlNextPage(20);
+
+      assert.equal(url, 'database/databaseId/_all_docs?limit=21&startkey_docid=%22myId2%22&startkey=%22myId2%22');
+
+    });
+
+     it('Should return urlPrevious', function () {
+      var url = collection.urlPreviousPage(20, {limit: 21, startkey_docid: "myId1",startkey:"myId1"} );
+      assert.equal(url, 'database/databaseId/_all_docs?limit=20&startkey_docid=myId1&startkey=myId1');
+    });
+
+
+  });
+
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
new file mode 100644
index 0000000..97d58e3
--- /dev/null
+++ b/app/addons/documents/views.js
@@ -0,0 +1,1855 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+
+       "api",
+       "addons/fauxton/components",
+
+       "addons/documents/resources",
+       "addons/databases/resources",
+       "addons/pouchdb/base",
+
+       // Libs
+       "resizeColumns",
+
+       // Plugins
+       "plugins/prettify"
+
+],
+
+function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns) {
+  var Views = {};
+  Views.Tabs = FauxtonAPI.View.extend({
+    template: "templates/documents/tabs",
+    initialize: function(options){
+      this.collection = options.collection;
+      this.database = options.database;
+      this.active_id = options.active_id;
+    },
+
+    events: {
+      "click #delete-database": "delete_database"
+    },
+
+    serialize: function () {
+      return {
+        // TODO make this not hard coded here
+        changes_url: '#' + this.database.url('changes'),
+        db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
+      };
+    },
+
+    beforeRender: function(manage) {
+      this.insertView("#search", new Views.SearchBox({
+        collection: this.collection,
+        database: this.database.id
+      }));
+    },
+
+    afterRender: function () {
+      if (this.active_id) {
+        this.$('.active').removeClass('active');
+        this.$('#'+this.active_id).addClass('active');
+      }
+    },
+
+    delete_database: function (event) {
+      event.preventDefault();
+
+      var result = confirm("Are you sure you want to delete this database?");
+
+      if (!result) { return; }
+      FauxtonAPI.addNotification({
+        msg: "Deleting your database...",
+        type: "error"
+      });
+      return this.database.destroy().done(function () {
+        app.router.navigate('#/_all_dbs', {trigger: true});
+      });
+    }
+  });
+
+  Views.SearchBox = FauxtonAPI.View.extend({
+    template: "templates/documents/search",
+    tagName: "form",
+    initialize: function(options){
+      this.collection = options.collection;
+      this.database = options.database;
+    },
+    afterRender: function(){
+      var collection = this.collection;
+      var form = this.$el;
+      var searchbox = form.find("input#searchbox");
+      var database = this.database;
+
+      form.submit(function(evt){
+        evt.preventDefault();
+        var viewname = form.find("input#view").val().split('/');
+        var url = "#database/" + database + "/_design/";
+        url += viewname[0] + "/_view/" + viewname[1];
+        if (searchbox.val() !== ""){
+          // TODO: this'll need to work when val() is a number etc.
+          url += '?startkey="' + searchbox.val() + '"';
+        }
+        FauxtonAPI.navigate(url);
+      });
+
+      searchbox.typeahead({
+        source: function(query, process) {
+          // TODO: include _all_docs and view keys somehow
+          var views = _.map(collection.pluck('doc'), function(d){
+            return _.map(_.keys(d.views), function(view){
+              return d._id.split('/')[1] + "/" + view;
+            });
+          });
+          return _.flatten(views);
+        },
+        minLength: 3,
+        updater: function(item){
+          // TODO: some way to return the original search box
+          this.$element.removeClass('span12');
+          this.$element.addClass('span6');
+          this.$element.attr('placeholder', 'Search by view key');
+          $('<span class="add-on span6">' + item +'</span>').insertBefore(this.$element);
+          $('<input type="hidden" id="view" value="' + item +'"/>').insertBefore(this.$element);
+          // Remove the type ahead for now
+          $('.typehead').unbind();
+        }
+      });
+    }
+  });
+
+  Views.UploadModal = FauxtonAPI.View.extend({
+    template: "templates/documents/upload_modal",
+
+    disableLoader: true,
+    
+    initialize: function (options) {
+      _.bindAll(this);
+    },
+
+    events: {
+      "click a#upload-btn": "uploadFile"
+    },
+
+    uploadFile: function (event) {
+      event.preventDefault();
+
+      var docRev = this.model.get('_rev'),
+          that = this,
+          $form = this.$('#file-upload');
+
+      if (!docRev) {
+        return this.set_error_msg('The document needs to be saved before adding an attachment.');
+      }
+
+      if ($('input[type="file"]')[0].files.length === 0) {
+        return this.set_error_msg('Selected a file to be uploaded.');
+      }
+
+      this.$('#_rev').val(docRev);
+
+      $form.ajaxSubmit({
+        url: this.model.url(),
+        type: 'POST',
+        beforeSend: this.beforeSend,
+        uploadProgress: this.uploadProgress,
+        success: this.success,
+        error: function (resp) {
+          console.log('ERR on upload', resp);
+          return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
+        }
+      });
+    },
+
+    success: function (resp) {
+      var hideModal = this.hideModal,
+          $form = this.$('#file-upload');
+
+      FauxtonAPI.triggerRouteEvent('reRenderDoc');
+      //slight delay to make this transistion a little more fluid and less jumpy
+      setTimeout(function () {
+        $form.clearForm();
+        hideModal();
+        $('.modal-backdrop').remove();
+      }, 1000);
+    },
+
+    uploadProgress: function(event, position, total, percentComplete) {
+      this.$('.bar').css({width: percentComplete + '%'});
+    },
+
+    beforeSend: function () {
+      this.$('.progress').removeClass('hide');
+    },
+
+    showModal: function () {
+      this.$('.bar').css({width: '0%'});
+      this.$('.progress').addClass('hide');
+      this.clear_error_msg();
+      this.$('.modal').modal();
+      // hack to get modal visible 
+      $('.modal-backdrop').css('z-index',1025);
+    },
+
+    hideModal: function () {
+      this.$('.modal').modal('hide');
+    },
+
+    set_error_msg: function (msg) {
+      var text;
+      if (typeof(msg) == 'string') {
+        text = msg;
+      } else {
+        text = JSON.parse(msg.responseText).reason;
+      }
+      this.$('#modal-error').text(text).removeClass('hide');
+    },
+
+    clear_error_msg: function () {
+      this.$('#modal-error').text(' ').addClass('hide');
+    },
+
+    serialize: function () {
+      return this.model.toJSON();
+    }
+  });
+
+  Views.DuplicateDocModal = FauxtonAPI.View.extend({
+    template: "templates/documents/duplicate_doc_modal",
+
+    initialize: function () {
+      _.bindAll(this);
+    },
+
+    events: {
+      "click #duplicate-btn":"duplicate"
+
+    },
+
+    duplicate: function (event) {
+      event.preventDefault();
+      var newId = this.$('#dup-id').val(),
+          encodedID = app.mixins.safeURLName(newId);
+
+      this.hideModal();
+      FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
+    },
+
+    _showModal: function () {
+      this.$('.bar').css({width: '0%'});
+      this.$('.progress').addClass('hide');
+      this.clear_error_msg();
+      this.$('.modal').modal();
+      // hack to get modal visible 
+      $('.modal-backdrop').css('z-index',1025);
+    },
+
+    showModal: function () {
+      var showModal = this._showModal,
+          setDefaultIdValue = this.setDefaultIdValue,
+          uuid = new FauxtonAPI.UUID();
+
+      uuid.fetch().then(function () {
+        setDefaultIdValue(uuid.next());
+        showModal();
+      });
+    },
+
+    setDefaultIdValue: function (id) {
+      this.$('#dup-id').val(id);
+    },
+
+    hideModal: function () {
+      this.$('.modal').modal('hide');
+    },
+
+    set_error_msg: function (msg) {
+      var text;
+      if (typeof(msg) == 'string') {
+        text = msg;
+      } else {
+        text = JSON.parse(msg.responseText).reason;
+      }
+      this.$('#modal-error').text(text).removeClass('hide');
+    },
+
+    clear_error_msg: function () {
+      this.$('#modal-error').text(' ').addClass('hide');
+    },
+
+    serialize: function () {
+      return this.model.toJSON();
+    }
+
+  });
+
+  Views.FieldEditorTabs = FauxtonAPI.View.extend({
+    template: "templates/documents/doc_field_editor_tabs",
+    disableLoader: true,
+    initialize: function(options) {
+      this.selected = options.selected;
+    },
+
+    events: {
+    },
+    updateSelected: function (selected) {
+      this.selected = selected;
+      this.$('.active').removeClass('active');
+      this.$('#'+this.selected).addClass('active');
+    },
+
+    serialize: function() {
+      var selected = this.selected;
+      return {
+        doc: this.model,
+        isNewDoc: this.model.isNewDoc(),
+        isSelectedClass: function(item) {
+          return item && item === selected ? "active" : "";
+        }
+      };
+    },
+
+    establish: function() {
+      return [this.model.fetch()];
+    }
+  });
+
+  Views.Document = FauxtonAPI.View.extend({
+    template: "templates/documents/all_docs_item",
+    tagName: "tr",
+    className: "all-docs-item",
+
+    events: {
+      "click button.delete": "destroy",
+      "dblclick pre.prettyprint": "edit"
+    },
+
+    attributes: function() {
+      return {
+        "data-id": this.model.id
+      };
+    },
+
+    serialize: function() {
+      return {
+        doc: this.model
+      };
+    },
+
+    establish: function() {
+      return [this.model.fetch()];
+    },
+
+    edit: function(event) {
+      event.preventDefault();
+      FauxtonAPI.navigate("#" + this.model.url('app'));
+    },
+
+    destroy: function(event) {
+      event.preventDefault();
+      var that = this;
+
+      if (!window.confirm("Are you sure you want to delete this doc?")) {
+        return false;
+      }
+
+      this.model.destroy().then(function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Succesfully destroyed your doc"
+        });
+        that.$el.fadeOut(function () {
+          that.remove();
+        });
+
+        that.model.collection.remove(that.model.id);
+        if (!!that.model.id.match('_design')) {
+          FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
+        }
+      }, function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Failed to destroy your doc!",
+          type: "error"
+        });
+      });
+    }
+  });
+
+  Views.Row = FauxtonAPI.View.extend({
+    template: "templates/documents/index_row_docular",
+    tagName: "tr",
+
+    events: {
+      "click button.delete": "destroy"
+    },
+
+    destroy: function (event) {
+      event.preventDefault(); 
+      
+      window.alert('Cannot delete a document generated from a view.');
+    },
+
+    serialize: function() {
+      return {
+        doc: this.model
+      };
+    }
+  });
+
+  Views.IndexItem = FauxtonAPI.View.extend({
+    template: "templates/documents/index_menu_item",
+    tagName: "li",
+
+    initialize: function(options){
+      this.index = options.index;
+      this.ddoc = options.ddoc;
+      this.database = options.database;
+      this.selected = !! options.selected;
+    },
+
+    serialize: function() {
+      return {
+        index: this.index,
+        ddoc: this.ddoc,
+        database: this.database,
+        index_clean: app.mixins.removeSpecialCharacters(this.index),
+        ddoc_clean: app.mixins.removeSpecialCharacters(this.ddoc), 
+        index_encoded: app.mixins.safeURLName(this.index),
+        ddoc_encoded: app.mixins.safeURLName(this.ddoc),
+        database_encoded: app.mixins.safeURLName(this.database),
+        selected: this.selected
+      };
+    },
+
+    afterRender: function() {
+      if (this.selected) {
+        $("#sidenav ul.nav-list li").removeClass("active");
+        this.$el.addClass("active");
+      }
+    }
+  });
+
+  Views.AllDocsNumber = FauxtonAPI.View.extend({
+    template: "templates/documents/all_docs_number",
+
+    initialize: function (options) {
+      this.newView = options.newView || false;
+      this.showNumbers = options.showNumbers;
+      this.pagination = options.pagination;
+      
+      this.listenTo(this.collection, 'totalRows:decrement', this.render);
+    },
+
+    serialize: function () {
+       var totalRows = 0,
+          recordStart = 0,
+          updateSeq = false,
+          pageStart = 0,
+          pageEnd = 20;
+
+      if (!this.newView) {
+        totalRows = this.collection.totalRows();
+        updateSeq = this.collection.updateSeq();
+      }
+
+      recordStart = this.collection.recordStart();
+      if (this.pagination) {
+        pageStart = this.pagination.pageStart();
+        pageEnd =  this.pagination.pageEnd();
+      }
+
+      return {
+        database: app.mixins.safeURLName(this.collection.database.id),
+        updateSeq: updateSeq,
+        offset: recordStart,
+        totalRows: totalRows,
+        showNumbers: this.showNumbers,
+        numModels: this.collection.models.length + recordStart - 1,
+        pageStart: pageStart,
+        pageEnd: pageEnd
+      };
+    }
+
+  });
+
+  Views.AllDocsLayout = FauxtonAPI.View.extend({
+    template: "templates/documents/all_docs_layout",
+    className: "row",
+
+    initialize: function (options) {
+      this.database = options.database;
+      this.params = options.params;
+    },
+
+    events: {
+      'click #toggle-query': "toggleQuery"
+    },
+
+    toggleQuery: function (event) {
+      $('#dashboard-content').scrollTop(0);
+      this.$('#query').toggle('fast');
+    },
+
+    beforeRender: function () {
+      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
+        updateViewFn: this.updateAllDocs,
+        previewFn: this.previewView,
+        hasReduce: false,
+        showPreview: false,
+        database: this.database
+      }));
+
+      this.$('#query').hide();
+    },
+
+    afterRender: function () {
+      if (this.params) {
+        this.advancedOptions.updateFromParams(this.params);
+      }
+
+    },
+
+    updateAllDocs: function (event, paramInfo) {
+      event.preventDefault();
+
+      var errorParams = paramInfo.errorParams,
+          params = paramInfo.params;
+
+      if (_.any(errorParams)) {
+        _.map(errorParams, function(param) {
+
+          // TODO: Where to add this error?
+          // bootstrap wants the error on a control-group div, but we're not using that
+          //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
+          return FauxtonAPI.addNotification({
+            msg: "JSON Parse Error on field: "+param.name,
+            type: "error",
+            selector: ".advanced-options .errors-container"
+          });
+        });
+        FauxtonAPI.addNotification({
+          msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
+          type: "warning",
+          selector: ".advanced-options .errors-container"
+        });
+
+        return false;
+      }
+
+      var fragment = window.location.hash.replace(/\?.*$/, '');
+      fragment = fragment + '?' + $.param(params);
+      FauxtonAPI.navigate(fragment, {trigger: false});
+
+      FauxtonAPI.triggerRouteEvent('updateAllDocs', {allDocs: true});
+    },
+
+    previewView: function (event) {
+      event.preventDefault();
+    }
+
+  });
+
+  // TODO: Rename to reflect that this is a list of rows or documents
+  Views.AllDocsList = FauxtonAPI.View.extend({
+    template: "templates/documents/all_docs_list",
+    events: {
+      "click button.all": "selectAll",
+      "click button.bulk-delete": "bulkDelete",
+      "click #collapse": "collapse",
+      "change .row-select":"toggleTrash"
+    },
+
+    toggleTrash: function () {
+      if (this.$('.row-select:checked').length > 0) {
+        this.$('.bulk-delete').removeClass('disabled');
+      } else {
+        this.$('.bulk-delete').addClass('disabled');
+      }
+    },
+
+    initialize: function(options){
+      this.nestedView = options.nestedView || Views.Document;
+      this.rows = {};
+      this.viewList = !! options.viewList;
+      this.database = options.database;
+      if (options.ddocInfo) {
+        this.designDocs = options.ddocInfo.designDocs;
+        this.ddocID = options.ddocInfo.id;
+      }
+      this.newView = options.newView || false;
+      this.expandDocs = true;
+    },
+
+    establish: function() {
+      if (this.newView) { return null; }
+
+      return this.collection.fetch({reset: true}).fail(function() {
+        // TODO: handle error requests that slip through
+        // This should just throw a notification, not break the page
+        console.log("ERROR: ", arguments);
+      });
+    },
+
+    selectAll: function(evt){
+      $('.all-docs').find("input:checkbox").prop('checked', !$(evt.target).hasClass('active')).trigger('change');
+    },
+
+    serialize: function() {
+      var requestDuration = false;
+
+      if (this.collection.requestDurationInString) {
+        requestDuration = this.collection.requestDurationInString();
+      }
+
+      return {
+        viewList: this.viewList,
+        requestDuration: requestDuration,
+        expandDocs: this.expandDocs
+      };
+    },
+
+    collapse: function (event) {
+      event.preventDefault();
+
+      if (this.expandDocs) {
+        this.expandDocs = false;
+      } else {
+        this.expandDocs = true;
+      }
+
+      this.render();
+    },
+
+    /*
+     * TODO: this should be reconsidered
+     * This currently performs delete operations on the model level,
+     * when we could be using bulk docs with _deleted = true. Using
+     * individual models is cleaner from a backbone standpoint, but
+     * not from the couchdb api.
+     * Also, the delete method is naive and leaves the body intact,
+     * when we should switch the doc to only having id/rev/deleted.
+     */
+    bulkDelete: function() {
+      var that = this;
+      // yuck, data binding ftw?
+      var eles = this.$el.find("input.row-select:checked")
+                         .parents("tr.all-docs-item")
+                         .map(function(e) { return $(this).attr("data-id"); })
+                         .get();
+
+      if (eles.length === 0 || !window.confirm("Are you sure you want to delete these " + eles.length + " docs?")) {
+        return false;
+      }
+
+      _.each(eles, function(ele) {
+        var model = this.collection.get(ele);
+
+        model.destroy().then(function(resp) {
+          that.rows[ele].$el.fadeOut(function () {
+            $(this).remove();
+          });
+
+          model.collection.remove(model.id);
+          if (!!model.id.match('_design')) { 
+            FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
+          }
+          that.$('.bulk-delete').addClass('disabled');
+        }, function(resp) {
+          FauxtonAPI.addNotification({
+            msg: "Failed to destroy your doc!",
+            type: "error"
+          });
+        });
+      }, this);
+    },
+
+    addPagination: function () {
+      var collection = this.collection;
+      var perPage = function () {
+        if (collection.params.limit && collection.skipFirstItem) {
+          return parseInt(collection.params.limit, 10) - 1;
+        } else if (collection.params.limit) {
+          return parseInt(collection.params.limit, 10);
+        }
+
+        return 20;
+      };
+
+      this.pagination = new Components.IndexPagination({
+        collection: this.collection,
+        scrollToSelector: '#dashboard-content',
+        previousUrlfn: function () {
+          return collection.urlPreviousPage(perPage(), this.previousParams.pop());
+        },
+        canShowPreviousfn: function () {
+          if (this.previousParams.length === 0) {
+            return false;
+          }
+
+          return true;
+        },
+        canShowNextfn: function () {
+          if (collection.length < (perPage() -1)) {
+            return false;
+          }
+
+          return true;
+        },
+        
+        nextUrlfn: function () {
+          return collection.urlNextPage(perPage());
+        }
+      });
+    },
+    
+    cleanup: function () {
+      //if (!this.pagination) { return; }
+      this.pagination.remove();
+      //this.pagination = null;
+      this.allDocsNumber.remove();
+      _.each(this.rows, function (row) {row.remove();});
+    },
+
+    beforeRender: function() {
+      var showNumbers = true;
+
+      if (!this.pagination) {
+        this.addPagination();
+      }
+
+      this.insertView('#documents-pagination', this.pagination);
+
+      if (this.designDocs || this.collection.idxType === '_view' || this.collection.params.startkey === '"_design"') {
+        showNumbers = false;
+      }
+
+      this.allDocsNumber = this.setView('#item-numbers', new Views.AllDocsNumber({
+        collection: this.collection,
+        newView: this.newView,
+        showNumbers: showNumbers,
+        pagination: this.pagination
+      }));
+
+      var docs = this.expandDocs ? this.collection : this.collection.simple();
+
+      docs.each(function(doc) {
+        this.rows[doc.id] = this.insertView("table.all-docs tbody", new this.nestedView({
+          model: doc
+        }));
+      }, this);
+    },
+
+    afterRender: function(){
+      prettyPrint();
+    }
+  });
+
+  Views.Doc = FauxtonAPI.View.extend({
+    template: "templates/documents/doc",
+    events: {
+      "click button.save-doc": "saveDoc",
+      "click button.delete": "destroy",
+      "click button.duplicate": "duplicate",
+      "click button.upload": "upload",
+      "click button.cancel-button": "goback"
+    },
+    disableLoader: true,
+    initialize: function (options) {
+      this.database = options.database;
+      _.bindAll(this);
+    },
+    goback: function(){
+      FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
+    },
+    destroy: function(event) {
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'This document has not been saved yet.',
+          type: 'warning'
+        });
+        return;
+      }
+
+      if (!window.confirm("Are you sure you want to delete this doc?")) {
+        return false;
+      }
+
+      var database = this.model.database;
+
+      this.model.destroy().then(function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Succesfully destroyed your doc"
+        });
+        FauxtonAPI.navigate(database.url("index"));
+      }, function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Failed to destroy your doc!",
+          type: "error"
+        });
+      });
+    },
+
+    beforeRender: function () {
+      this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model}));
+      this.uploadModal.render();
+
+      this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model}));
+      this.duplicateModal.render();
+    },
+
+    upload: function (event) {
+      event.preventDefault();
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'Please save the document before uploading an attachment.',
+          type: 'warning'
+        });
+        return;
+      }
+      this.uploadModal.showModal();
+    },
+
+    duplicate: function(event) {
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'Please save the document before duplicating it.',
+          type: 'warning'
+        });
+        return;
+      }
+      event.preventDefault();
+      this.duplicateModal.showModal();
+    },
+
+    updateValues: function() {
+      var notification;
+      if (this.model.changedAttributes()) {
+        notification = FauxtonAPI.addNotification({
+          msg: "Document saved successfully.",
+          type: "success",
+          clear: true
+        });
+        this.editor.setValue(this.model.prettyJSON());
+      }
+    },
+
+    establish: function() {
+      var promise = this.model.fetch(),
+          databaseId = this.database.safeID(),
+          deferred = $.Deferred(),
+          that = this;
+
+      promise.then(function () {
+        deferred.resolve();
+      }, function (xhr, reason, msg) {
+        if (xhr.status === 404) {
+          FauxtonAPI.addNotification({
+            msg: 'The document does not exist',
+            type: 'error',
+            clear: true
+          });
+          that.goback();
+        }
+        deferred.reject();
+     });
+      
+      return deferred;
+    },
+
+    saveDoc: function(event) {
+      var json, notification, 
+      that = this,
+      editor = this.editor,
+      validDoc = this.getDocFromEditor();
+
+      if (validDoc) {
+        this.getDocFromEditor();
+
+        notification = FauxtonAPI.addNotification({msg: "Saving document."});
+
+        this.model.save().then(function () {
+          editor.editSaved();
+          FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
+        }).fail(function(xhr) {
+
+          var responseText = JSON.parse(xhr.responseText).reason;
+          notification = FauxtonAPI.addNotification({
+            msg: "Save failed: " + responseText,
+            type: "error",
+            clear: true,
+            selector: "#doc .errors-container"
+          });
+        });
+      } else if(this.model.validationError && this.model.validationError === 'Cannot change a documents id.') {
+          notification = FauxtonAPI.addNotification({
+            msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
+            type: "error",
+            selector: "#doc .errors-container"
+          });
+        delete this.model.validationError;
+      } else {
+        notification = FauxtonAPI.addNotification({
+          msg: "Please fix the JSON errors and try again.",
+          type: "error",
+          selector: "#doc .errors-container"
+        });
+      }
+    },
+
+    getDocFromEditor: function () {
+      if (!this.hasValidCode()) {
+        return false;
+      }
+
+      json = JSON.parse(this.editor.getValue());
+
+      this.model.clear().set(json, {validate: true});
+      if (this.model.validationError) {
+        return false;
+      }
+
+      return this.model;
+    },
+
+    hasValidCode: function() {
+      var errors = this.editor.getAnnotations();
+      return errors.length === 0;
+    },
+
+    serialize: function() {
+      return {
+        doc: this.model,
+        attachments: this.getAttachments()
+      };
+    },
+
+    getAttachments: function () {
+      var attachments = this.model.get('_attachments');
+
+      if (!attachments) { return false; }
+
+      return _.map(attachments, function (att, key) {
+        return {
+          fileName: key,
+          size: att.length,
+          contentType: att.content_type,
+          url: this.model.url() + '/' + key
+        };
+      }, this);
+    },
+
+    afterRender: function() {
+      var saveDoc = this.saveDoc;
+
+      this.editor = new Components.Editor({
+        editorId: "editor-container",
+        commands: [{
+          name: 'save',
+          bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
+          exec: function(editor) {
+            saveDoc();
+          },
+          readOnly: true // false if this command should not apply in readOnly mode
+        }]
+      });
+      this.editor.render();
+      this.model.on("sync", this.updateValues, this);
+    },
+
+    cleanup: function () {
+      if (this.editor) this.editor.remove();
+    }
+  });
+
+  Views.DocFieldEditor = FauxtonAPI.View.extend({
+    template: "templates/documents/doc_field_editor",
+    disableLoader: true,
+    events: {
+      "click button.save": "saveDoc"
+    },
+
+    saveDoc: function(event) {
+      FauxtonAPI.addNotification({
+        type: "warning",
+        msg: "Save functionality coming soon."
+      });
+    },
+
+    serialize: function() {
+      return {
+        doc: this.getModelWithoutAttachments(),
+        attachments: this.getAttachments()
+      };
+    },
+
+    getModelWithoutAttachments: function() {
+      var model = this.model.toJSON();
+      delete model._attachments;
+      return model;
+    },
+
+    getAttachments: function () {
+      var attachments = this.model.get('_attachments');
+
+      if (!attachments) { return []; }
+
+      return _.map(attachments, function (att, key) {
+        return {
+          fileName: key,
+          size: att.length,
+          contentType: att.content_type,
+          url: this.model.url() + '/' + key
+        };
+      }, this);
+    },
+
+    establish: function() {
+      return [this.model.fetch()];
+    }
+  });
+
+  Views.AdvancedOptions = FauxtonAPI.View.extend({
+    template: "templates/documents/advanced_options",
+    className: "advanced-options well",
+
+    initialize: function (options) {
+      this.database = options.database;
+      this.ddocName = options.ddocName;
+      this.viewName = options.viewName;
+      this.updateViewFn = options.updateViewFn;
+      this.previewFn = options.previewFn;
+      //this.hadReduce = options.hasReduce || true;
+
+      if (typeof(options.hasReduce) === 'undefined') {
+        this.hasReduce = true;
+      } else {
+        this.hasReduce = options.hasReduce;
+      }
+
+      if (typeof(options.showPreview) === 'undefined') {
+        this.showPreview = true;
+      } else {
+        this.showPreview = options.showPreview;
+      }
+    },
+
+    events: {
+      "change form.view-query-update input": "updateFilters",
+      "change form.view-query-update select": "updateFilters",
+      "submit form.view-query-update": "updateView",
+      "click button.preview": "previewView"
+    },
+
+    beforeRender: function () {
+      if (this.viewName && this.ddocName) {
+        var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
+        _.each(buttonViews, function (view) {
+          this.insertView('#button-options', view);
+          view.update(this.database, this.ddocName, this.viewName);
+        }, this);
+      }
+    },
+
+    renderOnUpdatehasReduce: function (hasReduce) {
+      this.hasReduce = hasReduce;
+      this.render();
+    },
+
+    queryParams: function () {
+      var $form = this.$(".view-query-update");
+      // Ignore params without a value
+      var params = _.filter($form.serializeArray(), function(param) {
+        return param.value;
+      });
+
+      // Validate *key* params to ensure they're valid JSON
+      var keyParams = ["key","keys","startkey","endkey"];
+      var errorParams = _.filter(params, function(param) {
+        if (_.contains(keyParams, param.name)) {
+          try {
+            JSON.parse(param.value);
+            return false;
+          } catch(e) {
+            return true;
+          }
+        } else {
+          return false;
+        }
+      });
+
+      return {params: params, errorParams: errorParams};
+    },
+
+    updateFilters: function(event) {
+      event.preventDefault();
+      var $ele = $(event.currentTarget);
+      var name = $ele.attr('name');
+      this.updateFiltersFor(name, $ele);
+    },
+
+    updateFiltersFor: function(name, $ele) {
+      var $form = $ele.parents("form.view-query-update:first");
+      switch (name) {
+        // Reduce constraints
+        //   - Can't include_docs for reduce=true
+        //   - can't include group_level for reduce=false
+        case "reduce":
+          if ($ele.prop('checked') === true) {
+          if ($form.find("input[name=include_docs]").prop("checked") === true) {
+            $form.find("input[name=include_docs]").prop("checked", false);
+            var notification = FauxtonAPI.addNotification({
+              msg: "include_docs has been disabled as you cannot include docs on a reduced view",
+              type: "warn",
+              selector: ".view.show .all-docs-list.errors-container"
+            });
+          }
+          $form.find("input[name=include_docs]").prop("disabled", true);
+          $form.find("select[name=group_level]").prop("disabled", false);
+        } else {
+          $form.find("select[name=group_level]").prop("disabled", true);
+          $form.find("input[name=include_docs]").prop("disabled", false);
+        }
+        break;
+        case "include_docs":
+        break;
+      }
+    },
+
+    updateFromParams: function (params) {
+      var $form = this.$el.find("form.view-query-update");
+      _.each(params, function(val, key) {
+        var $ele;
+        switch (key) {
+          case "limit":
+            case "group_level":
+            $form.find("select[name='"+key+"']").val(val);
+          break;
+          case "include_docs":
+            case "stale":
+            case "descending":
+            case "inclusive_end":
+            $form.find("input[name='"+key+"']").prop('checked', true);
+          break;
+          case "reduce":
+            $ele = $form.find("input[name='"+key+"']");
+          if (val == "true") {
+            $ele.prop('checked', true);
+          }
+          this.updateFiltersFor(key, $ele);
+          break;
+          default:
+            $form.find("input[name='"+key+"']").val(val);
+          break;
+        }
+      }, this);
+    },
+
+    updateView: function (event) {
+      this.updateViewFn(event, this.queryParams());
+    },
+
+    previewView: function (event) {
+      this.previewFn(event, this.queryParams());
+    },
+
+    serialize: function () {
+      return {
+        hasReduce: this.hasReduce,
+        showPreview: this.showPreview
+      };
+    }
+  });
+
+  Views.DesignDocSelector = FauxtonAPI.View.extend({
+    template: "templates/documents/design_doc_selector",
+
+    events: {
+      "change select#ddoc": "updateDesignDoc"
+    },
+
+    initialize: function (options) {
+      this.ddocName = options.ddocName;
+      this.database = options.database;
+      this.listenTo(this.collection, 'add', this.ddocAdded);
+      this.DocModel = options.DocModel || Documents.Doc;
+    },
+
+    ddocAdded: function (ddoc) {
+      this.ddocName = ddoc.id;
+      this.render();
+    },
+
+    serialize: function () {
+      return {
+        ddocName: this.ddocName,
+        ddocs: this.collection
+      };
+    },
+
+    updateDesignDoc: function () {
+      if (this.newDesignDoc()) {
+        this.$('#new-ddoc-section').show();
+      } else {
+        this.$('#new-ddoc-section').hide();
+      }
+    },
+
+    newDesignDoc: function () {
+
+      return this.$('#ddoc').val() === 'new-doc';
+    },
+
+    newDocValidation: function(){
+      return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
+    },
+    getCurrentDesignDoc: function () {
+      if (this.newDesignDoc()) {
+        var doc = {
+          _id: '_design/' + this.$('#new-ddoc').val(),
+          views: {},
+          language: "javascript"
+        };
+        var ddoc = new this.DocModel(doc, {database: this.database});
+        //this.collection.add(ddoc);
+        return ddoc;
+      } else if ( !this.newDesignDoc() ) {
+        var ddocName = this.$('#ddoc').val();
+        return this.collection.find(function (ddoc) {
+          return ddoc.id === ddocName;
+        }).dDocModel();
+      }
+    }
+  });
+
+  Views.ViewEditor = FauxtonAPI.View.extend({
+    template: "templates/documents/view_editor",
+    builtinReduces: ['_sum', '_count', '_stats'],
+
+    events: {
+      "click button.save": "saveView",
+      "click button.delete": "deleteView",
+      "change select#reduce-function-selector": "updateReduce",
+      "click button.preview": "previewView",
+      "click #db-views-tabs-nav": 'toggleIndexNav'
+    },
+
+    langTemplates: {
+      "javascript": {
+        map: "function(doc) {\n  emit(doc._id, 1);\n}",
+        reduce: "function(keys, values, rereduce){\n  if (rereduce){\n    return sum(values);\n  } else {\n    return values.length;\n  }\n}"
+      }
+    },
+
+    defaultLang: "javascript",
+
+    initialize: function(options) {
+      this.newView = options.newView || false;
+      this.ddocs = options.ddocs;
+      this.params = options.params;
+      this.database = options.database;
+      if (this.newView) {
+        this.viewName = 'newView';
+      } else {
+        this.ddocID = options.ddocInfo.id;
+        this.viewName = options.viewName;
+        this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
+      }
+
+      this.showIndex = false;
+      _.bindAll(this);
+    },
+
+    establish: function () {
+      if (this.ddocInfo) {
+        return this.ddocInfo.fetch();
+      }
+    },
+
+    updateValues: function() {
+      var notification;
+      if (this.model.changedAttributes()) {
+        notification = FauxtonAPI.addNotification({
+          msg: "Document saved successfully.",
+          type: "success",
+          clear: true
+        });
+        this.editor.setValue(this.model.prettyJSON());
+      }
+    },
+
+    updateReduce: function(event) {
+      var $ele = $("#reduce-function-selector");
+      var $reduceContainer = $(".control-group.reduce-function");
+      if ($ele.val() == "CUSTOM") {
+        this.createReduceEditor();
+        this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
+        $reduceContainer.show();
+      } else {
+        $reduceContainer.hide();
+      }
+    },
+
+    deleteView: function (event) {
+      event.preventDefault();
+
+      if (this.newView) { return alert('Cannot delete a new view.'); }
+      if (!confirm('Are you sure you want to delete this view?')) {return;}
+
+      var that = this,
+          promise,
+          viewName = this.$('#index-name').val(),
+          ddocName = this.$('#ddoc :selected').val(),
+          ddoc = this.getCurrentDesignDoc();
+
+      ddoc.removeDdocView(viewName);
+
+      if (ddoc.hasViews()) {
+        promise = ddoc.save(); 
+      } else {
+        promise = ddoc.destroy();
+      }
+
+      promise.then(function () {
+        FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
+        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
+      });
+    },
+
+    saveView: function(event) {
+      var json, notification,
+      that = this;
+
+      if (event) { event.preventDefault();}
+
+      $('#dashboard-content').scrollTop(0); //scroll up
+
+      if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
+        var mapVal = this.mapEditor.getValue(), 
+        reduceVal = this.reduceVal(),
+        viewName = this.$('#index-name').val(),
+        ddoc = this.getCurrentDesignDoc(),
+        ddocName = ddoc.id;
+
+        this.viewName = viewName;
+
+        notification = FauxtonAPI.addNotification({
+          msg: "Saving document.",
+          selector: "#define-view .errors-container",
+          clear: true
+        });
+
+        ddoc.setDdocView(viewName, mapVal, reduceVal);
+
+        ddoc.save().then(function () {
+          that.ddocs.add(ddoc);
+
+          that.mapEditor.editSaved();
+          that.reduceEditor && that.reduceEditor.editSaved();
+
+          FauxtonAPI.addNotification({
+            msg: "View has been saved.",
+            type: "success",
+            selector: "#define-view .errors-container",
+            clear: true
+          });
+
+          if (that.newView) {
+            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.mixins.safeURLName(viewName); 
+
+            FauxtonAPI.navigate(fragment, {trigger: false});
+            that.newView = false;
+            that.ddocID = ddoc.safeID();
+            that.viewName = viewName;
+            that.ddocInfo = ddoc;
+            that.showIndex = true;
+            that.render();
+            FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
+              selectedTab: app.mixins.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.mixins.removeSpecialCharacters(viewName)
+            });
+          }
+
+          if (that.reduceFunStr !== reduceVal) {
+            that.reduceFunStr = reduceVal;
+            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce()); 
+          }
+
+          FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
+
+        }, function(xhr) {
+          var responseText = JSON.parse(xhr.responseText).reason;
+          notification = FauxtonAPI.addNotification({
+            msg: "Save failed: " + responseText,
+            type: "error",
+            clear: true
+          });
+        });
+      } else {
+        var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
+        notification = FauxtonAPI.addNotification({
+          msg: errormessage,
+          type: "error",
+          selector: "#define-view .errors-container",
+          clear: true
+        });
+      }
+    },
+
+    updateView: function(event, paramInfo) {
+       event.preventDefault();
+ 
+       if (this.newView) { return alert('Please save this new view before querying it.'); }
+ 
+       var errorParams = paramInfo.errorParams,
+           params = paramInfo.params;
+ 
+       if (_.any(errorParams)) {
+         _.map(errorParams, function(param) {
+ 
+           // TODO: Where to add this error?
+           // bootstrap wants the error on a control-group div, but we're not using that
+           //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
+           return FauxtonAPI.addNotification({
+             msg: "JSON Parse Error on field: "+param.name,
+             type: "error",
+             selector: ".advanced-options .errors-container",
+             clear: true
+           });
+         });
+         FauxtonAPI.addNotification({
+           msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
+           type: "warning",
+           selector: ".advanced-options .errors-container",
+           clear: true
+         });
+ 
+         return false;
+      }
+ 
+       var fragment = window.location.hash.replace(/\?.*$/, '');
+       fragment = fragment + '?' + $.param(params);
+       FauxtonAPI.navigate(fragment, {trigger: false});
+ 
+       FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
+    },
+
+
+    previewView: function(event, paramsInfo) {
+      event.preventDefault();
+      var that = this,
+      mapVal = this.mapVal(),
+      reduceVal = this.reduceVal(),
+      paramsArr = [];
+
+      if (paramsInfo && paramsInfo.params) {
+        paramsArr = paramsInfo.params;
+      }
+
+      var params = _.reduce(paramsArr, function (params, param) {
+        params[param.name] = param.value;
+        return params;
+      }, {reduce: false});
+
+      event.preventDefault();
+
+      FauxtonAPI.addNotification({
+        msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
+        type: "warning",
+        selector: ".advanced-options .errors-container",
+        fade: true
+      });
+
+      var promise = FauxtonAPI.Deferred();
+
+      if (!this.database.allDocs) {
+        this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
+        promise = this.database.allDocs.fetch();
+      } else {
+        promise.resolve();
+      }
+
+      promise.then(function () {
+        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
+
+        var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
+        queryPromise.then(function (results) {
+          FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
+        });
+      });
+    },
+
+    getCurrentDesignDoc: function () {
+      return this.designDocSelector.getCurrentDesignDoc();
+    },
+    
+    isCustomReduceEnabled: function() {
+      return $("#reduce-function-selector").val() == "CUSTOM";
+    },
+
+    mapVal: function () {
+      if (this.mapEditor) {
+        return this.mapEditor.getValue();
+      }
+
+      return this.$('#map-function').text();
+    },
+
+    reduceVal: function() {
+      var reduceOption = this.$('#reduce-function-selector :selected').val(),
+      reduceVal = "";
+
+      if (reduceOption === 'CUSTOM') {
+        reduceVal = this.reduceEditor.getValue();
+      } else if ( reduceOption !== 'NONE') {
+        reduceVal = reduceOption;
+      }
+
+      return reduceVal;
+    },
+
+
+    hasValidCode: function() {
+      return _.every(["mapEditor", "reduceEditor"], function(editorName) {
+        var editor = this[editorName];
+        if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
+          return true;
+        } 
+        return editor.hadValidCode();
+      }, this);
+    },
+
+    toggleIndexNav: function (event) {
+      var $targetId = this.$(event.target).attr('id'),
+          $previousTab = this.$(this.$('li.active a').attr('href')),
+          $targetTab = this.$(this.$(event.target).attr('href'));
+
+      if ($targetTab.attr('id') !== $previousTab.attr('id')) {
+        $previousTab.removeAttr('style');
+      }
+
+      if ($targetId === 'index-nav') {
+        if (this.newView) { return; }
+        var that = this;
+        $('#dashboard-content').scrollTop(0); //scroll up
+        $targetTab.toggle('slow', function(){
+           that.showEditors();
+        });
+      } else {
+        $targetTab.toggle('slow');
+      }
+    },
+
+    serialize: function() {
+      return {
+        ddocs: this.ddocs,
+        ddoc: this.model,
+        ddocName: this.model.id,
+        viewName: this.viewName,
+        reduceFunStr: this.reduceFunStr,
+        isCustomReduce: this.hasCustomReduce(),
+        newView: this.newView,
+        langTemplates: this.langTemplates.javascript
+      };
+    },
+
+    hasCustomReduce: function() {
+      return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
+    },
+
+    hasReduce: function () {
+      return this.reduceFunStr || false;
+    },
+
+    createReduceEditor: function () {
+      if (this.reduceEditor) {
+        this.reduceEditor.remove();
+      }
+
+      this.reduceEditor = new Components.Editor({
+        editorId: "reduce-function",
+        mode: "javascript",
+        couchJSHINT: true
+      });
+      this.reduceEditor.render();
+    },
+
+    beforeRender: function () {
+
+      if (this.newView) {
+        this.reduceFunStr = '_sum';
+        if (this.ddocs.length === 0) {
+          this.model = new Documents.Doc(null, {database: this.database});
+        } else {
+          this.model = this.ddocs.first().dDocModel();
+        }
+        this.ddocID = this.model.id;
+      } else {
+        var ddocDecode = decodeURIComponent(this.ddocID);
+        this.model = this.ddocs.get(ddocDecode).dDocModel();
+        this.reduceFunStr = this.model.viewHasReduce(this.viewName);
+        this.setView('#ddoc-info', new Views.DdocInfo({model: this.ddocInfo }));
+      }
+
+      this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
+        collection: this.ddocs,
+        ddocName: this.model.id,
+        database: this.database
+      }));
+      
+      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
+        updateViewFn: this.updateView,
+        previewFn: this.previewView,
+        database: this.database,
+        viewName: this.viewName,
+        ddocName: this.model.id,
+        hasReduce: this.hasReduce()
+      }));
+    },
+
+    afterRender: function() {
+      if (this.params) {
+        this.advancedOptions.updateFromParams(this.params);
+      }
+
+      this.designDocSelector.updateDesignDoc();
+      if (this.newView || this.showIndex) {
+        this.showEditors();
+        this.showIndex = false;
+      } else {
+        this.$('#index').hide();
+        this.$('#index-nav').parent().removeClass('active');
+      }
+    },
+
+    showEditors: function () {
+      this.mapEditor = new Components.Editor({
+        editorId: "map-function",
+        mode: "javascript",
+        couchJSHINT: true
+      });
+      this.mapEditor.render();
+
+      if (this.hasCustomReduce()) {
+        this.createReduceEditor();
+      } else {
+        $(".control-group.reduce-function").hide();
+      }
+
+      if (this.newView) {
+        this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
+        //Use a built in view by default
+        //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
+      } 
+
+      this.mapEditor.editSaved();
+      this.reduceEditor && this.reduceEditor.editSaved();
+    },
+
+    cleanup: function () {
+      this.mapEditor && this.mapEditor.remove();
+      this.reduceEditor && this.reduceEditor.remove();
+    }
+  });
+
+  Views.JumpToDoc = FauxtonAPI.View.extend({
+    template: "templates/documents/jumpdoc",
+
+    initialize: function (options) {
+      this.database = options.database;
+    },
+
+    events: {
+      "submit #jump-to-doc": "jumpToDoc"
+    },
+
+    jumpToDoc: function (event) {
+      event.preventDefault();
+      var docId = this.$('#jump-to-doc-id').val().trim();
+      FauxtonAPI.navigate('/database/' + app.mixins.safeURLName(this.database.id) +'/' + app.mixins.safeURLName(docId), {trigger: true});
+    },
+
+    afterRender: function () {
+     this.typeAhead = new Components.DocSearchTypeahead({el: '#jump-to-doc-id', database: this.database});
+     this.typeAhead.render();
+    }
+  });
+
+  Views.Sidebar = FauxtonAPI.View.extend({
+    template: "templates/documents/sidebar",
+    events: {
+      "click button#delete-database": "deleteDatabase"
+    },
+
+    initialize: function(options) {
+      this.database = options.database;
+      if (options.ddocInfo) {
+        this.ddocID = options.ddocInfo.id;
+        this.currView = options.ddocInfo.currView;
+      }
+    },
+
+    deleteDatabase: function (event) {
+      event.preventDefault();
+
+      var result = confirm('Are you sure you want to delete this database?');
+
+      if (!result) { return; }
+      var databaseName = this.database.id;
+      FauxtonAPI.addNotification({
+        msg: "Deleting your database...",
+        type: "error",
+        clear: true
+      });
+
+      this.database.destroy().then(function () {
+        FauxtonAPI.navigate('#/_all_dbs');
+        FauxtonAPI.addNotification({
+          msg: 'The database ' + databaseName + ' has been deleted.',
+          clear: true
+        });
+      }).fail(function (rsp, error, msg) {
+        FauxtonAPI.addNotification({
+          msg: 'Could not delete the database, reason ' + msg + '.',
+          type: 'error',
+          clear: true
+        });
+      });
+    },
+
+    serialize: function() {
+      var docLinks = FauxtonAPI.getExtensions('docLinks'),
+          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
+          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
+          extensionList = FauxtonAPI.getExtensions('sidebar:list');
+      return {
+        changes_url: '#' + this.database.url('changes'),
+        permissions_url: '#' + this.database.url('app') + '/permissions',
+        db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
+        database: this.collection.database,
+        database_url: '#' + this.database.url('app'), 
+        docLinks: docLinks,
+        docLimit: Databases.DocLimit,
+        addLinks: addLinks,
+        newLinks: newLinks,
+        extensionList: extensionList > 0
+      };
+    },
+
+    buildIndexList: function(collection, selector, design){
+      _.each(_.keys(collection), function(key){
+        var selected = this.ddocID == "_design/"+design;
+        this.insertView("ul.nav." + selector, new Views.IndexItem({
+          ddoc: design,
+          index: key,
+          database: this.collection.database.id,
+          selected: selected && key == this.currView
+        }));
+      }, this);
+    },
+
+    beforeRender: function(manage) {
+
+      var sidebarListViews = FauxtonAPI.getExtensions('sidebar:list');
+      _.each(sidebarListViews, function (view) {
+        var extension = this.insertView('#extension-navs', view);
+        extension.update(this.database, this.collection, this.viewName);
+        extension.render();
+      }, this);
+
+
+      this.collection.each(function(design) {
+        if (design.has('doc')){
+          var ddoc = design.id.replace(/^_design\//,"");
+          if (design.get('doc').views){
+            this.buildIndexList(design.get('doc').views, "views", ddoc);
+          }
+        }
+      }, this);
+    },
+
+
+    afterRender: function () {
+      if (this.selectedTab) {
+        this.setSelectedTab(this.selectedTab);
+      }
+    },
+
+    setSelectedTab: function (selectedTab) {
+      this.selectedTab = selectedTab;
+      this.$('li').removeClass('active');
+      this.$('#' + selectedTab).parent().addClass('active');
+    }
+  });
+
+  Views.Indexed = FauxtonAPI.View.extend({});
+
+  Views.Changes = FauxtonAPI.View.extend({
+    template: "templates/documents/changes",
+
+    establish: function() {
+      return [ this.model.changes.fetch()];
+    },
+
+    serialize: function () {
+      return {
+        changes: this.model.changes.toJSON(),
+        database: this.model
+      };
+    },
+
+    afterRender: function(){
+      prettyPrint();
+    }
+  });
+
+  Views.DdocInfo = FauxtonAPI.View.extend({
+    template: "templates/documents/ddoc_info",
+
+    initialize: function (options) {
+      this.refreshTime = options.refreshTime || 5000;
+      this.listenTo(this.model, 'change', this.render);
+    },
+
+    serialize: function () {
+      return {
+        view_index: this.model.get('view_index')
+      };
+    },
+
+    afterRender: function () {
+      this.startRefreshInterval();
+    },
+
+    startRefreshInterval: function () {
+      var model = this.model;
+
+      // Interval already set
+      if (this.intervalId) { return ; }
+
+      this.intervalId = setInterval(function () {
+        model.fetch();
+      }, this.refreshTime);
+    },
+
+    stopRefreshInterval: function () {
+      clearInterval(this.intervalId);
+    },
+
+    cleanup: function () {
+      this.stopRefreshInterval();
+    }
+  });
+
+  Documents.Views = Views;
+  return Documents;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js
new file mode 100644
index 0000000..aa4c3d4
--- /dev/null
+++ b/app/addons/fauxton/base.js
@@ -0,0 +1,271 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+        // Libs
+       "backbone",
+	   "resizeColumns",
+],
+
+function(app, Backbone, resizeColumns) {
+
+
+  //resizeAnimation
+  app.resizeColumns = new resizeColumns({});
+  app.resizeColumns.onResizeHandler();
+ 
+  var Fauxton = {};
+
+  Fauxton.Breadcrumbs = Backbone.View.extend({
+    template: "templates/fauxton/breadcrumbs",
+
+    serialize: function() {
+      var crumbs = _.clone(this.crumbs);
+      return {
+        crumbs: crumbs
+      };
+    },
+
+    initialize: function(options) {
+      this.crumbs = options.crumbs;
+    }
+  });
+
+  Fauxton.VersionInfo = Backbone.Model.extend({
+    url: app.host
+  });
+
+  // TODO: this View should extend from FauxtonApi.View.
+  // Chicken and egg problem, api.js extends fauxton/base.js.
+  // Need to sort the loading order.
+  Fauxton.Footer = Backbone.View.extend({
+    template: "templates/fauxton/footer",
+
+    initialize: function() {
+      this.versionInfo = new Fauxton.VersionInfo();
+    },
+
+    establish: function() {
+      return [this.versionInfo.fetch()];
+    },
+
+    serialize: function() {
+      return {
+        version: this.versionInfo.get("version")
+      };
+    }
+  });
+
+  Fauxton.NavBar = Backbone.View.extend({
+    className:"navbar",
+    template: "templates/fauxton/nav_bar",
+    // TODO: can we generate this list from the router?
+    navLinks: [
+      {href:"#/_all_dbs", title:"Databases", icon: "fonticon-database", className: 'databases'}
+    ],
+
+    bottomNavLinks: [],
+    footerNavLinks: [],
+
+    serialize: function() {
+      return {
+        navLinks: this.navLinks,
+        bottomNavLinks: this.bottomNavLinks,
+        footerNavLinks: this.footerNavLinks
+      };
+    },
+
+    addLink: function(link) {
+      // link.top means it gets pushed to the top of the array,
+      // link.bottomNav means it goes to the additional bottom nav
+      // link.footerNav means goes to the footer nav
+      if (link.top && !link.bottomNav){
+        this.navLinks.unshift(link);
+      } else if (link.top && link.bottomNav){
+        this.bottomNavLinks.unshift(link);
+      } else if (link.bottomNav) {
+        this.bottomNavLinks.push(link);
+      } else if (link.footerNav) {
+        this.footerNavLinks.push(link);
+      } else {
+        this.navLinks.push(link);
+      }
+    },
+
+    removeLink: function (removeLink) {
+      var links = this.navlinks;
+
+      if (removeLink.bottomNav) {
+        links = this.bottomNavLinks;
+      } else if (removeLink.footerNav) {
+        links = this.footerNavLinks;
+      }
+
+      var foundIndex = -1;
+
+      _.each(links, function (link, index) {
+        if (link.title === removeLink.title) {
+          foundIndex = index;
+        }
+      });
+
+      if (foundIndex === -1) {return;}
+      links.splice(foundIndex, 1);
+      this.render();
+    },
+
+    afterRender: function(){
+
+      $('#primary-navbar li[data-nav-name="' + app.selectedHeader + '"]').addClass('active');
+
+      var menuOpen = true;
+      var $selectorList = $('body');
+      $('.brand').off();
+      $('.brand').on({
+        click: function(e){
+          if(!$(e.target).is('a')){
+            toggleMenu();
+          }
+         }
+      });
+
+      function toggleMenu(){
+        $selectorList.toggleClass('closeMenu');
+        menuOpen = $selectorList.hasClass('closeMenu');
+        app.resizeColumns.onResizeHandler();
+      }
+
+      $('#primary-navbar').on("click", ".nav a", function(){
+        if (!($selectorList.hasClass('closeMenu'))){
+        setTimeout(
+          function(){
+            $selectorList.addClass('closeMenu');
+            app.resizeColumns.onResizeHandler();
+          },3000);
+
+        }
+      });
+
+      app.resizeColumns.initialize();
+    },
+
+    beforeRender: function () {
+      this.addLinkViews();
+    },
+
+    addLinkViews: function () {
+      var that = this;
+
+      _.each(_.union(this.navLinks, this.bottomNavLinks), function (link) {
+        if (!link.view) { return; }
+
+        //TODO check if establish is a function
+        var establish = link.establish || [];
+        $.when.apply(null, establish).then( function () {
+          var selector =  link.bottomNav ? '#bottom-nav-links' : '#nav-links';
+          that.insertView(selector, link.view).render();
+        });
+      }, this);
+    }
+
+    // TODO: ADD ACTIVE CLASS
+  });
+
+  Fauxton.ApiBar = Backbone.View.extend({
+    template: "templates/fauxton/api_bar",
+    endpoint: '_all_docs',
+
+    documentation: 'docs',
+
+    events:  {
+      "click .api-url-btn" : "toggleAPIbar"
+    },
+
+    toggleAPIbar: function(e){
+      var $currentTarget = $(e.currentTarget).find('span');
+      if ($currentTarget.hasClass("fonticon-plus")){
+        $currentTarget.removeClass("fonticon-plus").addClass("fonticon-minus");
+      }else{
+        $currentTarget.removeClass("fonticon-minus").addClass("fonticon-plus");
+      }
+
+      $('.api-navbar').toggle();
+
+    },
+
+    serialize: function() {
+      return {
+        endpoint: this.endpoint,
+        documentation: this.documentation
+      };
+    },
+
+    hide: function(){
+      this.$el.addClass('hide');
+    },
+    show: function(){
+      this.$el.removeClass('hide');
+    },
+    update: function(endpoint) {
+      this.show();
+      this.endpoint = endpoint[0];
+      this.documentation = endpoint[1];
+      this.render();
+    }
+
+  });
+
+  Fauxton.Notification = Backbone.View.extend({
+    fadeTimer: 5000,
+
+    initialize: function(options) {
+      this.msg = options.msg;
+      this.type = options.type || "info";
+      this.selector = options.selector;
+      this.fade = options.fade === undefined ? true : options.fade;
+      this.clear = options.clear;
+      this.data = options.data || "";
+      this.template = options.template || "templates/fauxton/notification";
+    },
+
+    serialize: function() {
+      return {
+        data: this.data,
+        msg: this.msg,
+        type: this.type
+      };
+    },
+
+    delayedFade: function() {
+      var that = this;
+      if (this.fade) {
+        setTimeout(function() {
+          that.$el.fadeOut();
+        }, this.fadeTimer);
+      }
+    },
+
+    renderNotification: function(selector) {
+      selector = selector || this.selector;
+      if (this.clear) {
+        $(selector).html('');
+      }
+      this.render().$el.appendTo(selector);
+      this.delayedFade();
+      return this;
+    }
+  });
+
+  
+  return Fauxton;
+});


[03/52] [abbrv] Fauxton: move modules to addons

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
new file mode 100644
index 0000000..a9f45ad
--- /dev/null
+++ b/app/addons/fauxton/components.js
@@ -0,0 +1,337 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define('ace_configuration', ["app", "ace/ace"], function (app, ace) {
+  var path = app.host + app.root + 'js/ace';
+  var config = require("ace/config");
+  config.set("packaged", true);
+  config.set("workerPath",path);
+  config.set("modePath",path);
+  config.set("themePath", path);
+  return ace;
+});
+
+define([
+  "app",
+  // Libs
+  "api",
+  "ace_configuration",
+],
+
+function(app, FauxtonAPI, ace) {
+  var Components = app.module();
+
+  Components.Pagination = FauxtonAPI.View.extend({
+    template: "templates/fauxton/pagination",
+
+    initialize: function(options) {
+      this.page = parseInt(options.page, 10);
+      this.perPage = options.perPage;
+      this.total = options.total;
+      this.totalPages = Math.ceil(this.total / this.perPage);
+      this.urlFun = options.urlFun;
+    },
+
+    serialize: function() {
+      return {
+        page: this.page,
+        perPage: this.perPage,
+        total: this.total,
+        totalPages: this.totalPages,
+        urlFun: this.urlFun
+      };
+    }
+  });
+
+  Components.IndexPagination = FauxtonAPI.View.extend({
+    template: "templates/fauxton/index_pagination",
+    events: {
+      "click a": 'scrollTo',
+      "click a#next": 'nextClicked',
+      "click a#previous": 'previousClicked'
+    },
+
+    scrollTo: function () {
+      if (!this.scrollToSelector) { return; }
+      $(this.scrollToSelector).animate({ scrollTop: 0 }, 'slow');
+    },
+
+    initialize: function (options) {
+      this.previousUrlfn = options.previousUrlfn;
+      this.nextUrlfn = options.nextUrlfn;
+      this.canShowPreviousfn = options.canShowPreviousfn;
+      this.canShowNextfn = options.canShowNextfn;
+      this.scrollToSelector = options.scrollToSelector;
+      _.bindAll(this);
+      this.previousParams = [];
+    },
+
+    previousClicked: function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      if (!this.canShowPreviousfn()) { return; }
+      FauxtonAPI.navigate(this.previousUrlfn(), {trigger: false});
+      FauxtonAPI.triggerRouteEvent('paginate', 'previous');
+    },
+
+    nextClicked: function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      if (!this.canShowNextfn()) { return; }
+
+      var params = _.clone(this.collection.params);
+
+      if (params) {
+        this.previousParams.push(params);
+      }
+
+      FauxtonAPI.navigate(this.nextUrlfn(), {trigger: false});
+      FauxtonAPI.triggerRouteEvent('paginate', 'next');
+    },
+
+    serialize: function () {
+      return {
+        canShowNextfn: this.canShowNextfn,
+        canShowPreviousfn: this.canShowPreviousfn,
+      };
+    },
+
+    pageLimit: function () {
+      var limit = 20;
+
+      if (this.collection.params.limit && this.collection.skipFirstItem) {
+        limit = parseInt(this.collection.params.limit, 10) - 1;
+      } else if (this.collection.params.limit) {
+        limit = parseInt(this.collection.params.limit, 10);
+      }
+
+      return limit;
+    },
+
+    pageStart: function () {
+      return (this.previousParams.length * this.pageLimit()) + 1; 
+
+    },
+
+    pageEnd: function () {
+      return (this.previousParams.length * this.pageLimit()) + this.pageLimit();
+    }
+
+  });
+
+  //TODO allow more of the typeahead options.
+  //Current this just does what we need but we
+  //need to support the other typeahead options.
+  Components.Typeahead = FauxtonAPI.View.extend({
+
+    initialize: function (options) {
+      this.source = options.source;
+      _.bindAll(this);
+    },
+
+    afterRender: function () {
+      var onUpdate = this.onUpdate;
+
+      this.$el.typeahead({
+        source: this.source,
+        updater: function (item) {
+          if (onUpdate) {
+            onUpdate(item);
+          }
+
+          return item;
+        }
+      });
+    }
+
+  });
+
+
+  Components.DbSearchTypeahead = Components.Typeahead.extend({
+    initialize: function (options) {
+      this.dbLimit = options.dbLimit || 30;
+      this.onUpdate = options.onUpdate;
+      _.bindAll(this);
+    },
+    source: function(query, process) {
+      var url = [
+        app.host,
+        "/_all_dbs?startkey=%22",
+        query,
+        "%22&endkey=%22",
+        query,
+        "\u9999",
+        "%22&limit=",
+        this.dbLimit
+      ].join('');
+
+      if (this.ajaxReq) { this.ajaxReq.abort(); }
+
+      this.ajaxReq = $.ajax({
+        cache: false,
+        url: url,
+        dataType: 'json',
+        success: function(data) {
+          process(data);
+        }
+      });
+    }
+  });
+
+  Components.DocSearchTypeahead = Components.Typeahead.extend({
+    initialize: function (options) {
+      this.docLimit = options.docLimit || 30;
+      this.database = options.database;
+      _.bindAll(this);
+    },
+    source: function(query, process) {
+      var url = [
+        app.host,
+        "/",
+        this.database.id,
+        "/_all_docs?startkey=%22",
+        query,
+        "%22&endkey=%22",
+        query,
+        "\u9999",
+        "%22&limit=",
+        this.docLimit
+      ].join('');
+
+      if (this.ajaxReq) { this.ajaxReq.abort(); }
+
+      this.ajaxReq = $.ajax({
+        cache: false,
+        url: url,
+        dataType: 'json',
+        success: function(data) {
+          var ids = _.map(data.rows, function (row) {
+            return row.id;
+          });
+          process(ids);
+        }
+      });
+    }
+  });
+
+  Components.Editor = FauxtonAPI.View.extend({
+    initialize: function (options) {
+      this.editorId = options.editorId;
+      this.mode = options.mode || "json";
+      this.commands = options.commands;
+      this.theme = options.theme || 'crimson_editor';
+      this.couchJSHINT = options.couchJSHINT;
+      this.edited = false;
+    },
+
+    afterRender: function () {
+      this.editor = ace.edit(this.editorId);
+      this.setHeightToLineCount();
+      this.editor.setTheme("ace/theme/" + this.theme);
+      this.editor.getSession().setMode("ace/mode/" + this.mode);
+      this.editor.getSession().setUseWrapMode(true);
+      this.editor.setShowPrintMargin(false);
+      this.editor.gotoLine(2);
+      this.addCommands();
+
+      if (this.couchJSHINT) {
+        this.removeIncorrectAnnotations();
+      }
+
+      var that = this;
+      this.editor.getSession().on('change', function () {
+        that.setHeightToLineCount();
+        that.edited = true;
+      });
+
+      $(window).on('beforeunload.editor', function() {
+        if (that.edited) {
+          return 'Your changes have not been saved. Click cancel to return to the document.';
+        }
+      });
+
+      FauxtonAPI.beforeUnload("editor", function (deferred) {
+        if (that.edited) {
+          return 'Your changes have not been saved. Click cancel to return to the document.';
+        }
+      });
+    },
+
+    cleanup: function () {
+      $(window).off('beforeunload.editor');
+      FauxtonAPI.removeBeforeUnload("editor");
+    },
+
+    setHeightToLineCount: function () {
+      var lines = this.editor.getSession().getDocument().getLength();
+      this.editor.setOptions({
+        maxLines: lines
+      });
+
+      this.editor.resize();
+    },
+
+    addCommands: function () {
+      _.each(this.commands, function (command) {
+        this.editor.commands.addCommand(command);
+      }, this);
+    },
+
+    removeIncorrectAnnotations: function () {
+      var editor = this.editor;
+
+      this.editor.getSession().on("changeAnnotation", function(){
+        var annotations = editor.getSession().getAnnotations();
+
+        var newAnnotations = _.reduce(annotations, function (annotations, error) {
+          if (!FauxtonAPI.isIgnorableError(error.raw)) {
+            annotations.push(error);
+          }
+          return annotations;
+        }, []);
+
+        if (annotations.length !== newAnnotations.length) {
+          editor.getSession().setAnnotations(newAnnotations);
+        }
+      });
+    },
+
+    editSaved: function () {
+      this.edited = false;
+    },
+
+    setValue: function (data, lineNumber) {
+      lineNumber = lineNumber ? lineNumber : -1;
+      this.editor.setValue(data, lineNumber);
+    },
+
+    getValue: function () {
+      return this.editor.getValue();
+    },
+
+    getAnnotations: function () {
+      return this.editor.getSession().getAnnotations();
+    },
+
+    hadValidCode: function () {
+     var errors = this.getAnnotations();
+     // By default CouchDB view functions don't pass lint
+     return _.every(errors, function(error) {
+      return FauxtonAPI.isIgnorableError(error.raw);
+      },this);
+    }
+
+  });
+
+  return Components;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/layout.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/layout.js b/app/addons/fauxton/layout.js
new file mode 100644
index 0000000..1422241
--- /dev/null
+++ b/app/addons/fauxton/layout.js
@@ -0,0 +1,98 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define(["backbone"],
+
+function(Backbone) {
+
+  // A wrapper of the main Backbone.layoutmanager
+  // Allows the main layout of the page to be changed by any plugin.
+  // Exposes the different views:
+  //    navBar -> the top navigation bar
+  //    dashboardContent -> Main display view
+  //    breadcrumbs -> Breadcrumbs navigation section
+  var Layout = function (navBar, apiBar) {
+    this.navBar = navBar;
+    this.apiBar = apiBar;
+
+    this.layout = new Backbone.Layout({
+      template: "templates/layouts/with_sidebar",
+
+      views: {
+        "#primary-navbar": this.navBar,
+        "#api-navbar": this.apiBar
+      },
+      afterRender: function(){
+
+      }
+    });
+
+    this.layoutViews = {};
+    //this.hooks = {};
+
+    this.el = this.layout.el;
+  };
+
+  // creatings the dashboard object same way backbone does
+  _.extend(Layout.prototype, {
+    render: function () {
+      return this.layout.render();
+    },
+
+    setTemplate: function(template) {
+      if (template.prefix){
+        this.layout.template = template.prefix + template.name;
+      } else{
+        this.layout.template = "templates/layouts/" + template;
+      }
+      // If we're changing layouts all bets are off, so kill off all the
+      // existing views in the layout.
+      _.each(this.layoutViews, function(view){view.remove();});
+      this.layoutViews = {};
+      this.render();
+    },
+
+    setTabs: function(view){
+      // TODO: Not sure I like this - seems fragile/repetitive
+      this.tabs = this.layout.setView("#tabs", view);
+      this.tabs.render();
+    },
+
+    setBreadcrumbs: function(view) {
+      this.breadcrumbs = this.layout.setView("#breadcrumbs", view);
+      this.breadcrumbs.render();
+    },
+
+    clearBreadcrumbs: function () {
+      if (!this.breadcrumbs) {return ;}
+
+      this.breadcrumbs.remove();
+    },
+
+    setView: function(selector, view) {
+      this.layoutViews[selector] = this.layout.setView(selector, view, false);
+    },
+
+    renderView: function(selector) {
+      var view = this.layoutViews[selector];
+      if (!view) {
+        return false;
+      } else {
+        return view.render();
+      }
+    }
+
+  });
+
+  return Layout;
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/api_bar.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/api_bar.html b/app/addons/fauxton/templates/api_bar.html
new file mode 100644
index 0000000..1f03a2c
--- /dev/null
+++ b/app/addons/fauxton/templates/api_bar.html
@@ -0,0 +1,30 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<button class="button api-url-btn">
+  API URL 
+  <span class="fonticon-plus icon"></span>
+</button>
+<div class="api-navbar" style="display: none">
+    <div class="input-prepend input-append">
+      <span class="add-on">
+        API reference
+        <a href="<%=getDocUrl(documentation)%>" target="_blank">
+          <i class="icon-question-sign"></i>
+        </a>
+      </span>
+      <input type="text" class="input-xxlarge" value="<%= endpoint %>">
+      <a href="<%= endpoint %>" target="_blank" class="btn">Show me</a>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/breadcrumbs.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/breadcrumbs.html b/app/addons/fauxton/templates/breadcrumbs.html
new file mode 100644
index 0000000..026db89
--- /dev/null
+++ b/app/addons/fauxton/templates/breadcrumbs.html
@@ -0,0 +1,24 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<ul class="breadcrumb">
+  <% _.each(_.initial(crumbs), function(crumb) { %>
+    <li>
+      <a href="#<%= crumb.link %>"><%= crumb.name %></a>
+      <span class="divider fonticon fonticon-carrot"> </span>
+    </li>
+  <% }); %>
+  <% var last = _.last(crumbs) || {name: ''} %>
+  <li class="active"><%= last.name %></li>
+</ul>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/footer.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/footer.html b/app/addons/fauxton/templates/footer.html
new file mode 100644
index 0000000..593c11f
--- /dev/null
+++ b/app/addons/fauxton/templates/footer.html
@@ -0,0 +1,15 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<p>Fauxton on <a href="http://couchdb.apache.org/">Apache CouchDB</a> <%=version%></p>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/index_pagination.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/index_pagination.html b/app/addons/fauxton/templates/index_pagination.html
new file mode 100644
index 0000000..f445377
--- /dev/null
+++ b/app/addons/fauxton/templates/index_pagination.html
@@ -0,0 +1,24 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="pagination pagination-centered">
+  <ul>
+    <li <% if (!canShowPreviousfn()) {%> class="disabled" <% } %>>
+       <a id="previous" href="#"> Previous </a>
+     </li>
+     <li <% if (!canShowNextfn()) {%> class="disabled" <% } %>>
+       <a id="next" href="#"> Next </a></li>
+  </ul>
+</div>
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/nav_bar.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/nav_bar.html b/app/addons/fauxton/templates/nav_bar.html
new file mode 100644
index 0000000..da030d6
--- /dev/null
+++ b/app/addons/fauxton/templates/nav_bar.html
@@ -0,0 +1,75 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="brand">
+  <div class="burger">
+    <div><!-- * --></div>
+    <div><!-- * --></div>
+    <div><!-- * --></div>
+  </div>
+  <div class="icon">Apache Fauxton</div>
+</div>
+
+<nav id="main_navigation">
+  <ul id="nav-links" class="nav pull-right">
+    <% _.each(navLinks, function(link) { %>
+    <% if (link.view) {return;}  %>
+        <li data-nav-name= "<%= link.title %>" >
+          <a href="<%= link.href %>">
+            <span class="<%= link.icon %> fonticon"></span>
+            <%= link.title %>
+          </a>
+        </li>
+    <% }); %>
+  </ul>
+
+  <div id="footer-links">
+
+    <ul id="bottom-nav-links" class="nav">
+        <li data-nav-name= "Documentation">
+            <a href="<%=getDocUrl('docs')%>" target="_blank">
+              <span class="fonticon-bookmark fonticon"></span>
+                Documentation
+            </a>
+        </li>
+
+
+      <% _.each(bottomNavLinks, function(link) { %>
+      <% if (link.view) {return;}  %>
+        <li data-nav-name= "<%= link.title %>">
+            <a href="<%= link.href %>">
+              <span class="<%= link.icon %> fonticon"></span>
+              <%= link.title %>
+            </a>
+        </li>
+      <% }); %>
+    </ul>
+
+    <ul id="footer-nav-links" class="nav">
+      <% _.each(footerNavLinks, function(link) { %>
+      <% if (link.view) {return;}  %>
+        <li data-nav-name= "<%= link.title %>">
+            <a href="<%= link.href %>">
+              <span class="<%= link.icon %> fonticon"></span>
+              <%= link.title %>
+            </a>
+        </li>
+      <% }); %>
+    </ul>
+
+  </div>
+</nav>
+
+
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/notification.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/notification.html b/app/addons/fauxton/templates/notification.html
new file mode 100644
index 0000000..ca8a903
--- /dev/null
+++ b/app/addons/fauxton/templates/notification.html
@@ -0,0 +1,18 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="alert alert-<%= type %>">
+  <button type="button" class="close" data-dismiss="alert">×</button>
+  <%= msg %>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/fauxton/templates/pagination.html
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/templates/pagination.html b/app/addons/fauxton/templates/pagination.html
new file mode 100644
index 0000000..19dfc8c
--- /dev/null
+++ b/app/addons/fauxton/templates/pagination.html
@@ -0,0 +1,31 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+-->
+
+<div class="pagination pagination-centered">
+  <ul>
+    <% if (page > 1) { %>
+    <li> <a href="<%= urlFun(page-1) %>">&laquo;</a></li>
+    <% } else { %>
+      <li class="disabled"> <a href="<%= urlFun(page) %>">&laquo;</a></li>
+    <% } %>
+    <% _.each(_.range(1, totalPages+1), function(i) { %>
+      <li <% if (page == i) { %>class="active"<% } %>> <a href="<%= urlFun(i) %>"><%= i %></a></li>
+    <% }) %>
+    <% if (page < totalPages) { %>
+      <li><a href="<%= urlFun(page+1) %>">&raquo;</a></li>
+    <% } else { %>
+      <li class="disabled"> <a href="<%= urlFun(page) %>">&raquo;</a></li>
+    <% } %>
+  </ul>
+</div>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/permissions/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/permissions/routes.js b/app/addons/permissions/routes.js
index 89c2bd7..0e9fa52 100644
--- a/app/addons/permissions/routes.js
+++ b/app/addons/permissions/routes.js
@@ -13,7 +13,7 @@
 define([
        "app",
        "api",
-       "modules/databases/base",
+       "addons/databases/base",
        "addons/permissions/views"
 ],
 function (app, FauxtonAPI, Databases, Permissions) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/pouchdb/base.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/base.js b/app/addons/pouchdb/base.js
new file mode 100644
index 0000000..df6c726
--- /dev/null
+++ b/app/addons/pouchdb/base.js
@@ -0,0 +1,47 @@
+/*
+ * NOTE:
+ * This temporarily uses the PouchDB map reduce implementation
+ * These files are modified locally until we make a more general version and
+ * push it back upstream.
+ */
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/pouchdb/pouchdb.mapreduce.js"
+],
+
+function(app, FauxtonAPI, MapReduce) {
+  var Pouch = FauxtonAPI.addon();
+  Pouch.MapReduce = MapReduce;
+
+  Pouch.runViewQuery = function(fun, opts) {
+    /*docs = [
+      {_id: 'test_doc_1', foo: 'bar-1'},
+      {_id: 'test_doc_2', foo: 'bar-2'},
+      {_id: 'test_doc_3', foo: 'bar-3'},
+      {_id: 'test_doc_4', foo: 'bar-4'},
+      {_id: 'test_doc_5', foo: 'bar-5'},
+      {_id: 'test_doc_6', foo: 'bar-6'},
+      {_id: 'test_doc_7', foo: 'bar-7'},
+      {_id: 'test_doc_8', foo: 'bar-8'},
+      {_id: 'test_doc_9', foo: 'bar-9'},
+      {_id: 'test_doc_10', foo: 'bar-10'}
+    ];*/
+
+    var deferred = FauxtonAPI.Deferred();
+    var complete = function(resp, rows) {
+      deferred.resolve(rows);
+    };
+
+    var options = _.extend(opts, {complete: complete});
+
+    Pouch.MapReduce.query(fun, options);
+    return deferred;
+  };
+  //pdb.runViewQuery({map:function(doc) { emit(doc._id, doc.foo) }})
+  return Pouch;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/pouchdb/pouch.collate.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/pouch.collate.js b/app/addons/pouchdb/pouch.collate.js
new file mode 100644
index 0000000..6c64410
--- /dev/null
+++ b/app/addons/pouchdb/pouch.collate.js
@@ -0,0 +1,115 @@
+/*
+ * NOTE:
+ * This temporarily uses the PouchDB map reduce implementation
+ * These files are modified locally until we make a more general version and
+ * push it back upstream.
+ * Original file:
+ * https://github.com/daleharvey/pouchdb/blob/master/src/pouch.collate.js
+ */
+
+/*
+(function() {
+  // a few hacks to get things in the right place for node.js
+  if (typeof module !== 'undefined' && module.exports) {
+    module.exports = Pouch;
+  }
+*/
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/pouchdb/pouch.collate.js"
+],
+
+function(app, FauxtonAPI, Collate) {
+  var Pouch = {};
+
+  Pouch.collate = function(a, b) {
+    var ai = collationIndex(a);
+    var bi = collationIndex(b);
+    if ((ai - bi) !== 0) {
+      return ai - bi;
+    }
+    if (a === null) {
+      return 0;
+    }
+    if (typeof a === 'number') {
+      return a - b;
+    }
+    if (typeof a === 'boolean') {
+      return a < b ? -1 : 1;
+    }
+    if (typeof a === 'string') {
+      return stringCollate(a, b);
+    }
+    if (Array.isArray(a)) {
+      return arrayCollate(a, b);
+    }
+    if (typeof a === 'object') {
+      return objectCollate(a, b);
+    }
+  };
+
+  var stringCollate = function(a, b) {
+    // See: https://github.com/daleharvey/pouchdb/issues/40
+    // This is incompatible with the CouchDB implementation, but its the
+    // best we can do for now
+    return (a === b) ? 0 : ((a > b) ? 1 : -1);
+  };
+
+  var objectCollate = function(a, b) {
+    var ak = Object.keys(a), bk = Object.keys(b);
+    var len = Math.min(ak.length, bk.length);
+    for (var i = 0; i < len; i++) {
+      // First sort the keys
+      var sort = Pouch.collate(ak[i], bk[i]);
+      if (sort !== 0) {
+        return sort;
+      }
+      // if the keys are equal sort the values
+      sort = Pouch.collate(a[ak[i]], b[bk[i]]);
+      if (sort !== 0) {
+        return sort;
+      }
+
+    }
+    return (ak.length === bk.length) ? 0 :
+      (ak.length > bk.length) ? 1 : -1;
+  };
+
+  var arrayCollate = function(a, b) {
+    var len = Math.min(a.length, b.length);
+    for (var i = 0; i < len; i++) {
+      var sort = Pouch.collate(a[i], b[i]);
+      if (sort !== 0) {
+        return sort;
+      }
+    }
+    return (a.length === b.length) ? 0 :
+      (a.length > b.length) ? 1 : -1;
+  };
+
+  // The collation is defined by erlangs ordered terms
+  // the atoms null, true, false come first, then numbers, strings,
+  // arrays, then objects
+  var collationIndex = function(x) {
+    var id = ['boolean', 'number', 'string', 'object'];
+    if (id.indexOf(typeof x) !== -1) {
+      if (x === null) {
+        return 1;
+      }
+      return id.indexOf(typeof x) + 2;
+    }
+    if (Array.isArray(x)) {
+      return 4.5;
+    }
+  };
+
+  return Pouch;
+
+//}).call(this);
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/pouchdb/pouchdb.mapreduce.js
----------------------------------------------------------------------
diff --git a/app/addons/pouchdb/pouchdb.mapreduce.js b/app/addons/pouchdb/pouchdb.mapreduce.js
new file mode 100644
index 0000000..224a6f6
--- /dev/null
+++ b/app/addons/pouchdb/pouchdb.mapreduce.js
@@ -0,0 +1,324 @@
+/*
+ * NOTE:
+ * This temporarily uses the PouchDB map reduce implementation
+ * These files are modified locally until we make a more general version and
+ * push it back upstream.
+ * Original file:
+ * https://github.com/daleharvey/pouchdb/blob/master/src/plugins/pouchdb.mapreduce.js
+ */
+
+/*global Pouch: true */
+
+//"use strict";
+
+// This is the first implementation of a basic plugin, we register the
+// plugin object with pouch and it is mixin'd to each database created
+// (regardless of adapter), adapters can override plugins by providing
+// their own implementation. functions on the plugin object that start
+// with _ are reserved function that are called by pouchdb for special
+// notifications.
+
+// If we wanted to store incremental views we can do it here by listening
+// to the changes feed (keeping track of our last update_seq between page loads)
+// and storing the result of the map function (possibly using the upcoming
+// extracted adapter functions)
+
+define([
+  "app",
+
+  "api",
+
+  // Modules
+  "addons/pouchdb/pouch.collate.js"
+],
+
+function(app, FauxtonAPI, Collate) {
+  var Pouch = {};
+  Pouch.collate = Collate.collate;
+
+  //var MapReduce = function(db) {
+  var MapReduce = function() {
+
+    var builtInReduce = {
+      "_sum": function(keys, values){
+        return sum(values);
+      },
+
+      "_count": function(keys, values, rereduce){
+        if (rereduce){
+          return sum(values);
+        } else {
+          return values.length;
+        }
+      },
+
+      "_stats": function(keys, values, rereduce){
+        return {
+          'sum': sum(values),
+          'min': Math.min.apply(null, values),
+          'max': Math.max.apply(null, values),
+          'count': values.length,
+          'sumsqr': (function(){
+            _sumsqr = 0;
+            for(var idx in values){
+              _sumsqr += values[idx] * values[idx];
+            }
+            return _sumsqr;
+          })()
+        };
+      }
+    };
+
+    function viewQuery(fun, options) {
+      console.log("IN VIEW QUERY");
+      if (!options.complete) {
+        return;
+      }
+
+      function sum(values) {
+        return values.reduce(function(a, b) { return a + b; }, 0);
+      }
+
+      var results = [];
+      var current = null;
+      var num_started= 0;
+      var completed= false;
+
+      var emit = function(key, val) {
+        //console.log("IN EMIT: ", key, val, current);
+        var viewRow = {
+          id: current.doc._id,
+          key: key,
+          value: val
+        }; 
+        //console.log("VIEW ROW: ", viewRow);
+
+        if (options.startkey && Pouch.collate(key, options.startkey) < 0) return;
+        if (options.endkey && Pouch.collate(key, options.endkey) > 0) return;
+        if (options.key && Pouch.collate(key, options.key) !== 0) return;
+        num_started++;
+        if (options.include_docs) {
+          // TODO:: FIX
+          throw({error: "Include Docs not supported"});
+          /*
+
+          //in this special case, join on _id (issue #106)
+          if (val && typeof val === 'object' && val._id){
+            db.get(val._id,
+                function(_, joined_doc){
+                  if (joined_doc) {
+                    viewRow.doc = joined_doc;
+                  }
+                  results.push(viewRow);
+                  checkComplete();
+                });
+            return;
+          } else {
+            viewRow.doc = current.doc;
+          }
+          */
+        }
+        console.log("EMITTING: ", viewRow);
+        results.push(viewRow);
+      };
+
+      // ugly way to make sure references to 'emit' in map/reduce bind to the
+      // above emit
+      eval('fun.map = ' + fun.map.toString() + ';');
+      if (fun.reduce && options.reduce) {
+        if (builtInReduce[fun.reduce]) {
+          console.log('built in reduce');
+          fun.reduce = builtInReduce[fun.reduce];
+        }
+        eval('fun.reduce = ' + fun.reduce.toString() + ';');
+      }
+
+      // exclude  _conflicts key by default
+      // or to use options.conflicts if it's set when called by db.query
+      var conflicts = ('conflicts' in options ? options.conflicts : false);
+
+      //only proceed once all documents are mapped and joined
+      var checkComplete= function(){
+        console.log('check');
+        if (completed && results.length == num_started){
+          results.sort(function(a, b) {
+            return Pouch.collate(a.key, b.key);
+          });
+          if (options.descending) {
+            results.reverse();
+          }
+          if (options.reduce === false) {
+            return options.complete(null, {rows: results});
+          }
+
+          console.log('reducing', options);
+          var groups = [];
+          results.forEach(function(e) {
+            var last = groups[groups.length-1] || null;
+            if (last && Pouch.collate(last.key[0][0], e.key) === 0) {
+              last.key.push([e.key, e.id]);
+              last.value.push(e.value);
+              return;
+            }
+            groups.push({key: [[e.key, e.id]], value: [e.value]});
+          });
+          groups.forEach(function(e) {
+            e.value = fun.reduce(e.key, e.value) || null;
+            e.key = e.key[0][0];
+          });
+          console.log('GROUPs', groups);
+          options.complete(null, {rows: groups});
+        }
+      };
+
+      if (options.docs) {
+        //console.log("RUNNING MR ON DOCS: ", options.docs);
+        _.each(options.docs, function(doc) {
+          current = {doc: doc};
+          fun.map.call(this, doc);
+        }, this);
+        completed = true;
+        return checkComplete();//options.complete(null, {rows: results});
+      } else {
+        //console.log("COULD NOT FIND DOCS");
+        return false;
+      }
+
+      /*
+      db.changes({
+        conflicts: conflicts,
+        include_docs: true,
+        onChange: function(doc) {
+          if (!('deleted' in doc)) {
+            current = {doc: doc.doc};
+            fun.map.call(this, doc.doc);
+          }
+        },
+        complete: function() {
+          completed= true;
+          checkComplete();
+        }
+      });
+      */
+    }
+
+    /*
+    function httpQuery(fun, opts, callback) {
+
+      // List of parameters to add to the PUT request
+      var params = [];
+      var body = undefined;
+      var method = 'GET';
+
+      // If opts.reduce exists and is defined, then add it to the list
+      // of parameters.
+      // If reduce=false then the results are that of only the map function
+      // not the final result of map and reduce.
+      if (typeof opts.reduce !== 'undefined') {
+        params.push('reduce=' + opts.reduce);
+      }
+      if (typeof opts.include_docs !== 'undefined') {
+        params.push('include_docs=' + opts.include_docs);
+      }
+      if (typeof opts.limit !== 'undefined') {
+        params.push('limit=' + opts.limit);
+      }
+      if (typeof opts.descending !== 'undefined') {
+        params.push('descending=' + opts.descending);
+      }
+      if (typeof opts.startkey !== 'undefined') {
+        params.push('startkey=' + encodeURIComponent(JSON.stringify(opts.startkey)));
+      }
+      if (typeof opts.endkey !== 'undefined') {
+        params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey)));
+      }
+      if (typeof opts.key !== 'undefined') {
+        params.push('key=' + encodeURIComponent(JSON.stringify(opts.key)));
+      }
+
+      // If keys are supplied, issue a POST request to circumvent GET query string limits
+      // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
+      if (typeof opts.keys !== 'undefined') {
+        method = 'POST';
+        body = JSON.stringify({keys:opts.keys});
+      }
+
+      // Format the list of parameters into a valid URI query string
+      params = params.join('&');
+      params = params === '' ? '' : '?' + params;
+
+      // We are referencing a query defined in the design doc
+      if (typeof fun === 'string') {
+        var parts = fun.split('/');
+        db.request({
+          method: method,
+          url: '_design/' + parts[0] + '/_view/' + parts[1] + params,
+          body: body
+        }, callback);
+        return;
+      }
+
+      // We are using a temporary view, terrible for performance but good for testing
+      var queryObject = JSON.parse(JSON.stringify(fun, function(key, val) {
+        if (typeof val === 'function') {
+          return val + ''; // implicitly `toString` it
+        }
+        return val;
+      }));
+
+      db.request({
+        method:'POST',
+        url: '_temp_view' + params,
+        body: queryObject
+      }, callback);
+    }
+    */
+
+    function query(fun, opts, callback) {
+      if (typeof opts === 'function') {
+        callback = opts;
+        opts = {};
+      }
+
+      if (callback) {
+        opts.complete = callback;
+      }
+
+      /*
+      if (db.type() === 'http') {
+        return httpQuery(fun, opts, callback);
+      }
+      */
+
+      if (typeof fun === 'object') {
+        console.log("RUNNING VIEW QUERY", fun, opts, arguments);
+        return viewQuery(fun, opts);
+      }
+
+      throw({error: "Shouldn't have gotten here"});
+
+      /*
+      var parts = fun.split('/');
+      db.get('_design/' + parts[0], function(err, doc) {
+        if (err) {
+          if (callback) callback(err);
+          return;
+        }
+        viewQuery({
+          map: doc.views[parts[1]].map,
+          reduce: doc.views[parts[1]].reduce
+        }, opts);
+      });
+      */
+    }
+
+    return {'query': query};
+  };
+
+  // Deletion is a noop since we dont store the results of the view
+  MapReduce._delete = function() { };
+
+  //Pouch.plugin('mapreduce', MapReduce);
+
+  return MapReduce();
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/replication/views.js
----------------------------------------------------------------------
diff --git a/app/addons/replication/views.js b/app/addons/replication/views.js
index f4b96fd..1b31a9d 100644
--- a/app/addons/replication/views.js
+++ b/app/addons/replication/views.js
@@ -13,7 +13,7 @@
 define([
        "app",
        "api",
-       "modules/fauxton/components",
+       "addons/fauxton/components",
        "addons/replication/resources"
 ],
 function(app, FauxtonAPI, Components, replication) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/stats/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/stats/resources.js b/app/addons/stats/resources.js
index a761e6b..b3c4ce1 100644
--- a/app/addons/stats/resources.js
+++ b/app/addons/stats/resources.js
@@ -15,7 +15,7 @@ define([
        "api",
        "backbone",
        "lodash",
-       "modules/fauxton/base"
+       "addons/fauxton/base"
 ],
 
 function (app, FauxtonAPI, backbone, _, Fauxton) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/addons/verifyinstall/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/verifyinstall/resources.js b/app/addons/verifyinstall/resources.js
index 5d83f9a..8a98883 100644
--- a/app/addons/verifyinstall/resources.js
+++ b/app/addons/verifyinstall/resources.js
@@ -13,8 +13,8 @@
 define([
   "app",
   "api",
-  "modules/databases/resources",
-  "modules/documents/resources"
+  "addons/databases/resources",
+  "addons/documents/resources"
 ],
 
 function (app, FauxtonAPI, Databases, Documents) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/api.js
----------------------------------------------------------------------
diff --git a/app/api.js b/app/api.js
index 5ad032a..c9d08bf 100644
--- a/app/api.js
+++ b/app/api.js
@@ -14,7 +14,7 @@ define([
        "app",
 
        // Modules
-       "modules/fauxton/base",
+       "addons/fauxton/base",
        "spin"
 ],
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/app.js
----------------------------------------------------------------------
diff --git a/app/app.js b/app/app.js
index 0a51410..9ac5bc2 100644
--- a/app/app.js
+++ b/app/app.js
@@ -22,6 +22,8 @@ define([
 
   "helpers",
   "mixins",
+  // Modules
+  "resizeColumns",
 
    // Plugins.
   "plugins/backbone.layoutmanager",
@@ -29,7 +31,7 @@ define([
 
 ],
 
-function(app, $, _, Backbone, Bootstrap, Helpers, Mixins) {
+function(app, $, _, Backbone, Bootstrap, Helpers, Mixins, resizeColumns) {
 
    // Make sure we have a console.log
   if (typeof console == "undefined") {
@@ -81,6 +83,10 @@ function(app, $, _, Backbone, Bootstrap, Helpers, Mixins) {
     }
   });
 
+  //resizeAnimation
+  app.resizeColumns = new resizeColumns({});
+  app.resizeColumns.onResizeHandler();
+
   // Localize or create a new JavaScript Template object.
   var JST = window.JST = window.JST || {};
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/databases/base.js
----------------------------------------------------------------------
diff --git a/app/modules/databases/base.js b/app/modules/databases/base.js
deleted file mode 100644
index 6ff12c6..0000000
--- a/app/modules/databases/base.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/databases/routes",
-  // Views
-  "modules/databases/views"
-
-],
-
-function(app, FauxtonAPI, Databases, Views) {
-  Databases.Views = Views;
-
-  // Utility functions
-  Databases.databaseUrl = function(database) {
-    var name = _.isObject(database) ? database.id : database,
-        dbname = app.mixins.safeURLName(name);
-
-    return ["/database/", dbname, "/_all_docs?limit=" + Databases.DocLimit].join('');
-  };
-
-  return Databases;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/modules/databases/resources.js b/app/modules/databases/resources.js
deleted file mode 100644
index f3bde80..0000000
--- a/app/modules/databases/resources.js
+++ /dev/null
@@ -1,193 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/documents/resources"
-],
-
-function(app, FauxtonAPI, Documents) {
-  var Databases = FauxtonAPI.module();
-
-  Databases.DocLimit = 20;
-
-  Databases.Model = Backbone.Model.extend({
-    initialize: function(options) {
-      this.status = new Databases.Status({
-        database: this
-      });
-    },
-
-    documentation: function(){
-      return "all_dbs";
-    },
-    
-    buildAllDocs: function(params) {
-      this.allDocs = new Documents.AllDocs(null, {
-        database: this,
-        params: params
-      });
-
-      return this.allDocs;
-    },
-
-    isNew: function(){
-      // Databases are never new, to make Backbone do a PUT
-      return false;
-    },
-
-    url: function(context) {
-      if (context === "index") {
-        return "/database/" + this.safeID() + "/_all_docs";
-      } else if (context === "web-index") {
-        return "#/database/"+ this.safeID() + "/_all_docs?limit=" + Databases.DocLimit;
-      } else if (context === "apiurl") { 
-        return window.location.origin + "/database/" + this.safeID() + "/_all_docs";
-      } else if (context === "changes") {
-        return "/database/" + this.safeID() + "/_changes?descending=true&limit=100&include_docs=true";
-      } else if (context === "changes-apiurl") { 
-        return window.location.origin + "/database/" + this.safeID() + "/_changes?descending=true&limit=100&include_docs=true";
-      } else if (context === "app") {
-        return "/database/" + this.safeID();
-      } else {
-        return app.host + "/" + this.safeID();
-      }
-    },
-    safeName: function(){
-      return app.mixins.safeURLName(this.get("name"));
-    },
-    safeID: function() {
-      return app.mixins.safeURLName(this.id);
-    },
-    buildChanges: function (params) {
-      this.changes = new Databases.Changes({
-        database: this,
-        params: params
-      });
-
-      return this.changes;
-    }
-  });
-
-  Databases.Changes = Backbone.Collection.extend({
-
-    initialize: function(options) {
-      this.database = options.database;
-      this.params = options.params;
-    },
-    documentation: function(){
-      return "changes";
-    },
-    url: function (context) {
-      var query = "";
-      if (this.params) {
-        query = "?" + $.param(this.params);
-      }
-      if (context === "apiurl") { 
-        return window.location.origin + '/' + this.database.safeID() + '/_changes' + query;
-      } else {
-
-      return app.host + '/' + this.database.safeID() + '/_changes' + query;
-      }
-    },
-
-    parse: function (resp) {
-      this.last_seq = resp.last_seq;
-      return resp.results;
-    }
-  });
-
-  Databases.Status = Backbone.Model.extend({
-    url: function() {
-      return app.host + "/" + this.database.safeID();
-    },
-
-    initialize: function(options) {
-      this.database = options.database;
-    },
-
-    numDocs: function() {
-      return this.get("doc_count");
-    },
-
-    updateSeq: function(full) {
-      var updateSeq = this.get("update_seq");
-      if (full || (typeof(updateSeq) === 'number')) {
-        return updateSeq;
-      } else if (updateSeq) {
-        return updateSeq.split('-')[0];
-      } else {
-        return 0;
-      }
-    },
-
-    humanSize: function() {
-      // cribbed from http://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable
-      var i = -1;
-      var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
-      var fileSizeInBytes = this.dataSize();
-
-      if (!fileSizeInBytes) {
-        return 0;
-      }
-
-      do {
-          fileSizeInBytes = fileSizeInBytes / 1024;
-          i++;
-      } while (fileSizeInBytes > 1024);
-
-      return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
-    },
-    diskSize: function () {
-      return this.get("disk_size");
-    },
-
-    dataSize: function () {
-      if (this.get("other")){
-        return this.get("other").data_size;
-      }else{
-        return 0;
-      }  
-    }
-  });
-
-  // TODO: shared databases - read from the user doc
-  Databases.List = Backbone.Collection.extend({
-    model: Databases.Model,
-    documentation: function(){
-      return "all_dbs";
-    },
-    url: function(context) {
-      if (context === "apiurl") { 
-        return window.location.origin + "/_all_dbs";
-      } else {
-        return app.host + "/_all_dbs";
-      }
-    },
-
-    parse: function(resp) {
-      // TODO: pagination!
-      return _.map(resp, function(database) {
-        return {
-          id: app.mixins.safeURLName(database),
-          name: database
-        };
-      });
-    }
-  });
-
-  return Databases;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/databases/routes.js
----------------------------------------------------------------------
diff --git a/app/modules/databases/routes.js b/app/modules/databases/routes.js
deleted file mode 100644
index ca3d640..0000000
--- a/app/modules/databases/routes.js
+++ /dev/null
@@ -1,69 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/databases/resources",
-  // TODO:: fix the include flow modules so we don't have to require views here
-  "modules/databases/views"
-],
-
-function(app, FauxtonAPI, Databases, Views) {
-
-  var AllDbsRouteObject = FauxtonAPI.RouteObject.extend({
-    layout: "one_pane",
-
-    crumbs: [
-      {"name": "Databases", "link": "/_all_dbs"}
-    ],
-
-    routes: {
-      "": "allDatabases",
-      "index.html": "allDatabases",
-      "_all_dbs(:params)": "allDatabases"
-    },
-
-    apiUrl: function() {
-      return [this.databases.url("apiurl"), this.databases.documentation()];
-    },
-
-    selectedHeader: "Databases",
-
-    initialize: function() {
-      this.databases = new Databases.List();
-      this.deferred = FauxtonAPI.Deferred();
-    },
-
-    allDatabases: function() {
-      var params = app.getParams(),
-          dbPage = params.page;
-
-      this.databasesView = this.setView("#dashboard-content", new Views.List({
-        collection: this.databases
-      }));
-
-      this.databasesView.setPage(dbPage);
-    },
-
-    establish: function() {
-     return [this.databases.fetch()];
-    }
-  });
-
-  Databases.RouteObjects = [AllDbsRouteObject];
-
-  return Databases;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/databases/views.js
----------------------------------------------------------------------
diff --git a/app/modules/databases/views.js b/app/modules/databases/views.js
deleted file mode 100644
index dbeb475..0000000
--- a/app/modules/databases/views.js
+++ /dev/null
@@ -1,255 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-  
-  "modules/fauxton/components",
-  "api",
-  "modules/databases/resources"
-],
-
-function(app, Components, FauxtonAPI, Databases) {
-  var Views = {};
-
-  Views.Item = FauxtonAPI.View.extend({
-    template: "templates/databases/item",
-    tagName: "tr",
-    establish: function(){
-      return [this.model.fetch()];
-    },
-    serialize: function() {
-      return {
-        encoded: app.mixins.safeURLName(this.model.get("name")),
-        database: this.model,
-        docLimit: Databases.DocLimit
-      };
-    }
-  });
-
-  Views.List = FauxtonAPI.View.extend({
-    dbLimit: 20,
-    perPage: 20,
-    template: "templates/databases/list",
-    events: {
-      "click button.all": "selectAll",
-      "submit form#jump-to-db": "switchDatabase"
-    },
-
-    initialize: function(options) {
-      var params = app.getParams();
-      this.page = params.page ? parseInt(params.page, 10) : 1;
-    },
-
-    serialize: function() {
-      return {
-        databases: this.collection
-      };
-    },
-    establish: function(){
-      var currentDBs = this.paginated();
-      var deferred = FauxtonAPI.Deferred();
-
-      FauxtonAPI.when(currentDBs.map(function(database) {
-        return database.status.fetch();
-      })).always(function(resp) {
-        //make this always so that even if a user is not allowed access to a database
-        //they will still see a list of all databases
-        deferred.resolve();
-      });
-      return [deferred];
-    },
-    switchDatabase: function(event, selectedName) {
-      event && event.preventDefault();
-
-      var dbname = this.$el.find("[name='search-query']").val().trim();
-
-      if (selectedName) {
-        dbname = selectedName;
-      }
-
-      if (dbname && this.collection.where({"id":app.mixins.safeURLName(dbname)}).length > 0){
-          // TODO: switch to using a model, or Databases.databaseUrl()
-          // Neither of which are in scope right now
-          // var db = new Database.Model({id: dbname});
-          var url = ["/database/", app.mixins.safeURLName(dbname), "/_all_docs?limit=" + Databases.DocLimit].join('');
-          FauxtonAPI.navigate(url);
-      } else {
-        FauxtonAPI.addNotification({
-          msg: 'Database does not exist.',
-          type: 'error'
-        });
-      }
-    },
-
-    paginated: function() {
-      var start = (this.page - 1) * this.perPage;
-      var end = this.page * this.perPage;
-      return this.collection.slice(start, end);
-    },
-
-    beforeRender: function() {
-
-      this.insertView("#newButton", new Views.NewDatabaseButton({
-        collection: this.collection
-      }));
-
-      _.each(this.paginated(), function(database) {
-        this.insertView("table.databases tbody", new Views.Item({
-          model: database
-        }));
-      }, this);
-
-      this.insertView("#database-pagination", new Components.Pagination({
-        page: this.page,
-        perPage: this.perPage,
-        total: this.collection.length,
-        urlFun: function(page) {
-          return "#/_all_dbs?page=" + page;
-        }
-      }));
-    },
-
-    setPage: function(page) {
-      this.page = page || 1;
-    },
-
-    afterRender: function() {
-      var that = this;
-      this.dbSearchTypeahead = new Components.DbSearchTypeahead({
-        dbLimit: this.dbLimit,
-        el: "input.search-autocomplete",
-        onUpdate: function (item) {
-          that.switchDatabase(null, item);
-        }
-      });
-
-      this.dbSearchTypeahead.render();
-    },
-
-    selectAll: function(evt){
-      $("input:checkbox").attr('checked', !$(evt.target).hasClass('active'));
-    }
-  });
-
-
-  Views.NewDatabaseButton = FauxtonAPI.View.extend({
-    template: "templates/databases/newdatabase",
-    events: {
-      "click a#new": "newDatabase"
-    },
-    newDatabase: function() {
-      var notification;
-      var db;
-      // TODO: use a modal here instead of the prompt
-      var name = prompt('Name of database', 'newdatabase');
-      if (name === null) {
-        return;
-      } else if (name.length === 0) {
-        notification = FauxtonAPI.addNotification({
-          msg: "Please enter a valid database name",
-          type: "error",
-          clear: true
-        });
-        return;
-      }
-      db = new this.collection.model({
-        id: name,
-        name: name
-      });
-      notification = FauxtonAPI.addNotification({msg: "Creating database."});
-      db.save().done(function() {
-        notification = FauxtonAPI.addNotification({
-          msg: "Database created successfully",
-          type: "success",
-          clear: true
-        });
-        var route = "#/database/" +  app.mixins.safeURLName(name) + "/_all_docs?limit=" + Databases.DocLimit;
-        app.router.navigate(route, { trigger: true });
-      }
-      ).error(function(xhr) {
-        var responseText = JSON.parse(xhr.responseText).reason;
-        notification = FauxtonAPI.addNotification({
-          msg: "Create database failed: " + responseText,
-          type: "error",
-          clear: true
-        });
-      }
-      );
-    }
-  });
-
-  Views.Sidebar = FauxtonAPI.View.extend({
-    template: "templates/databases/sidebar",
-    events: {
-      "click a#new": "newDatabase",
-      "click a#owned": "showMine",
-      "click a#shared": "showShared"
-    },
-
-    newDatabase: function() {
-      var notification;
-      var db;
-      // TODO: use a modal here instead of the prompt
-      var name = prompt('Name of database', 'newdatabase');
-      if (name === null) {
-        return;
-      } else if (name.length === 0) {
-        notification = FauxtonAPI.addNotification({
-          msg: "Please enter a valid database name",
-          type: "error",
-          clear: true
-        });
-        return;
-      }
-      db = new this.collection.model({
-        id: encodeURIComponent(name),
-        name: name
-      });
-      notification = FauxtonAPI.addNotification({msg: "Creating database."});
-      db.save().done(function() {
-        notification = FauxtonAPI.addNotification({
-          msg: "Database created successfully",
-          type: "success",
-          clear: true
-        });
-        var route = "#/database/" +  name + "/_all_docs?limit=" + Databases.DocLimit;
-        app.router.navigate(route, { trigger: true });
-      }
-      ).error(function(xhr) {
-        var responseText = JSON.parse(xhr.responseText).reason;
-        notification = FauxtonAPI.addNotification({
-          msg: "Create database failed: " + responseText,
-          type: "error",
-          clear: true
-        });
-      }
-      );
-    },
-
-    showMine: function(){
-      $.contribute(
-        'Show unshared databases',
-        'app/addons/databases/views.js'
-      );
-    },
-
-    showShared: function(){
-      $.contribute(
-        'Show shared databases (e.g. continuous replications to/from the database)',
-        'app/addons/databases/views.js'
-      );
-    }
-  });
-
-  return Views;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/documents/base.js
----------------------------------------------------------------------
diff --git a/app/modules/documents/base.js b/app/modules/documents/base.js
deleted file mode 100644
index 96e4ada..0000000
--- a/app/modules/documents/base.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-
-  "api",
-
-  // Modules
-  "modules/documents/routes"
-],
-
-function(app, FauxtonAPI, Documents) {
-  return Documents;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5f9a88f6/app/modules/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/modules/documents/resources.js b/app/modules/documents/resources.js
deleted file mode 100644
index 43bb0fd..0000000
--- a/app/modules/documents/resources.js
+++ /dev/null
@@ -1,646 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-  "api"
-],
-
-function(app, FauxtonAPI) {
-  var Documents = app.module();
-
-  Documents.Doc = Backbone.Model.extend({
-    idAttribute: "_id",
-    documentation: function(){
-      return "docs";
-    },
-    url: function(context) {
-      if (context === "app") {
-        return this.getDatabase().url("app") + "/" + this.safeID();
-      } else if (context === "web-index") {
-        return this.getDatabase().url("app") + "/" + app.mixins.safeURLName(this.id);
-      } else if (context === "apiurl"){
-        return window.location.origin + "/" + this.getDatabase().safeID() + "/" + this.safeID();
-      } else {
-        return app.host + "/" + this.getDatabase().safeID() + "/" + this.safeID();
-      }
-    },
-
-    initialize: function(_attrs, options) {
-      if (this.collection && this.collection.database) {
-        this.database = this.collection.database;
-      } else if (options.database) {
-        this.database = options.database;
-      }
-    },
-
-    // HACK: the doc needs to know about the database, but it may be
-    // set directly or indirectly in all docs
-    getDatabase: function() {
-      return this.database ? this.database : this.collection.database;
-    },
-
-    validate: function(attrs, options) {
-      if (this.id && this.id !== attrs._id && this.get('_rev') ) {
-        return "Cannot change a documents id.";
-      }
-    },
-
-    docType: function() {
-      return this.id.match(/^_design/) ? "design doc" : "doc";
-    },
-
-    isEditable: function() {
-      return this.docType() != "reduction";
-    },
-
-    isDdoc: function() {
-      return this.docType() === "design doc";
-    },
-
-    hasViews: function() {
-      if (!this.isDdoc()) return false;
-      var doc = this.get('doc');
-      if (doc) {
-        return doc && doc.views && _.keys(doc.views).length > 0;
-      }
-
-      var views = this.get('views');
-      return views && _.keys(views).length > 0;
-    },
-
-    hasAttachments: function () {
-      return !!this.get('_attachments');
-    },
-
-    getDdocView: function(view) {
-      if (!this.isDdoc() || !this.hasViews()) return false;
-
-      var doc = this.get('doc');
-      if (doc) {
-        return doc.views[view];
-      }
-
-      return this.get('views')[view];
-    },
-
-    setDdocView: function (view, map, reduce) {
-      if (!this.isDdoc()) return false;
-      var views = this.get('views');
-          tempView = views[view] || {};
-
-      if (reduce) {
-        tempView.reduce=reduce;
-      } else {
-        delete tempView.reduce;
-      }
-      tempView.map= map;
-
-      views[view] = tempView;
-      this.set({views: views});
-
-      return true;
-    },
-
-    removeDdocView: function (viewName) {
-      if (!this.isDdoc()) return false;
-      var views = this.get('views');
-
-      delete views[viewName];
-      this.set({views: views});
-    },
-
-    dDocModel: function () {
-      if (!this.isDdoc()) return false;
-      var doc = this.get('doc');
-
-      if (doc) {
-        return new Documents.Doc(doc, {database: this.database});
-      } 
-
-      return this;
-    },
-
-    viewHasReduce: function(viewName) {
-      var view = this.getDdocView(viewName);
-
-      return view && view.reduce;
-    },
-
-    // Need this to work around backbone router thinking _design/foo
-    // is a separate route. Alternatively, maybe these should be
-    // treated separately. For instance, we could default into the
-    // json editor for docs, or into a ddoc specific page.
-    safeID: function() {
-      if (this.isDdoc()){
-        var ddoc = this.id.replace(/^_design\//,"");
-        return "_design/"+app.mixins.safeURLName(ddoc);
-      }else{
-        return app.mixins.safeURLName(this.id);
-      }
-    },
-
-    destroy: function() {
-      var url = this.url() + "?rev=" + this.get('_rev');
-      return $.ajax({
-        url: url,
-        dataType: 'json',
-        type: 'DELETE'
-      });
-    },
-
-    parse: function(resp) {
-      if (resp.rev) {
-        resp._rev = resp.rev;
-        delete resp.rev;
-      }
-      if (resp.id) {
-        if (typeof(this.id) === "undefined") {
-          resp._id = resp.id;
-        }
-        delete resp.id;
-      }
-      if (resp.ok) {
-        delete resp.ok;
-      }
-      return resp;
-    },
-
-    prettyJSON: function() {
-      var data = this.get("doc") ? this.get("doc") : this;
-
-      return JSON.stringify(data, null, "  ");
-    },
-
-    copy: function (copyId) {
-      return $.ajax({
-        type: 'COPY',
-        url: '/' + this.database.safeID() + '/' + this.safeID(),
-        headers: {Destination: copyId}
-      });
-    },
-
-    isNewDoc: function () {
-      return this.get('_rev') ? false : true;
-    }
-  });
-
-  Documents.DdocInfo = Backbone.Model.extend({
-    idAttribute: "_id",
-    documentation: function(){
-      return "docs";
-    },
-    initialize: function (_attrs, options) {
-      this.database = options.database;
-    },
-
-    url: function(context) {
-      if (context === "app") {
-        return this.database.url("app") + "/" + this.safeID() + '/_info';
-      } else if (context === "apiurl"){
-        return window.location.origin + "/" + this.database.safeID() + "/" + this.safeID() + '/_info';
-      } else {
-        return app.host + "/" + this.database.safeID() + "/" + this.safeID() + '/_info';
-      }
-    },
-
-    // Need this to work around backbone router thinking _design/foo
-    // is a separate route. Alternatively, maybe these should be
-    // treated separately. For instance, we could default into the
-    // json editor for docs, or into a ddoc specific page.
-    safeID: function() {
-      var ddoc = this.id.replace(/^_design\//,"");
-      return "_design/"+app.mixins.safeURLName(ddoc);
-    }
-
-  });
-
-  Documents.ViewRow = Backbone.Model.extend({
-    // this is a hack so that backbone.collections doesn't group 
-    // these by id and reduce the number of items returned.
-    idAttribute: "_id",
-
-    docType: function() {
-      if (!this.id) return "reduction";
-
-      return this.id.match(/^_design/) ? "design doc" : "doc";
-    },
-    documentation: function(){
-      return "docs";
-    },
-    url: function(context) {
-      if (!this.isEditable()) return false;
-
-      return this.collection.database.url(context) + "/" + this.safeID();
-    },
-
-    isEditable: function() {
-      return this.docType() != "reduction";
-    },
-    safeID: function() {
-      return app.mixins.safeURLName(this.id);
-    },
-
-    prettyJSON: function() {
-      //var data = this.get("doc") ? this.get("doc") : this;
-      return JSON.stringify(this, null, "  ");
-    }
-  });
-
-  Documents.NewDoc = Documents.Doc.extend({
-    fetch: function() {
-      var uuid = new FauxtonAPI.UUID();
-      var deferred = this.deferred = $.Deferred();
-      var that = this;
-
-      uuid.fetch().done(function() {
-        that.set("_id", uuid.next());
-        deferred.resolve();
-      });
-
-      return deferred.promise();
-    }
-
-  });
-
-  Documents.AllDocs = Backbone.Collection.extend({
-    model: Documents.Doc,
-    documentation: function(){
-      return "docs";
-    },
-    initialize: function(_models, options) {
-      this.database = options.database;
-      this.params = options.params;
-      this.skipFirstItem = false;
-
-      this.on("remove",this.decrementTotalRows , this);
-    },
-
-    url: function(context) {
-      var query = "";
-      if (this.params) {
-        query = "?" + $.param(this.params);
-      }
-
-      if (context === 'app') {
-        return 'database/' + this.database.safeID() + "/_all_docs" + query;
-      } else if (context === "apiurl"){
-        return window.location.origin + "/" + this.database.safeID() + "/_all_docs" + query;
-      } else {
-        return app.host + "/" + this.database.safeID() + "/_all_docs" + query;
-      }
-    },
-
-    simple: function () {
-      var docs = this.map(function (item) {
-        return {
-          _id: item.id,
-          _rev: item.get('_rev'),
-        };
-      });
-
-      return new Documents.AllDocs(docs, {
-        database: this.database,
-        params: this.params
-      });
-    },
-
-    urlNextPage: function (num, lastId) {
-      if (!lastId) {
-        var doc = this.last();
-
-        if (doc) {
-          lastId = doc.id;
-        } else {
-          lastId = '';
-        }
-      }
-
-      this.params.startkey_docid = '"' + lastId + '"';
-      this.params.startkey = '"' + lastId + '"';
-      // when paginating forward, fetch 21 and don't show
-      // the first item as it was the last item in the previous list
-      this.params.limit = num + 1;
-      return this.url('app');
-    },
-
-    urlPreviousPage: function (num, params) {
-      if (params) { 
-        this.params = params;
-      } else {
-        this.params = {reduce: false};
-      }
-
-      this.params.limit = num;
-      return this.url('app'); 
-    },
-
-    totalRows: function() {
-      return this.viewMeta.total_rows || "unknown";
-    },
-
-    decrementTotalRows: function () {
-      if (this.viewMeta.total_rows) {
-        this.viewMeta.total_rows = this.viewMeta.total_rows -1;
-        this.trigger('totalRows:decrement');
-      }
-    },
-
-    updateSeq: function() {
-      return this.viewMeta.update_seq || false;
-    },
-
-    recordStart: function () {
-      if (this.viewMeta.offset === 0) {
-        return 1;
-      }
-
-      if (this.skipFirstItem) {
-        return this.viewMeta.offset + 2;
-      }
-
-      return this.viewMeta.offset + 1;
-    },
-
-    parse: function(resp) {
-      var rows = resp.rows;
-
-      this.viewMeta = {
-        total_rows: resp.total_rows,
-        offset: resp.offset,
-        update_seq: resp.update_seq
-      };
-
-      //Paginating, don't show first item as it was the last
-      //item in the previous page
-      if (this.skipFirstItem) {
-        rows = rows.splice(1);
-      }
-      return _.map(rows, function(row) {
-        return {
-          _id: row.id,
-          _rev: row.value.rev,
-          value: row.value,
-          key: row.key,
-          doc: row.doc || undefined
-        };
-      });
-    }
-  });
-
-  Documents.IndexCollection = Backbone.Collection.extend({
-    model: Documents.ViewRow,
-    documentation: function(){
-      return "docs";
-    },
-    initialize: function(_models, options) {
-      this.database = options.database;
-      this.params = _.extend({limit: 20, reduce: false}, options.params);
-      this.idxType = "_view";
-      this.view = options.view;
-      this.design = options.design.replace('_design/','');
-      this.skipFirstItem = false;
-    },
-
-    url: function(context) {
-      var query = "";
-      if (this.params) {
-        query = "?" + $.param(this.params);
-      }
-      
-      var startOfUrl = app.host;
-      if (context === 'app') {
-        startOfUrl = 'database';
-      } else if (context === "apiurl"){
-        startOfUrl = window.location.origin;
-      }
-      var design = app.mixins.safeURLName(this.design),
-          view = app.mixins.safeURLName(this.view);
-
-      var url = [startOfUrl, this.database.safeID(), "_design", design, this.idxType, view];
-      return url.join("/") + query;
-    },
-
-    urlNextPage: function (num, lastId) {
-      if (!lastId) {
-        lastDoc = this.last();
-      }
-
-      var id = lastDoc.get("id");
-      if (id) {
-        this.params.startkey_docid = id;
-      }
-
-      this.params.startkey =  JSON.stringify(lastDoc.get('key'));
-      this.params.limit = num + 1;
-      return this.url('app');
-    },
-
-     urlPreviousPage: function (num, params) {
-      if (params) { 
-        this.params = params;
-      } else {
-        this.params = {reduce: false};
-      }
-
-      this.params.limit = num;
-      return this.url('app');
-    },
-
-    recordStart: function () {
-      if (this.viewMeta.offset === 0) {
-        return 1;
-      }
-
-      if (this.skipFirstItem) {
-        return this.viewMeta.offset + 2;
-      }
-
-      return this.viewMeta.offset + 1;
-    },
-
-    totalRows: function() {
-      if (this.params.reduce) { return "unknown_reduce";}
-
-      return this.viewMeta.total_rows || "unknown";
-    },
-
-    updateSeq: function() {
-      return this.viewMeta.update_seq || false;
-    },
-
-    simple: function () {
-      var docs = this.map(function (item) {
-        return {
-          _id: item.id,
-          key: item.get('key'),
-          value: item.get('value')
-        };
-      });
-
-      return new Documents.IndexCollection(docs, {
-        database: this.database,
-        params: this.params,
-        view: this.view,
-        design: this.design
-      });
-    },
-
-    parse: function(resp) {
-      var rows = resp.rows;
-      this.endTime = new Date().getTime();
-      this.requestDuration = (this.endTime - this.startTime);
-
-      if (this.skipFirstItem) {
-        rows = rows.splice(1);
-      }
-
-      this.viewMeta = {
-        total_rows: resp.total_rows,
-        offset: resp.offset,
-        update_seq: resp.update_seq
-      };
-      return _.map(rows, function(row) {
-        return {
-          value: row.value,
-          key: row.key,
-          doc: row.doc,
-          id: row.id
-        };
-      });
-    },
-
-    buildAllDocs: function(){
-      this.fetch();
-    },
-
-    // We implement our own fetch to store the starttime so we that
-    // we can get the request duration
-    fetch: function () {
-      this.startTime = new Date().getTime();
-      return Backbone.Collection.prototype.fetch.call(this);
-    },
-
-    allDocs: function(){
-      return this.models;
-    },
-
-    // This is taken from futon.browse.js $.timeString
-    requestDurationInString: function () {
-      var ms, sec, min, h, timeString, milliseconds = this.requestDuration;
-
-      sec = Math.floor(milliseconds / 1000.0);
-      min = Math.floor(sec / 60.0);
-      sec = (sec % 60.0).toString();
-      if (sec.length < 2) {
-         sec = "0" + sec;
-      }
-
-      h = (Math.floor(min / 60.0)).toString();
-      if (h.length < 2) {
-        h = "0" + h;
-      }
-
-      min = (min % 60.0).toString();
-      if (min.length < 2) {
-        min = "0" + min;
-      }
-
-      timeString = h + ":" + min + ":" + sec;
-
-      ms = (milliseconds % 1000.0).toString();
-      while (ms.length < 3) {
-        ms = "0" + ms;
-      }
-      timeString += "." + ms;
-
-      return timeString;
-    }
-  });
-
-  
-  Documents.PouchIndexCollection = Backbone.Collection.extend({
-    model: Documents.ViewRow,
-    documentation: function(){
-      return "docs";
-    },
-    initialize: function(_models, options) {
-      this.database = options.database;
-      this.rows = options.rows;
-      this.view = options.view;
-      this.design = options.design.replace('_design/','');
-      this.params = _.extend({limit: 20, reduce: false}, options.params);
-      this.idxType = "_view";
-    },
-
-    url: function () {
-      return '';
-    },
-
-    simple: function () {
-      var docs = this.map(function (item) {
-        return {
-          _id: item.id,
-          key: item.get('key'),
-          value: item.get('value')
-        };
-      });
-
-      return new Documents.PouchIndexCollection(docs, {
-        database: this.database,
-        params: this.params,
-        view: this.view,
-        design: this.design,
-        rows: this.rows
-      });
-
-    },
-
-    fetch: function() {
-      var deferred = FauxtonAPI.Deferred();
-      this.reset(this.rows, {silent: true});
-
-      this.viewMeta = {
-        total_rows: this.rows.length,
-        offset: 0,
-        update_seq: false
-      };
-
-      deferred.resolve();
-      return deferred;
-    },
-
-    recordStart: function () {
-      return 1;
-    },
-
-    totalRows: function() {
-      return this.viewMeta.total_rows || "unknown";
-    },
-
-    updateSeq: function() {
-      return this.viewMeta.update_seq || false;
-    },
-
-    buildAllDocs: function(){
-      this.fetch();
-    },
-
-    allDocs: function(){
-      return this.models;
-    }
-  });
-
-
-
-  return Documents;
-});


[31/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Fauxton: block user from deleting _id and _rev from doc


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/c9ad37bc
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/c9ad37bc
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/c9ad37bc

Branch: refs/heads/import-master
Commit: c9ad37bc0f5bc7aa3cf16b04ddffb6baf7c5ba29
Parents: 77ce5d0
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Jan 21 21:57:23 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Jan 28 09:02:05 2014 +0200

----------------------------------------------------------------------
 app/addons/documents/views.js    | 33 +++++++++++++++++++++++++++++++++
 app/addons/fauxton/components.js |  4 ++++
 2 files changed, 37 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c9ad37bc/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index bd89527..e2f5578 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -961,6 +961,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
 
       this.editor = new Components.Editor({
         editorId: "editor-container",
+        forceMissingId: true,
         commands: [{
           name: 'save',
           bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
@@ -972,6 +973,38 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
       });
       this.editor.render();
       this.model.on("sync", this.updateValues, this);
+
+      var editor = this.editor,
+          model = this.model;
+
+      editor.editor.on("change", function (event) {
+        //if (event.data.action !== 'removeText') { return; }
+        //if (!event.data.text.match(/_id/) && !event.data.text.match(/_rev/)) { return; }
+
+        var changedDoc;
+        try {
+          changedDoc = JSON.parse(editor.getValue());
+        } catch(exception) {
+          //not complete doc. Cannot work with it
+          return;
+        }
+        
+        var keyChecked = ["_id"];
+        if (model.get("_rev")) { keyChecked.push("_rev");}
+
+        //check the changedDoc has all the required standard keys
+        if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; }
+
+        editor.setReadOnly(true);
+        setTimeout(function () { editor.setReadOnly(false);}, 400);
+        // use extend so that _id stays at the top of the object with displaying the doc
+        changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc);
+        editor.setValue(JSON.stringify(changedDoc, null, "  "));
+        FauxtonAPI.addNotification({
+          type: "error",
+          msg: "Cannot remove a documents Id or Revision."
+        });
+      });
     },
 
     cleanup: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c9ad37bc/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index 8b8aa5b..edde428 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -317,6 +317,10 @@ function(app, FauxtonAPI, ace) {
       this.edited = false;
     },
 
+    setReadOnly: function (value) {
+      return this.editor.setReadOnly(value);
+    },
+
     setValue: function (data, lineNumber) {
       lineNumber = lineNumber ? lineNumber : -1;
       this.editor.setValue(data, lineNumber);


[09/52] [abbrv] fauxton commit: updated refs/heads/import-master to d11b90b

Posted by da...@apache.org.
Regex fix for creating (from duplicate)  Design docs and deleting weirdly encoded docs what begin with _design


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/e22f2568
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/e22f2568
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/e22f2568

Branch: refs/heads/import-master
Commit: e22f2568b32fd2389390220319277607c5b737fe
Parents: c601fdc
Author: suelockwood <de...@apache.org>
Authored: Mon Jan 13 12:05:24 2014 -0500
Committer: suelockwood <de...@apache.org>
Committed: Mon Jan 13 12:05:24 2014 -0500

----------------------------------------------------------------------
 app/addons/documents/resources.js | 2 +-
 app/addons/documents/views.js     | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e22f2568/app/addons/documents/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js
index 5e10ded..0fd99f1 100644
--- a/app/addons/documents/resources.js
+++ b/app/addons/documents/resources.js
@@ -56,7 +56,7 @@ function(app, FauxtonAPI) {
     },
 
     docType: function() {
-      return this.id.match(/^_design/) ? "design doc" : "doc";
+      return this.id && this.id.match(/^_design\//) ? "design doc" : "doc";
     },
 
     isEditable: function() {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/e22f2568/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 94332a2..2502b58 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -242,7 +242,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
     duplicate: function (event) {
       event.preventDefault();
       var newId = this.$('#dup-id').val(),
-          encodedID = app.utils.safeURLName(newId);
+          isDDoc = newId.match(/^_design\//),
+          removeDDocID = newId.replace(/^_design\//,""),
+          encodedID = isDDoc? "_design/"+ app.utils.safeURLName(removeDDocID):app.utils.safeURLName(newId);
 
       this.hideModal();
       FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);


[33/52] [abbrv] Fauxton: Split up api.js

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/core/utils.js
----------------------------------------------------------------------
diff --git a/app/core/utils.js b/app/core/utils.js
new file mode 100644
index 0000000..44945e8
--- /dev/null
+++ b/app/core/utils.js
@@ -0,0 +1,94 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+
+// This file creates a set of helper functions that will be loaded for all html
+// templates. These functions should be self contained and not rely on any 
+// external dependencies as they are loaded prior to the application. We may
+// want to change this later, but for now this should be thought of as a
+// "purely functional" helper system.
+
+
+define([
+  "jquery",
+  "lodash"
+],
+
+function($, _ ) {
+
+  var onWindowResize = {};
+
+  var utils = {
+    // Thanks to: http://stackoverflow.com/a/2880929
+    getParams: function(queryString) {
+      if (queryString) {
+        // I think this could be combined into one if
+        if (queryString.substring(0,1) === "?") {
+          queryString = queryString.substring(1);
+        } else if (queryString.indexOf('?') > -1) {
+          queryString = queryString.split('?')[1];
+        }
+      }
+      var hash = window.location.hash.split('?')[1];
+      queryString = queryString || hash || window.location.search.substring(1);
+      var match,
+      urlParams = {},
+      pl     = /\+/g,  // Regex for replacing addition symbol with a space
+      search = /([^&=]+)=?([^&]*)/g,
+      decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
+      query  = queryString;
+
+      if (queryString) {
+        while ((match = search.exec(query))) {
+          urlParams[decode(match[1])] = decode(match[2]);
+        }
+      }
+
+      return urlParams;
+    },
+
+    addWindowResize: function(fun, key){
+      onWindowResize[key]=fun;
+      // You shouldn't need to call it here. Just define it at startup and each time it will loop 
+      // through all the functions in the hash.
+      //app.initWindowResize();
+    },
+
+    removeWindowResize: function(key){
+      delete onWindowResize[key];
+      utils.initWindowResize();
+    },
+
+    initWindowResize: function(){
+      //when calling this it should be overriding what was called previously
+      window.onresize = function(e) {
+        // could do this instead of the above for loop
+        _.each(onWindowResize, function (fn) {
+          fn();
+        });
+      };
+    },
+
+    removeSpecialCharacters: function(name){
+      return name.replace(/[^\w\s]/gi,"");
+    },
+
+    safeURLName: function(name){
+      var testName = name || "";
+      var checkforBad = testName.match(/[\$\-/_,+-]/g);
+      return (checkforBad !== null)?encodeURIComponent(name):name;
+    }
+  };
+
+  return utils;
+});
+

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/main.js
----------------------------------------------------------------------
diff --git a/app/main.js b/app/main.js
index 6fe9991..9df15c5 100644
--- a/app/main.js
+++ b/app/main.js
@@ -13,19 +13,18 @@
 require([
         // Application.
         "app",
-
-        // Main Router.
-        "router"
+        "api",
+        "load_addons"
 ],
 
-function(app, Router) {
+function(app, FauxtonAPI, LoadAddons) {
 
-  // Define your master router on the application namespace and trigger all
-  // navigation from this instance.
-  app.router = new Router();
+  app.addons = LoadAddons.addons;
+  FauxtonAPI.router = app.router = new FauxtonAPI.Router(app.addons);
   // Trigger the initial route and enable HTML5 History API support, set the
   // root folder to '/' by default.  Change in app.js.
   Backbone.history.start({ pushState: false, root: app.root });
+
   // All navigation that is relative should be passed through the navigate
   // method, to be processed by the router. If the link has a `data-bypass`
   // attribute, bypass the delegation completely.

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/resizeColumns.js
----------------------------------------------------------------------
diff --git a/app/resizeColumns.js b/app/resizeColumns.js
deleted file mode 100644
index bb50767..0000000
--- a/app/resizeColumns.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-// This file creates a set of helper functions that will be loaded for all html
-// templates. These functions should be self contained and not rely on any 
-// external dependencies as they are loaded prior to the application. We may
-// want to change this later, but for now this should be thought of as a
-// "purely functional" helper system.
-
-define([
-  "utils"
-],
-
-function(utils) {
-
-  var Resize = function(options){
-    this.options = options;
-    this.options.selectorElements = options.selectorElements || ".window-resizeable";
-  };
-
-  Resize.prototype = {
-    getPrimaryNavWidth: function(){
-      var primaryNavWidth  = $('body').hasClass('closeMenu')? 64:224;
-      return primaryNavWidth;
-    },
-    getPanelWidth: function(){
-      var sidebarWidth = $('#sidebar-content').length > 0 ? $('#sidebar-content').width(): 0;
-      return (this.getPrimaryNavWidth() + sidebarWidth); 
-    },
-    initialize: function(){
-     // $(window).off('resize');
-      var that = this;
-      //add throttler :) 
-      this.lazyLayout = _.debounce(that.onResizeHandler, 300).bind(this);
-      utils.addWindowResize(this.lazyLayout,"animation");
-      utils.initWindowResize();
-      this.onResizeHandler();
-    },
-    updateOptions:function(options){
-      this.options = {};
-      this.options = options;
-      this.options.selectorElements = options.selectorElements || ".window-resizeable";
-    },
-    turnOff:function(){
-      utils.removeWindowResize("animation");
-    },
-    cleanupCallback: function(){
-      this.callback = null;
-    },
-    onResizeHandler: function (){
-      //if there is an override, do that instead
-      if (this.options.onResizeHandler){
-        this.options.onResizeHandler();
-      } else {
-        var combinedWidth = window.innerWidth - this.getPanelWidth(),
-        smallWidthConstraint = ($('#sidebar-content').length > 0)? 470:800,
-        panelWidth; 
-
-        if( combinedWidth > smallWidthConstraint  && combinedWidth < 1400){
-          panelWidth = window.innerWidth - this.getPanelWidth();
-        } else if (combinedWidth < smallWidthConstraint){
-          panelWidth = smallWidthConstraint;
-        } else if(combinedWidth > 1400){
-          panelWidth = 1400;
-        }
-
-        $(this.options.selectorElements).innerWidth(panelWidth);
-      }
-      //if there is a callback, run that
-      if(this.options.callback) {
-        this.options.callback();
-      }
-    } 
-  };
-
-  return Resize;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/router.js
----------------------------------------------------------------------
diff --git a/app/router.js b/app/router.js
deleted file mode 100644
index 89c60cf..0000000
--- a/app/router.js
+++ /dev/null
@@ -1,142 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       // Load require for use in nested requiring
-       // as per the note in: http://requirejs.org/docs/api.html#multiversion
-       "require",
-
-       // Application.
-       "app",
-
-       // Initialize application
-       "initialize",
-
-       // Load Fauxton API
-       "api",
-
-       // Modules
-       "addons/fauxton/base",
-       // Layout
-       "addons/fauxton/layout",
-
-       "load_addons"
-],
-
-function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, LoadAddons) {
-
-  var beforeUnloads = {};
-
-  var Router = app.router = Backbone.Router.extend({
-    routes: {},
-
-    beforeUnload: function (name, fn) {
-      beforeUnloads[name] = fn;
-    },
-
-    removeBeforeUnload: function (name) {
-      delete beforeUnloads[name];
-    },
-
-    navigate: function (fragment, trigger) {
-      var continueNav  = true,
-          msg = _.find(_.map(beforeUnloads, function (fn) { return fn(); }), function (beforeReturn) {
-            if (beforeReturn) { return true; }
-          });
-
-      if (msg) {
-        continueNav = window.confirm(msg);
-      }
-
-      if (continueNav) {
-        Backbone.Router.prototype.navigate(fragment, trigger);
-      }
-    },
-
-    addModuleRouteObject: function(RouteObject) {
-      var that = this;
-      var masterLayout = this.masterLayout,
-      routeUrls = RouteObject.prototype.getRouteUrls();
-
-      _.each(routeUrls, function(route) {
-        this.route(route, route.toString(), function() {
-          var args = Array.prototype.slice.call(arguments),
-          roles = RouteObject.prototype.getRouteRoles(route),
-          authPromise = app.auth.checkAccess(roles);
-
-          authPromise.then(function () {
-            if (!that.activeRouteObject || !that.activeRouteObject.hasRoute(route)) {
-              if (that.activeRouteObject) {
-                that.activeRouteObject.cleanup();
-              }
-              that.activeRouteObject = new RouteObject(route, masterLayout, args);
-            }
-
-            var routeObject = that.activeRouteObject;
-            routeObject.routeCallback(route, args);
-            routeObject.renderWith(route, masterLayout, args);
-          }, function () {
-            FauxtonAPI.auth.authDeniedCb();
-          });
-
-        }); 
-      }, this);
-    },
-
-    setModuleRoutes: function() {
-      _.each(LoadAddons.addons, function(module) {
-        if (module){
-          module.initialize();
-          // This is pure routes the addon provides
-          if (module.RouteObjects) {
-            _.each(module.RouteObjects, this.addModuleRouteObject, this);
-          }
-        }
-      }, this);
-    },
-
-    initialize: function() {
-      //TODO: It would be nice to handle this with a router
-      this.navBar = app.navBar = new Fauxton.NavBar();
-      this.apiBar = app.apiBar = new Fauxton.ApiBar();
-      this.auth = app.auth = FauxtonAPI.auth;
-      app.session = FauxtonAPI.session;
-
-      app.masterLayout = this.masterLayout = new Layout(this.navBar, this.apiBar);
-      app.footer = new Fauxton.Footer({el: "#footer-content"});
-
-      // NOTE: This must be below creation of the layout
-      // FauxtonAPI header links and others depend on existence of the layout
-      //this.setAddonHooks();
-      this.setModuleRoutes();
-
-      $("#app-container").html(this.masterLayout.el);
-      this.masterLayout.render();
-
-      // TODO: move this to a proper Fauxton.View
-      $.when.apply(null, app.footer.establish()).done(function() {
-        app.footer.render();
-      });
-    },
-
-    triggerRouteEvent: function(event, args) {
-      if (this.activeRouteObject) {
-        var eventArgs = [event].concat(args);
-        this.activeRouteObject.trigger.apply(this.activeRouteObject, eventArgs );
-        this.activeRouteObject.renderWith(eventArgs, this.masterLayout, args);
-      }
-    }
-  });
-
-  return Router;
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/app/utils.js
----------------------------------------------------------------------
diff --git a/app/utils.js b/app/utils.js
deleted file mode 100644
index ded7dac..0000000
--- a/app/utils.js
+++ /dev/null
@@ -1,66 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-// This file creates a set of helper functions that will be loaded for all html
-// templates. These functions should be self contained and not rely on any 
-// external dependencies as they are loaded prior to the application. We may
-// want to change this later, but for now this should be thought of as a
-// "purely functional" helper system.
-
-
-define([
-  "jquery",
-  "lodash"
-],
-
-function($, _ ) {
-
-  var utils = {};
-
-  var onWindowResize = {};
-   
-  utils.addWindowResize = function(fun, key){
-    onWindowResize[key]=fun;
-    // You shouldn't need to call it here. Just define it at startup and each time it will loop 
-    // through all the functions in the hash.
-    //app.initWindowResize();
-  };
-   
-  utils.removeWindowResize = function(key){
-    delete onWindowResize[key];
-    utils.initWindowResize();
-  };
-   
-  utils.initWindowResize = function(){
-  //when calling this it should be overriding what was called previously
-    window.onresize = function(e) {
-       // could do this instead of the above for loop
-      _.each(onWindowResize, function (fn) {
-        fn();
-      });
-    };
-  };
-
-  utils.removeSpecialCharacters = function(name){
-    return name.replace(/[^\w\s]/gi,"");
-  };
-
-  utils.safeURLName = function(name){
-    var testName = name || "";
-    var checkforBad = testName.match(/[\$\-/_,+-]/g);
-    return (checkforBad !== null)?encodeURIComponent(name):name;
-  };
-
-  return utils;
-});
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/settings.json.default
----------------------------------------------------------------------
diff --git a/settings.json.default b/settings.json.default
index cb09eb2..e817b79 100644
--- a/settings.json.default
+++ b/settings.json.default
@@ -1,5 +1,6 @@
 {
   "deps": [
+  { "name": "fauxton" },
   { "name": "databases" },
   { "name": "documents" },
   { "name": "pouchdb" },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/tasks/couchserver.js
----------------------------------------------------------------------
diff --git a/tasks/couchserver.js b/tasks/couchserver.js
index 5ccbfe1..21c2fcb 100644
--- a/tasks/couchserver.js
+++ b/tasks/couchserver.js
@@ -61,7 +61,7 @@ module.exports = function (grunt) {
         // server js from app directory
         filePath = path.join(app_dir, url.replace('/_utils/fauxton/',''));
       } else if (!!url.match(/testrunner/)) {
-        var testSetup = grunt.util.spawn({cmd: 'grunt', grunt: true, args: ['mochaSetup']}, function (error, result, code) {/* log.writeln(String(result));*/ });
+        var testSetup = grunt.util.spawn({cmd: 'grunt', grunt: true, args: ['test_inline']}, function (error, result, code) {/* log.writeln(String(result));*/ });
         testSetup.stdout.pipe(process.stdout);
         testSetup.stderr.pipe(process.stderr);
         filePath = path.join('./test/runner.html');

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/core/layoutSpec.js
----------------------------------------------------------------------
diff --git a/test/core/layoutSpec.js b/test/core/layoutSpec.js
deleted file mode 100644
index 4167100..0000000
--- a/test/core/layoutSpec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-define([
-       'addons/fauxton/layout',
-      'testUtils'
-], function (Layout, testUtils) {
-  var assert = testUtils.assert;
-
-  describe("Faxuton Layout", function () {
-    var layout;
-
-    beforeEach(function () {
-      var navBar = new Backbone.View();
-      var apiBar = new Backbone.View();
-      layout = new Layout(navBar, apiBar);
-    });
-
-    describe('#setTemplate', function () {
-
-      it("Should set template without prefix", function () {
-        layout.setTemplate('myTemplate');
-
-        assert.equal(layout.layout.template, 'templates/layouts/myTemplate');
-
-      });
-
-      it("Should set template with prefix", function () {
-        layout.setTemplate({name: 'myTemplate', prefix: 'myPrefix/'});
-
-        assert.equal(layout.layout.template, 'myPrefix/myTemplate');
-      });
-
-      it("Should remove old views", function () {
-        var view = {
-          remove: function () {}
-        };
-
-        layout.layoutViews = {
-          'selector': view
-        };
-
-        var mockRemove = sinon.spy(view, 'remove');
-        layout.setTemplate('myTemplate');
-        assert.ok(mockRemove.calledOnce);
-
-      });
-
-      it("Should render", function () {
-        var mockRender = sinon.spy(layout, 'render');
-
-        layout.setTemplate('myTemplate');
-
-        assert.ok(mockRender.calledOnce);
-
-      });
-
-    });
-
-    describe('#renderView', function () {
-
-      it('Should render existing view', function () {
-        var view = new Backbone.View();
-        var mockRender = sinon.spy(view, 'render');
-        layout.layoutViews = {
-          '#selector': view
-        };
-
-        var out = layout.renderView('#selector');
-
-        assert.ok(mockRender.calledOnce);
-      });
-
-      it('Should return false for non-existing view', function () {
-        var view = new Backbone.View();
-        layout.layoutViews = {
-          'selector': view
-        };
-
-        var out = layout.renderView('wrongSelector');
-        assert.notOk(out, 'No view found');
-      });
-    });
-
-  });
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/core/navbarSpec.js
----------------------------------------------------------------------
diff --git a/test/core/navbarSpec.js b/test/core/navbarSpec.js
deleted file mode 100644
index 3eca6f6..0000000
--- a/test/core/navbarSpec.js
+++ /dev/null
@@ -1,107 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-define([
-       'addons/fauxton/base',
-      'testUtils'
-], function (Fauxton, testUtils) {
-  var assert = testUtils.assert,
-      NavBar = Fauxton.NavBar;
-
-  describe('NavBar', function () {
-
-    describe('adding links', function () {
-      var navBar;
-
-      beforeEach(function () {
-        navBar = new NavBar();
-        navBar.navLinks = [];
-        navBar.bottomNavLinks = [];
-        navBar.footerNavLinks = [];
-      });
-
-      it('Should add link to navlinks', function () {
-        navBar.addLink({href: '#/test', title: 'Test Title'});
-
-        assert.equal(navBar.navLinks.length, 1);
-        assert.equal(navBar.footerNavLinks.length, 0);
-        assert.equal(navBar.bottomNavLinks.length, 0);
-      });
-
-      it('Should add link to bottom links', function () {
-        navBar.addLink({href: '#/test', bottomNav: true, title: 'Test Title'});
-
-        assert.equal(navBar.bottomNavLinks.length, 1);
-        assert.equal(navBar.navLinks.length, 0);
-        assert.equal(navBar.footerNavLinks.length, 0);
-      });
-
-      it('Should add link to footer links', function () {
-        navBar.addLink({href: '#/test', footerNav: true, title: 'Test Title'});
-
-        assert.equal(navBar.footerNavLinks.length, 1);
-        assert.equal(navBar.bottomNavLinks.length, 0);
-        assert.equal(navBar.navLinks.length, 0);
-      });
-    });
-
-    describe('removing links', function () {
-      var navBar;
-
-      beforeEach(function () {
-        navBar = new NavBar();
-        navBar.navLinks = [];
-        navBar.bottomNavLinks = [];
-        navBar.footerNavLinks = [];
-        navBar.addLink({
-          href: '#/test', 
-          footerNav: true, 
-          title: 'Test Title Footer'
-        });
-
-        navBar.addLink({
-          href: '#/test', 
-          bottomNav: true, 
-          title: 'Test Title Bottom'
-        });
-
-        navBar.addLink({
-          href: '#/test', 
-          title: 'Test Title'
-        });
-      });
-
-      it("should remove links from list", function () {
-        navBar.removeLink({
-          title: 'Test Title Footer',
-          footerNav: true
-        });
-
-        assert.equal(navBar.footerNavLinks.length, 0);
-        assert.equal(navBar.bottomNavLinks.length, 1);
-        assert.equal(navBar.navLinks.length, 1);
-      });
-
-      it("Should call render after removing links", function () {
-        var renderSpy = sinon.stub(navBar,'render');
-
-        navBar.removeLink({
-          title: 'Test Title Footer',
-          footerNav: true
-        });
-
-        assert.ok(renderSpy.calledOnce);
-      });
-
-    });
-  });
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/core/paginateSpec.js
----------------------------------------------------------------------
diff --git a/test/core/paginateSpec.js b/test/core/paginateSpec.js
deleted file mode 100644
index d05b322..0000000
--- a/test/core/paginateSpec.js
+++ /dev/null
@@ -1,109 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-define([
-       'api',
-       'addons/fauxton/components',
-       'addons/documents/resources',
-       'testUtils',
-       'app'
-], function (FauxtonAPI, Views, Models, testUtils, app) {
-  var assert = testUtils.assert,
-  ViewSandbox = testUtils.ViewSandbox;
-
-
-  describe('IndexPaginate', function () {
-    var viewSandbox, paginate, collection, navigateMock;
-    beforeEach(function () {
-      app.router = {
-        navigate: function () {}
-      };
-
-      collection = new Models.IndexCollection([{
-        id:'myId1',
-        doc: 'num1'
-      },
-      {
-        id:'myId2',
-        doc: 'num2'
-      }], {
-        database: {id: 'databaseId'},
-        design: '_design/myDoc'
-      });
-
-      paginate = new Views.IndexPagination({
-        collection: collection,
-        previousUrlfn: function () {},
-        nextUrlfn: function () {},
-        canShowPreviousfn: function () { return true; },
-        canShowNextfn: function () { return true;}
-      });
-      viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(paginate); 
-    });
-
-    afterEach(function () {
-      viewSandbox.remove();
-    });
-
-    describe('#next', function () {
-      beforeEach(function () {
-        //do this so it doesn't throw an error on other unwired up components
-        FauxtonAPI.triggerRouteEvent = function () {};
-        //FauxtonAPI.triggerRouteEvent.restore && FauxtonAPI.triggerRouteEvent.restore();
-        //FauxtonAPI.navigate.restore && FauxtonAPI.navigate.restore(); 
-      });
-
-      it('Should navigate', function () {
-        var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
-
-        paginate.$('a#next').click();
-
-        assert.ok(navigateMock.calledOnce);
-        FauxtonAPI.navigate.restore();
-      });
-
-      it('Should trigger routeEvent', function () {
-        var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
-
-        paginate.$('a#next').click();
-
-        assert.ok(navigateMock.calledOnce);
-        FauxtonAPI.triggerRouteEvent.restore();
-      });
-
-    });
-
-
-    describe('#previous', function () {
-
-      it('Should navigate', function () {
-        var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
-
-        paginate.$('a#previous').click();
-
-        assert.ok(navigateMock.calledOnce);
-        FauxtonAPI.navigate.restore();
-      });
-
-      it('Should trigger routeEvent', function () {
-        var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
-
-        paginate.$('a#previous').click();
-
-        assert.ok(navigateMock.calledOnce);
-        FauxtonAPI.triggerRouteEvent.restore();
-      });
-
-    });
-
-  });
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/core/routeObjectSpec.js
----------------------------------------------------------------------
diff --git a/test/core/routeObjectSpec.js b/test/core/routeObjectSpec.js
deleted file mode 100644
index 987d5b7..0000000
--- a/test/core/routeObjectSpec.js
+++ /dev/null
@@ -1,105 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-define([
-       'api',
-      'testUtils'
-], function (FauxtonAPI, testUtils) {
-  var assert = testUtils.assert,
-      RouteObject = FauxtonAPI.RouteObject;
-
-  describe('RouteObjects', function () {
-
-    describe('renderWith', function () {
-      var TestRouteObject, testRouteObject, mockLayout;
-
-      beforeEach(function () {
-        TestRouteObject = RouteObject.extend({
-          crumbs: ['mycrumbs']
-        });
-
-        testRouteObject = new TestRouteObject();
-        var apiBar = {};
-        apiBar.hide = sinon.spy();
-
-        // Need to find a better way of doing this
-        mockLayout = {
-          setTemplate: sinon.spy(),
-          clearBreadcrumbs: sinon.spy(),
-          setView: sinon.spy(),
-          renderView: sinon.spy(),
-          hooks: [],
-          setBreadcrumbs: sinon.spy(),
-          apiBar: apiBar
-        };
-
-      });
-
-      it('Should set template for first render ', function () {
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-
-        assert.ok(mockLayout.setTemplate.calledOnce, 'setTempalte was called');
-      });
-
-      it('Should not set template after first render', function () {
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-
-        assert.ok(mockLayout.setTemplate.calledOnce, 'SetTemplate not meant to be called');
-      });
-
-      it('Should clear breadcrumbs', function () {
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-        assert.ok(mockLayout.clearBreadcrumbs.calledOnce, 'Clear Breadcrumbs called');
-      });
-
-      it('Should set breadcrumbs when breadcrumbs exist', function () {
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-        assert.ok(mockLayout.setBreadcrumbs.calledOnce, 'Set Breadcrumbs was called');
-      });
-
-      it("Should call establish of routeObject", function () {
-        var establishSpy = sinon.spy(testRouteObject,"establish");
-
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-        assert.ok(establishSpy.calledOnce, 'Calls establish');
-      });
-
-      it("Should render views", function () {
-        var view = new FauxtonAPI.View(),
-            getViewsSpy = sinon.stub(testRouteObject,"getViews"),
-            viewSpy = sinon.stub(view, "establish");
-        
-        view.hasRendered = false;
-        getViewsSpy.returns({'#view': view});
-
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-        assert.ok(viewSpy.calledOnce, 'Should render view');
-      });
-
-      it("Should not re-render a view", function () {
-        var view = new FauxtonAPI.View(),
-            getViewsSpy = sinon.stub(testRouteObject,"getViews"),
-            viewSpy = sinon.stub(view, "establish");
-        
-        view.hasRendered = true;
-        getViewsSpy.returns({'#view': view});
-
-        testRouteObject.renderWith('the-route', mockLayout, 'args');
-        assert.notOk(viewSpy.calledOnce, 'Should render view');
-      });
-    });
-
-  });
-
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/mocha/testUtils.js
----------------------------------------------------------------------
diff --git a/test/mocha/testUtils.js b/test/mocha/testUtils.js
index f9643e8..2c418f9 100644
--- a/test/mocha/testUtils.js
+++ b/test/mocha/testUtils.js
@@ -11,11 +11,12 @@
 // the License.
 
 define([
+       "api",
        "chai",
        "sinon-chai",
        "underscore"
 ],
-function(chai, sinonChai) {
+function(FauxtonAPI,chai, sinonChai) {
   chai.use(sinonChai);
 
   var ViewSandbox = function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/61e34781/test/test.config.underscore
----------------------------------------------------------------------
diff --git a/test/test.config.underscore b/test/test.config.underscore
index dda16f2..5cebe78 100644
--- a/test/test.config.underscore
+++ b/test/test.config.underscore
@@ -5,6 +5,7 @@ require.config(
 );
 
 require([
+        "app",
         <% _.each(testFiles, function (test) {%>
            '../<%= test %>',
         <% }) %>