couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gar...@apache.org
Subject [47/50] git commit: updated refs/heads/route-events to c33e390
Date Thu, 09 May 2013 14:01:44 GMT
implementation of new route event api and get all modules working with it


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

Branch: refs/heads/route-events
Commit: d8b885629d943ddc6af99495a0c2cdaae3ccbc3a
Parents: 10a69fb
Author: Garren Smith <garren.smith@gmail.com>
Authored: Thu May 2 15:26:26 2013 +0200
Committer: Garren Smith <garren.smith@gmail.com>
Committed: Thu May 9 10:01:51 2013 +0200

----------------------------------------------------------------------
 src/fauxton/app/addons/config/routes.js            |   10 +-
 src/fauxton/app/addons/logs/resources.js           |    5 +
 src/fauxton/app/addons/logs/routes.js              |   12 +-
 src/fauxton/app/addons/stats/routes.js             |   10 +-
 src/fauxton/app/api.js                             |   72 ++--
 src/fauxton/app/initialize.js                      |    6 +-
 src/fauxton/app/main.js                            |    3 +-
 src/fauxton/app/modules/databases/routes.js        |   90 +---
 src/fauxton/app/modules/databases/views.js         |    5 +-
 src/fauxton/app/modules/documents/routes.js        |  434 ++++++---------
 src/fauxton/app/modules/documents/views.js         |   12 +
 src/fauxton/app/modules/fauxton/base.js            |    8 +-
 src/fauxton/app/router.js                          |   52 +--
 .../templates/documents/doc_field_editor_tabs.html |    4 +-
 .../app/templates/documents/index_menu_item.html   |    4 +-
 src/fauxton/app/templates/documents/sidebar.html   |    2 +-
 src/fauxton/app/templates/fauxton/pagination.html  |   10 +-
 17 files changed, 304 insertions(+), 435 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/addons/config/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/addons/config/routes.js b/src/fauxton/app/addons/config/routes.js
index 4db4da7..495e3a9 100644
--- a/src/fauxton/app/addons/config/routes.js
+++ b/src/fauxton/app/addons/config/routes.js
@@ -24,6 +24,10 @@ function(app, FauxtonAPI, Config) {
   var ConfigRouteObject = FauxtonAPI.RouteObject.extend({
     layout: "one_pane",
 
+    initialize: function () {
+      this.configs = new Config.Collection();
+    },
+
     crumbs: [
       {"name": "Config","link": "_config"}
     ],
@@ -34,9 +38,9 @@ function(app, FauxtonAPI, Config) {
 
     routes: ["_config"],
 
-    views: function () {
-      this.configs = new Config.Collection();
+    defaultRoute: "config",
 
+    config: function () {
       this.setView("#dashboard-content", new Config.View({collection: this.configs}));
     },
 
@@ -46,6 +50,6 @@ function(app, FauxtonAPI, Config) {
   });
 
 
-  Config.RouteObjects = [new ConfigRouteObject()];
+  Config.RouteObjects = [ConfigRouteObject];
   return Config;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/addons/logs/resources.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/addons/logs/resources.js b/src/fauxton/app/addons/logs/resources.js
index d1e6d20..91a9bcb 100644
--- a/src/fauxton/app/addons/logs/resources.js
+++ b/src/fauxton/app/addons/logs/resources.js
@@ -98,11 +98,16 @@ function (app, FauxtonAPI, Backbone) {
 
       this.filters = [];
       this.filteredCollection = new Log.Collection(this.collection.toJSON());
+
       this.collection.on("add", function () {
         this.createFilteredCollection();
       }, this);
     },
 
+    establish: function () {
+      return [this.collection.fetch()];
+    },
+
     serialize: function () {
       return { logs: this.filteredCollection};
     },

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/addons/logs/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/addons/logs/routes.js b/src/fauxton/app/addons/logs/routes.js
index a6af39c..9bd8f65 100644
--- a/src/fauxton/app/addons/logs/routes.js
+++ b/src/fauxton/app/addons/logs/routes.js
@@ -30,25 +30,27 @@ function(app, FauxtonAPI, Log) {
 
     routes: ["_log"],
 
+    defaultRoute: "showLog",
+
     apiUrl: function() {
       return this.logs.url();
     },
 
-    views: function () {
+    initialize: function () {
       this.logs = new Log.Collection();
-      this.setView("#dashboard-content", new Log.Views.View({collection: this.logs}));
       this.setView("#sidebar-content", new Log.Views.FilterView({}));
     },
 
-    route: function() {
+    showLog: function (event) {
+      this.setView("#dashboard-content", new Log.Views.View({collection: this.logs}));
     },
 
-    establish: function() {
+    e1stablish: function() {
       return [this.logs.fetch()];
     }
   });
 
-  Log.RouteObjects = [new LogRouteObject()];
+  Log.RouteObjects = [LogRouteObject];
 
   return Log;
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/addons/stats/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/addons/stats/routes.js b/src/fauxton/app/addons/stats/routes.js
index a0fc3bf..7ad2a1f 100644
--- a/src/fauxton/app/addons/stats/routes.js
+++ b/src/fauxton/app/addons/stats/routes.js
@@ -22,14 +22,18 @@ function(app, FauxtonAPI, Stats) {
     layout: "with_sidebar",
 
     routes: ["stats", "_stats"],
-    views: function () {
-      this.stats = new Stats.Collection();
+    defaultRoute: "showStats",
 
+    initialize: function () {
+      this.stats = new Stats.Collection();
 
       this.setView("#sidebar-content", new Views.StatSelect({
         collection: this.stats
       }));
 
+    },
+
+    showStats: function (event) {
       this.setView("#dashboard-content", new Views.Statistics({
         collection: this.stats
       }));
@@ -42,7 +46,7 @@ function(app, FauxtonAPI, Stats) {
     apiUrl: "_stats"
   });
 
-  Stats.RouteObjects = [new StatsRouteObject()];
+  Stats.RouteObjects = [StatsRouteObject];
 
   return Stats;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/api.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/api.js b/src/fauxton/app/api.js
index de0844c..6591daf 100644
--- a/src/fauxton/app/api.js
+++ b/src/fauxton/app/api.js
@@ -43,6 +43,14 @@ function(app, Fauxton) {
     // This should return an array of promises, an empty array, or null
     establish: function() {
       return null;
+    },
+
+    hasRendered: function () {
+      return !!this.__manager__.hasRendered;
+    },
+
+    reRender: function () {
+      this.__manager__.hasRendered = false;
     }
   });
 
@@ -62,6 +70,10 @@ function(app, Fauxton) {
     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));
   };
@@ -96,6 +108,7 @@ function(app, Fauxton) {
     }
   });
 
+  // Not needed, could be removed.
   FauxtonAPI.routeCallChain = {
     callChain: {},
 
@@ -129,7 +142,7 @@ function(app, Fauxton) {
 
   _.extend(FauxtonAPI.RouteObject.prototype, Backbone.Events, {
     // Should these be default vals or empty funcs?
-    _views: {},
+    views: {},
     routes: {},
     events: {},
     data: {},
@@ -142,10 +155,6 @@ function(app, Fauxton) {
     route: function() {},
     initialize: function() {}
   }, {
-    // By default, rerender is a full rerender
-    rerender: function() {
-      this.renderWith.apply(this, arguments);
-    },
 
     // TODO:: combine this and the renderWith function
     // All the things should go through establish, as it will resolve
@@ -153,20 +162,17 @@ function(app, Fauxton) {
     // function can rebuild the deferred as needed
     render: function(route, masterLayout, args) {
       this.route.call(this, route, args);
-
-      if (this.renderedState === true) {
-        this.rerender.apply(this, arguments);
-      } else {
-        this.preloadViews();
-        this.renderWith.apply(this, arguments);
-      }
+      this.renderWith.apply(this, Array.prototype.slice.call(arguments));
     },
 
     renderWith: function(route, masterLayout, args) {
       var routeObject = this;
 
-      this.masterLayout = masterLayout;
-      masterLayout.setTemplate(this.layout);
+      // Only want to redo the template if its a full render
+      if (!this.renderedState) {
+        masterLayout.setTemplate(this.layout);
+      }
+
       masterLayout.clearBreadcrumbs();
       var crumbs = this.get('crumbs');
 
@@ -178,7 +184,10 @@ function(app, Fauxton) {
 
       $.when.apply(this, this.establish()).done(function(resp) {
         _.each(routeObject.getViews(), function(view, selector) {
+          if(view.hasRendered()) { console.log('view been rendered'); return; }
+
           masterLayout.setView(selector, view);
+          console.log('set and render ', selector, view); 
 
           $.when.apply(null, view.establish()).then(function(resp) {
             masterLayout.renderView(selector);
@@ -192,13 +201,11 @@ function(app, Fauxton) {
 
           var hooks = masterLayout.hooks[selector];
 
-          if(hooks){
-            _.each(hooks, function(hook){
-              if (_.any(hook.routes, function(route){return route == boundRoute;})){
-                hook.callback(view);
-              }
-            });
-          }
+          _.each(hooks, function(hook){
+            if (_.any(hook.routes, function(route){return route == boundRoute;})){
+              hook.callback(view);
+            }
+          });
         });
       });
 
@@ -208,12 +215,6 @@ function(app, Fauxton) {
       this.renderedState = true;
     },
 
-    preloadViews: function () {
-      _.each(this.get('views'), function (view, selector) {
-        this.setView(selector, view);
-      }, this);
-    },
-
     get: function(key) {
       return _.isFunction(this[key]) ? this[key]() : this[key];
     },
@@ -237,27 +238,18 @@ function(app, Fauxton) {
     },
 
     getView: function(selector) {
-      return this._views[selector];
+      return this.views[selector];
     },
 
     setView: function(selector, view) {
-      this._views[selector] = view;
+      this.views[selector] = view;
       return view;
     },
 
-    rerenderView: function(selector) {
-      var view = this._views[selector];
-      this.masterLayout.setView(selector, view);
-      this.masterLayout.renderView(selector);
-    },
-
     getViews: function() {
-      return this._views;
-    },
-
-    clearViews: function () {
-      this._views = {};
+      return this.views;
     }
+
   });
 
   app.fauxtonAPI = FauxtonAPI;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/initialize.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/initialize.js b/src/fauxton/app/initialize.js
index 5699678..e5dbc73 100644
--- a/src/fauxton/app/initialize.js
+++ b/src/fauxton/app/initialize.js
@@ -37,8 +37,12 @@ function(app, _, Bootstrap) {
     // Thanks to: http://stackoverflow.com/a/2880929
     getParams: function(queryString) {
       if (typeof queryString !== "undefined") {
-        if (queryString.substring(0,1) === "?")
+        // 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);

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/main.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/main.js b/src/fauxton/app/main.js
index 99ea803..203b295 100644
--- a/src/fauxton/app/main.js
+++ b/src/fauxton/app/main.js
@@ -26,9 +26,10 @@ function(app, Router) {
     var routeEvent = $(this).attr("route-event");
     if (routeEvent) {
       evt.preventDefault();
-      app.router.triggerRouteEvent("route:"+routeEvent, href);
       // TODO:: change to false when route events are functional
       Backbone.history.navigate(href.attr, true);
+      // Trigger  route events after update of history so that we can get params from url
+      app.router.triggerRouteEvent("route:"+routeEvent, href);
     } else {
       // Ensure the root is part of the anchor href, meaning it's relative.
       if (href.prop && href.prop.slice(0, root.length) === root) {

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/modules/databases/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/databases/routes.js b/src/fauxton/app/modules/databases/routes.js
index f332eac..f1be372 100644
--- a/src/fauxton/app/modules/databases/routes.js
+++ b/src/fauxton/app/modules/databases/routes.js
@@ -22,6 +22,7 @@ define([
 ],
 
 function(app, FauxtonAPI, Databases, Views) {
+
   var AllDbsRouteObject = FauxtonAPI.RouteObject.extend({
     layout: "with_sidebar",
 
@@ -29,35 +30,38 @@ function(app, FauxtonAPI, Databases, Views) {
       {"name": "Databases", "link": "/_all_dbs"}
     ],
 
+    events: {
+      "route:all_databases": "allDatabases"
+    },
+
+    defaultRoute: "allDatabases",
+
     routes: ["", "index.html", "_all_dbs(:params)"],
 
     apiUrl: function() {
       return this.databases.url();
     },
 
-    views: function() {
+    initialize: function() {
       this.databases = new Databases.List();
       this.deferred = FauxtonAPI.Deferred();
 
-      this.databasesView = this.setView("#dashboard-content", new Views.List({
+      this.sidebarView = this.setView("#sidebar-content", new Views.Sidebar({
           collection: this.databases
       }));
+    },
 
-      this.databasesView.setPage(this.dbPage);
+    allDatabases: function(event) {
+      event = event || {};
 
-      this.sidebarView = this.setView("#sidebar-content", new Views.Sidebar({
+      var params = app.getParams(event.attr),
+          dbPage = params.page;
+
+      this.databasesView = this.setView("#dashboard-content", new Views.List({
           collection: this.databases
       }));
-    },
-
-    route: function() {
-      var params = app.getParams();
-      this.dbPage = params.page;
-    },
 
-    rerender: function() {
-      this.databasesView.setPage(this.dbPage);
-      this.databasesView.render();
+      this.databasesView.setPage(dbPage);
     },
 
     establish: function() {
@@ -73,66 +77,10 @@ function(app, FauxtonAPI, Databases, Views) {
       });
 
       return [deferred];
-    },
-
-    mrEvent: function() {
-      console.log("Triggering a most excellent event!!!!");
-    },
-
-    events: {
-      "myrandom_event": "mrEvent"
     }
   });
-
-  var allDbsCallback = function() {
-    var data = {
-      databases: new Databases.List()
-    };
-    var deferred = FauxtonAPI.Deferred();
-
-    return {
-      layout: "with_sidebar",
-
-      data: data,
-
-      crumbs: [
-        {"name": "Databases", "link": "/_all_dbs"}
-      ],
-
-      views: {
-        "#dashboard-content": new Databases.Views.List({
-          collection: data.databases
-        }),
-
-        "#sidebar-content": new Databases.Views.Sidebar({
-          collection: data.databases
-        })
-      },
-
-      apiUrl: data.databases.url(),
-
-      establish: function() {
-        data.databases.fetch().done(function(resp) {
-          $.when.apply(null, data.databases.map(function(database) {
-            return database.status.fetch();
-          })).done(function(resp) {
-            deferred.resolve();
-          });
-        });
-        return [deferred];
-      }
-    };
-  };
-
-  /*
-  Databases.Routes = {
-    "": allDbsCallback,
-    "index.html": allDbsCallback,
-    "_all_dbs(:params)": allDbsCallback
-  };
-  */
-
-  Databases.RouteObjects = [new AllDbsRouteObject()];
+  
+  Databases.RouteObjects = [AllDbsRouteObject];
 
   return Databases;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/modules/databases/views.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/databases/views.js b/src/fauxton/app/modules/databases/views.js
index 6b9cfea..23145fe 100644
--- a/src/fauxton/app/modules/databases/views.js
+++ b/src/fauxton/app/modules/databases/views.js
@@ -66,7 +66,7 @@ function(app, Fauxton, FauxtonAPI) {
 
     paginated: function() {
       var start = (this.page - 1) * this.perPage;
-      var end = this.page * this.perPage - 1;
+      var end = this.page * this.perPage;
       return this.collection.slice(start, end);
     },
 
@@ -83,7 +83,8 @@ function(app, Fauxton, FauxtonAPI) {
         total: this.collection.length,
         urlFun: function(page) {
           return "#/_all_dbs?page=" + page;
-        }
+        },
+        routeEvent: "all_databases"
       }));
     },
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/modules/documents/routes.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/routes.js b/src/fauxton/app/modules/documents/routes.js
index 78af28e..d57487f 100644
--- a/src/fauxton/app/modules/documents/routes.js
+++ b/src/fauxton/app/modules/documents/routes.js
@@ -25,12 +25,24 @@ function(app, FauxtonAPI, Documents, Databases) {
   // var Documents = require("modules/documents/models_collections");
   // var Databases = require("modules/databases/module");
 
-  // TODO:: expand this for new docs and design docs
   var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({
     layout: "one_pane",
 
-    initialize: function() {
-      this.selected = false;
+    initialize: function(options) {
+      var databaseName = options[0], docID = options[1];
+
+      this.database = this.database || new Databases.Model({id: databaseName});
+      this.doc = this.doc || new Documents.Doc({
+        _id: docID
+      }, {
+        database: this.database
+      });
+
+      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
+        selected: "code_editor",
+        model: this.doc
+      }));
+
     },
 
     routes: function() {
@@ -43,6 +55,13 @@ function(app, FauxtonAPI, Documents, Databases) {
       "database/:database/:doc": "code_editor"
     },
 
+    events: {
+      "route:field_editor": "field_editor",
+      "route:code_editor": "code_editor"
+    },
+
+    defaultRoute: "code_editor",
+
     crumbs: function() {
       return [
         {"name": "Databases", "link": "/_all_dbs"},
@@ -51,35 +70,16 @@ function(app, FauxtonAPI, Documents, Databases) {
       ];
     },
 
-    setEditorView: function() {
-      if (this.selected === "field_editor") {
-        this.docView = this.setView("#dashboard-content", new Documents.Views.DocFieldEditor({
-          model: this.doc
-        }));
-      } else {
-        this.docView = this.setView("#dashboard-content", new Documents.Views.Doc({
-          model: this.doc
-        }));
-      }
+    code_editor: function (event) {
+      this.tabsView.updateSelected('code_editor');
+      this.docView = this.setView("#dashboard-content", new Documents.Views.Doc({
+        model: this.doc
+      }));
     },
 
-    route: function(route, args) {
-      var databaseName = args[0], docID = args[1];
-
-      this.database = this.database || new Databases.Model({id: databaseName});
-      this.doc = this.doc || new Documents.Doc({
-        _id: docID
-      }, {
-        database: this.database
-      });
-
-      if (this.selected !== this.selectedRoutes[route]) {
-        this.selected = this.selectedRoutes[route];
-        this.setEditorView();
-      }
-
-      this.tabsView = this.setView("#tabs", new Documents.Views.FieldEditorTabs({
-        selected: this.selected,
+    field_editor: function(events) {
+      this.tabsView.updateSelected('field_editor');
+      this.docView = this.setView("#dashboard-content", new Documents.Views.DocFieldEditor({
         model: this.doc
       }));
     },
@@ -182,13 +182,40 @@ function(app, FauxtonAPI, Documents, Databases) {
   var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({
     layout: "with_tabs_sidebar",
 
-    initialize: function () {
-
-    },
-
     events: {
       "route:all_docs": "allDocs",
-      "route:all_design_docs": "allDesignDocs"
+      "route:all_design_docs": "allDesignDocs",
+      "route:view_fn": "viewFn",
+      "route:new_view": "newViewEditor"
+    },
+
+    defaultRoute: "allDocs",
+
+    initialize: function (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
+      }));
+
+      this.setView("#tabs", new Documents.Views.Tabs({
+        collection: this.data.designDocs,
+        database: this.data.database
+      }));
     },
 
     crumbs: function () {
@@ -198,140 +225,109 @@ function(app, FauxtonAPI, Documents, Databases) {
       ];
     },
 
-    allDocs: function() {
-      console.log("TRIGGERING all_docs ROUTE EVENT", arguments);
-    },
+    allDocs: function(event) {
+      var docOptions;
 
-    allDesignDocs: function() {
-      console.log("TRIGGERING all_design_docs ROUTE EVENT", arguments);
-    },
+      docOptions = app.getParams(event.attr);
+      docOptions.include_docs = true;
 
-    routes: ["database/:database/_all_docs(:extra)", "database/:database/_design/:ddoc/_view/:view"],
+      this.data.database.buildAllDocs(docOptions);
+      this.sidebar.setSelectedTab('all-docs');
 
-    apiUrl: function() {
-      return this.data.database.allDocs.url();
-    },
-
-    route: function(route, params) {
-      this.databaseName = params[0];
-
-      if (params.length > 2) {
-        this.view = params[2].replace(/\?.*$/,'');
-        this.ddoc = params[1];
-      } else {
-        delete this.view;
-        delete this.ddoc;
-      }
+      this.documentsView = this.setView("#dashboard-content", new Documents.Views.AllDocsList({
+        collection: this.data.database.allDocs
+      }));
     },
 
-    // this works for now, but it might be work considering having a renderWith function

-    // that only renders a specific view and setups up that views establish beforehand.
-    rerender: function () {
-      var self = this,
-          options = app.getParams();
-
-      options.include_docs = true;
-      this.data.database.buildAllDocs(options);
+    allDesignDocs: function(event) {
+      var docOptions = app.getParams(event.attr);
+      docOptions.include_docs = true;
 
-      this.updateDashboardView();
+      this.data.database.buildAllDocs(docOptions);
+      this.sidebar.setSelectedTab('design-docs');
 
-      //this.documentsView.collection = this.data.database.allDocs;
-
-      $.when.apply(null, this.documentsView.establish()).then(function () {
-        //self.documentsView.render();
-        self.rerenderView('#dashboard-content');
-      });
+      this.documentsView = this.setView("#dashboard-content", new Documents.Views.AllDocsList({
+        collection: this.data.database.allDocs
+      }));
     },
 
-    updateDashboardView: function () {
-      var options = app.getParams();
+    route: function (route, routeArgs) {
+      console.log('ROUTE ARG ', arguments);
 
-      if (this.view) {
-        var ddocInfo = {
-        id: "_design/" + this.ddoc,
-          currView: this.view,
-          designDocs: this.data.designDocs
-        };
+      if (route === 'database/:database/_design/:ddoc/_view/:view') {
 
-        this.data.indexedDocs = new Documents.IndexCollection(null, {
-          database: this.data.database,
-          design: this.ddoc,
-          view: this.view,
-          params: options
-        });
-
-        this.documentsView = this.setView('#dashboard-content',new Documents.Views.AllDocsList({
-            collection: this.data.indexedDocs,
-            nestedView: Documents.Views.Row,
-            viewList: true,
-            ddocInfo: ddocInfo,
-            params: options
-          }));
+        if (!this.docCrumbs && !this.docApiUrl) {
+          // Save the old crumbs and API. Easier to do it here than in each event
+          this.docCrumbs = this.crumbs;
+          this.docApiUrl = this.apiUrl;
+        }
 
+        this.routeArgs = {
+          designDoc: routeArgs[1],
+          view: routeArgs[2].replace(/\?.*$/,'')
+        };
       } else {
-
-        this.documentsView = this.setView("#dashboard-content", new Documents.Views.AllDocsList({
-          collection: this.data.database.allDocs
-        }));
+        this.routeArgs = {};
+        if (this.docCrumbs && this.docApiUrl) {
+          this.crumbs = this.docCrumbs;
+          this.docApiUrl = this.apiUrl;
+        }
       }
-      
     },
 
-    views: function () {
-      this.data = {
-        database: new Databases.Model({id:this.databaseName})
-      };
+    viewFn: function (event) {
+      var view = this.routeArgs.view,
+      ddoc = this.routeArgs.designDoc,
+      params = app.getParams(event.attr);
 
-      this.data.designDocs = new Documents.AllDocs(null, {
+      console.log('PARAMS', params);
+
+      this.data.indexedDocs = new Documents.IndexCollection(null, {
         database: this.data.database,
-        params: {startkey: '"_design"',
-          endkey: '"_design1"',
-          include_docs: true}
+        design: ddoc,
+        view: view,
+        params: params
       });
 
+      var ddocInfo = {
+        id: "_design/" + ddoc,
+        currView: view,
+        designDocs: this.data.designDocs
+      };
 
-      var options = app.getParams();
-      options.include_docs = true;
-      this.data.database.buildAllDocs(options);
+      this.setView("#dashboard-content", new Documents.Views.AllDocsList({
+        collection: this.data.indexedDocs,
+        nestedView: Documents.Views.Row,
+        viewList: true,
+        ddocInfo: ddocInfo,
+        params: params
+      }));
 
-      if (this.view) {
-        var ddocInfo = {
-        id: "_design/" + this.ddoc,
-          currView: this.view,
-          designDocs: this.data.designDocs
-        };
+      this.crumbs = function () {
+        return [
+          {"name": "Databases", "link": "/_all_dbs"},
+          {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)},
+          {"name": ddoc + "/" + view, "link": this.data.indexedDocs.url()}
+        ];
+      };
 
-        this.data.indexedDocs = new Documents.IndexCollection(null, {
-          database: this.data.database,
-          design: this.ddoc,
-          view: this.view,
-          params: options
-        });
-
-        this.documentsView = this.setView('#dashboard-content',new Documents.Views.AllDocsList({
-            collection: this.data.indexedDocs,
-            nestedView: Documents.Views.Row,
-            viewList: true,
-            ddocInfo: ddocInfo,
-            params: options
-          }));
+      // TODO: change to view URL
+      this.apiUrl = this.data.indexedDocs.url();
+    },
 
-      } else {
+    newViewEditor: function (event) {
+      // TODO: Get this working
+      this.setView("#dashboard-content", new Documents.Views.ViewEditor({
+        model: this.data.database,
+        ddocs: this.data.designDocs
+      }));
 
-        this.documentsView = this.setView("#dashboard-content", new Documents.Views.AllDocsList({
-          collection: this.data.database.allDocs
-        }));
-      }
+    },
 
-      
-      this.setView("#sidebar-content", new Documents.Views.Sidebar({
-        collection: this.data.designDocs
-      }));
+    routes: ["database/:database/_all_docs(:extra)", "database/:database/_design/:ddoc/_view/:view",
"database/:database/new_view"],
 
-      this.setView("#tabs", new Documents.Views.Tabs({
-        collection: this.data.designDocs,
-        database: this.data.database
-      }));
+    apiUrl: function() {
+      return this.data.database.allDocs.url();
     }
   });
 
@@ -350,141 +346,63 @@ function(app, FauxtonAPI, Documents, Databases) {
 
     routes: ["database/:database/_changes(:params)"],
 
-    apiUrl: function() {
-      return this.database.changes.url();
+    events: {
+      "route:_changes": "changes"
     },
 
-    route: function(route, params) {
-      this.databaseName = params[0];
-    },
+    defaultRoute: "changes",
 
-    views: function () {
+    initialize: function (options) {
+      this.databaseName = options[0];
       this.database = new Databases.Model({id: this.databaseName});
 
-      var options = app.getParams();
-      this.database.buildChanges(options);
-
+      var docOptions = app.getParams();
 
-      this.setView("#dashboard-content", new Documents.Views.Changes({
-        model: this.database
-      }));
+      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.changes.url();
+    }
 
+  });
 
   /* Documents.Routes = {
-  //"database/:database/:doc/code_editor": codeEditorCallback,
-  //"database/:database/:doc": codeEditorCallback,
-  "database/:database/_design%2F:doc": function(database, doc) {
-  var docID = "_design/"+doc;
-  return codeEditorCallback(database, docID);
-  },
-
-  "database/:database/_all_docs(:extra)": function(databaseName, page) {
-  var data = {
-database: new Databases.Model({id:databaseName})
-};
-data.designDocs = new Documents.AllDocs(null, {
-database: data.database,
-params: {startkey: '"_design"',
-endkey: '"_design1"',
-include_docs: true}
-});
+     "database/:database/_design%2F:doc": function(database, doc) {
+     var docID = "_design/"+doc;
+     return codeEditorCallback(database, docID);
+     },
 
-var options = app.getParams();
-options.include_docs = true;
-data.database.buildAllDocs(options);
 
-return {
-layout: "with_tabs_sidebar",
-
-data: data,
 
-crumbs: [
-{"name": "Databases", "link": "/_all_dbs"},
-{"name": data.database.id, "link": Databases.databaseUrl(data.database)}
-],
-
-views: {
-"#dashboard-content": new Documents.Views.AllDocsList({
-collection: data.database.allDocs
-}),
-
-"#sidebar-content": new Documents.Views.Sidebar({
-collection: data.designDocs
-}),
-
-"#tabs": new Documents.Views.Tabs({
-collection: data.designDocs,
-database: data.database
-})
-},
-
-apiUrl: data.database.allDocs.url()
-};
-},
-
-"database/:database/_changes(:params)": function(databaseName, params) {
-var data = {
-database: new Databases.Model({id:databaseName})
-};
-
-var options = app.getParams();
-data.database.buildChanges(options);
-
-return {
-layout: "with_tabs",
-
-data: data,
-
-crumbs: [
-{"name": "Databases", "link": "/_all_dbs"},
-{"name": data.database.id, "link": Databases.databaseUrl(data.database)},
-{"name": "_changes", "link": "/_changes"}
-],
-
-views: {
-         "#dashboard-content": new Documents.Views.Changes({
-model: data.database
-}),
-
-         "#tabs": new Documents.Views.Tabs({
-collection: data.designDocs,
-database: data.database,
-active_id: 'changes'
-})
-},
-
-apiUrl: data.database.changes.url()
-  };
-},
-
-  "database/:database/new": newDocCodeEditorCallback,
-  "database/:database/new_view": newViewEditorCallback,
+     "database/:database/new": newDocCodeEditorCallback,
+     "database/:database/new_view": newViewEditorCallback,
 
   // TODO: fix optional search params
   // Can't get ":view(?*search)" to work
   // However ":view?*search" does work
   //"database/:database/_design/:ddoc/_view/:view(\?*options)": function(databaseName, ddoc,
view, options) {
   "database/:database/_design/:ddoc/_view/:view": function(databaseName, ddoc, view, options)
{
-    // hack around backbone router limitations
-    view = view.replace(/\?.*$/,'');
-    var params = app.getParams();
-    var data = {
+// hack around backbone router limitations
+view = view.replace(/\?.*$/,'');
+var params = app.getParams();
+var data = {
 database: new Databases.Model({id:databaseName})
-    };
+};
 
-    data.indexedDocs = new Documents.IndexCollection(null, {
+data.indexedDocs = new Documents.IndexCollection(null, {
 database: data.database,
 design: ddoc,
 view: view,
@@ -500,17 +418,17 @@ include_docs: true}
 
 var ddocInfo = {
 id: "_design/" + ddoc,
-    currView: view,
-    designDocs: data.designDocs
+currView: view,
+designDocs: data.designDocs
 };
 
 return {
 layout: "with_tabs_sidebar",
 
-          data: data,
-          // TODO: change dashboard-content
-          views: {
-            "#dashboard-content": new Documents.Views.AllDocsList({
+data: data,
+  // TODO: change dashboard-content
+views: {
+"#dashboard-content": new Documents.Views.AllDocsList({
 collection: data.indexedDocs,
 nestedView: Documents.Views.Row,
 viewList: true,
@@ -518,12 +436,12 @@ ddocInfo: ddocInfo,
 params: params
 }),
 
-            "#sidebar-content": new Documents.Views.Sidebar({
+"#sidebar-content": new Documents.Views.Sidebar({
 collection: data.designDocs,
 ddocInfo: ddocInfo
 }),
 
-            "#tabs": new Documents.Views.Tabs({
+"#tabs": new Documents.Views.Tabs({
 collection: data.designDocs,
 database: data.database
 })
@@ -540,7 +458,7 @@ crumbs: [
 }
 };*/
 
-  Documents.RouteObjects = [new DocEditorRouteObject(), new DocumentsRouteObject(), new ChangesRouteObject()];
+  Documents.RouteObjects = [DocEditorRouteObject, DocumentsRouteObject, ChangesRouteObject];
 
   return Documents;
 });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/modules/documents/views.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/views.js b/src/fauxton/app/modules/documents/views.js
index 558f0c1..6ac9b44 100644
--- a/src/fauxton/app/modules/documents/views.js
+++ b/src/fauxton/app/modules/documents/views.js
@@ -163,6 +163,12 @@ function(app, FauxtonAPI, Codemirror, JSHint) {
       });
     },
 
+    updateSelected: function (selected) {
+      this.selected = selected;
+      this.$('.active').removeClass('active');
+      this.$('#'+this.selected).addClass('active');
+    },
+
     serialize: function() {
       var selected = this.selected;
       return {
@@ -390,6 +396,7 @@ function(app, FauxtonAPI, Codemirror, JSHint) {
       var fragment = window.location.hash.replace(/\?.*$/, '');
       fragment = fragment + '?' + $.param(params);
       FauxtonAPI.navigate(fragment);
+      FauxtonAPI.triggerRouteEvent('view_fn', params);
     },
 
     updateFilters: function(event) {
@@ -921,6 +928,11 @@ function(app, FauxtonAPI, Codemirror, JSHint) {
           }
         }
       }, this);
+    },
+
+    setSelectedTab: function (selectedTab) {
+      this.$('li').removeClass('active');
+      this.$('#' + selectedTab).parent().addClass('active');
     }
 
   });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/modules/fauxton/base.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/fauxton/base.js b/src/fauxton/app/modules/fauxton/base.js
index 8ddbb17..3bcae5d 100644
--- a/src/fauxton/app/modules/fauxton/base.js
+++ b/src/fauxton/app/modules/fauxton/base.js
@@ -11,8 +11,7 @@
 // the License.
 
 define([
-       "app",
-
+  "app",
        // Libs
        "backbone"
 
@@ -157,6 +156,8 @@ function(app, Backbone) {
       this.total = options.total;
       this.totalPages = Math.ceil(this.total / this.perPage);
       this.urlFun = options.urlFun;
+      this.routeEvent = options.routeEvent;
+
     },
 
     serialize: function() {
@@ -165,7 +166,8 @@ function(app, Backbone) {
         perPage: this.perPage,
         total: this.total,
         totalPages: this.totalPages,
-        urlFun: this.urlFun
+        urlFun: this.urlFun,
+        routeEvent: this.routeEvent
       };
     }
   });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/router.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/router.js b/src/fauxton/app/router.js
index 2bcd071..09b2338 100644
--- a/src/fauxton/app/router.js
+++ b/src/fauxton/app/router.js
@@ -97,51 +97,27 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases,
Documents
     };
   };
 
-  FauxtonAPI.routeCallChain.registerBeforeRoute('no_deferred', function () {
-    console.log('This is a before route callback with no deferred.');
-  });
-
-  FauxtonAPI.routeCallChain.registerBeforeRoute('deferred', function () {
-    var deferred = $.Deferred();
-
-    setTimeout(function () {
-      console.log('hi this is a delayed called before each route.');
-      deferred.resolve();
-    }, 10);
-
-    return deferred;
-  });
-
   var Router = app.router = Backbone.Router.extend({
     routes: {},
 
-    // These moduleRoutes functions are aguably better outside but
-    // need access to the Router instance which is not created in this
-    // module
-    addModuleRoute: function(generator, route) {
-      //this.route(route, route.toString(), generateRoute(generator, route));
-    },
-
-    addModuleRouteObject: function(routeObject) {
+    addModuleRouteObject: function(RouteObject) {
       var self = this;
       var masterLayout = this.masterLayout;
 
-      _.each(routeObject.get('routes'), function(route) {
+      _.each(RouteObject.prototype.get('routes'), function(route) {
         this.route(route, route.toString(), function() {
-          var args = arguments;
+          var args = Array.prototype.slice.call(arguments);
 
-          if (self.activeRouteObject && routeObject !== self.activeRouteObject) {
-            self.activeRouteObject.renderedState = false;
-            self.activeRouteObject.clearViews();
+          if (self.activeRouteObject && self.activeRouteObject.get('routes').indexOf(route)
> -1) {
+            //Don't need to do anything here as this route has been initialised
+            self.activeRouteObject.route.call(self.activeRouteObject, route, args);
+            console.log('Avoiding Route creation');
+            return;
           }
 
-          FauxtonAPI.routeCallChain.run().then(function () {
-            routeObject.initialize();
-            routeObject.render(route, masterLayout, Array.prototype.slice.call(args));
-          });
-
-          self.activeRouteObject = routeObject;
-
+          self.activeRouteObject = new RouteObject(args);
+          self.activeRouteObject[self.activeRouteObject.defaultRoute].apply(self.activeRouteObject,
args);
+          self.activeRouteObject.render(route, masterLayout, args);
         });
       }, this);
     },
@@ -149,7 +125,6 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases,
Documents
     setModuleRoutes: function() {
       _.each(modules, function(module) {
         if (module){
-          _.each(module.Routes, this.addModuleRoute, this);
           _.each(module.RouteObjects, this.addModuleRouteObject, this);
         }
       }, this);
@@ -158,7 +133,6 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases,
Documents
           module.initialize();
           // This is pure routes the addon provides
           if (module.Routes) {
-            _.each(module.Routes, this.addModuleRoute, this);
             _.each(module.RouteObjects, this.addModuleRouteObject, this);
           }
         }
@@ -201,8 +175,10 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases,
Documents
 
     triggerRouteEvent: function(event, args) {
       if (this.activeRouteObject) {
+        var eventArgs = [event].concat(args);
         console.log("CALLING ROUTE EVENT ON", this.activeRouteObject, arguments);
-        this.activeRouteObject.trigger.apply(this.activeRouteObject, [event].concat(args));
+        this.activeRouteObject.trigger.apply(this.activeRouteObject, eventArgs );
+        this.activeRouteObject.renderWith(eventArgs, this.masterLayout, args);
       }
     }
   });

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
----------------------------------------------------------------------
diff --git a/src/fauxton/app/templates/documents/doc_field_editor_tabs.html b/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
index bb16d73..b094e0e 100644
--- a/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
+++ b/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
@@ -13,8 +13,8 @@ the License.
 -->
 
 <ul class="nav nav-tabs">
-  <li class="<%= isSelectedClass('field_editor') %>"><a href="#<%= doc.url('app')
%>/field_editor">Doc fields</a></li>
-  <li class="<%= isSelectedClass('code_editor') %>"><a href="#<%= doc.url('app')
%>/code_editor"><i class="icon-pencil"></i> Code editor</a></li>
+  <li id="field_editor" class="<%= isSelectedClass('field_editor') %>"><a
route-event="field_editor" href="#<%= doc.url('app') %>/field_editor">Doc fields</a></li>
+  <li id="code_editor" class="<%= isSelectedClass('code_editor') %>"><a route-event="code_editor"
href="#<%= doc.url('app') %>/code_editor"><i class="icon-pencil"></i>
Code editor</a></li>
   <ul class="nav pull-right" style="margin:5px 10px 0px 10px;">
     <li>
       <div class="btn-group">

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/templates/documents/index_menu_item.html
----------------------------------------------------------------------
diff --git a/src/fauxton/app/templates/documents/index_menu_item.html b/src/fauxton/app/templates/documents/index_menu_item.html
index bb16b4f..2dac868 100644
--- a/src/fauxton/app/templates/documents/index_menu_item.html
+++ b/src/fauxton/app/templates/documents/index_menu_item.html
@@ -12,6 +12,6 @@ License for the specific language governing permissions and limitations
under
 the License.
 -->
 
-<a href="#database/<%= database %>/_design/<%= ddoc %>/_view/<%= index
%>" class="toggle-view">
+<a route-event="view_fn" href="#database/<%= database %>/_design/<%= ddoc %>/_view/<%=
index %>" class="toggle-view">
   <i class="icon-list"></i> <%= ddoc %><span class="divider">/</span><%=
index %>
-</a>
\ No newline at end of file
+</a>

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/templates/documents/sidebar.html
----------------------------------------------------------------------
diff --git a/src/fauxton/app/templates/documents/sidebar.html b/src/fauxton/app/templates/documents/sidebar.html
index 9c61adc..a8841a2 100644
--- a/src/fauxton/app/templates/documents/sidebar.html
+++ b/src/fauxton/app/templates/documents/sidebar.html
@@ -24,6 +24,6 @@ the License.
   </ul>
   <ul class="nav nav-list views">
     <li class="nav-header">Secondary Indexes</li>
-    <li><a href="#<%= database.url('app') %>/new_view" class="new"><i
class="icon-plus"></i> New</a></li>
+    <li><a route-event="new_view" href="#<%= database.url('app') %>/new_view"
class="new"><i class="icon-plus"></i> New</a></li>
   </ul>
 </div>

http://git-wip-us.apache.org/repos/asf/couchdb/blob/d8b88562/src/fauxton/app/templates/fauxton/pagination.html
----------------------------------------------------------------------
diff --git a/src/fauxton/app/templates/fauxton/pagination.html b/src/fauxton/app/templates/fauxton/pagination.html
index 161593b..2ec5ebe 100644
--- a/src/fauxton/app/templates/fauxton/pagination.html
+++ b/src/fauxton/app/templates/fauxton/pagination.html
@@ -1,17 +1,17 @@
 <div class="pagination pagination-centered">
   <ul>
     <% if (page > 1) { %>
-      <li><a href="<%= urlFun(page-1) %>">&laquo;</a></li>
+    <li><a route-event="<%= routeEvent %>" href="<%= urlFun(page-1) %>">&laquo;</a></li>
     <% } else { %>
-      <li class="disabled"><a href="<%= urlFun(page) %>">&laquo;</a></li>
+      <li class="disabled"><a a route-event="<%= routeEvent %>" 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>
+      <li <% if (page == i) { %>class="active"<% } %>><a route-event="<%=
routeEvent %>" href="<%= urlFun(i) %>"><%= i %></a></li>
     <% }) %>
     <% if (page < totalPages) { %>
-      <li><a href="<%= urlFun(page+1) %>">&raquo;</a></li>
+      <li><a route-event="<%= routeEvent %>" href="<%= urlFun(page+1) %>">&raquo;</a></li>
     <% } else { %>
-      <li class="disabled"><a href="<%= urlFun(page) %>">&raquo;</a></li>
+      <li class="disabled"><a route-event="<%= routeEvent %>" href="<%=
urlFun(page) %>">&raquo;</a></li>
     <% } %>
   </ul>
 </div>


Mime
View raw message