You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2013/05/15 10:29:07 UTC
[07/13] git commit: updated refs/heads/master to 0cd82b9
Experimental Route Objects to reduce full page rendering
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/61419957
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/61419957
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/61419957
Branch: refs/heads/master
Commit: 61419957cfb00dbf83f49458ed611bc75d2611fb
Parents: 3fd0931
Author: Russell Branca <ch...@gmail.com>
Authored: Thu Apr 4 16:18:47 2013 -0700
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed May 15 10:26:26 2013 +0200
----------------------------------------------------------------------
src/fauxton/app/api.js | 128 +++++++++
src/fauxton/app/modules/databases/routes.js | 68 +++++-
src/fauxton/app/modules/databases/views.js | 4 +
src/fauxton/app/modules/documents/resources.js | 4 +-
src/fauxton/app/modules/documents/routes.js | 202 +++++----------
src/fauxton/app/router.js | 11 +
.../templates/documents/doc_field_editor_tabs.html | 2 +-
7 files changed, 272 insertions(+), 147 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/src/fauxton/app/api.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/api.js b/src/fauxton/app/api.js
index 52e8611..2c68086 100644
--- a/src/fauxton/app/api.js
+++ b/src/fauxton/app/api.js
@@ -96,6 +96,134 @@ function(app, Fauxton) {
}
});
+ FauxtonAPI.RouteObject = function(options) {
+ this._options = options;
+
+ this._configure(options || {});
+ this.initialize.apply(this, arguments);
+ this.addEvents();
+ };
+
+ // Piggy-back on Backbone's self-propagating extend function
+ FauxtonAPI.RouteObject.extend = Backbone.Model.extend;
+
+ var routeObjectOptions = ["views", "routes", "events", "data", "crumbs", "layout", "apiUrl", "establish"];
+
+ _.extend(FauxtonAPI.RouteObject.prototype, Backbone.Events, {
+ // Should these be default vals or empty funcs?
+ views: {},
+ routes: {},
+ events: {},
+ data: {},
+ crumbs: [],
+ layout: "with_sidebar",
+ apiUrl: null,
+ renderedState: false,
+ currTab: "databases",
+ establish: function() {},
+ 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
+ // immediately if its already done, but this way the RouteObject.route
+ // 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.renderWith.apply(this, arguments);
+ }
+ },
+
+ renderWith: function(route, masterLayout, args) {
+ var routeObject = this;
+ //this.route.apply(this, args);
+
+ masterLayout.setTemplate(this.layout);
+ masterLayout.clearBreadcrumbs();
+
+ if (this.crumbs.length) {
+ masterLayout.setBreadcrumbs(new Fauxton.Breadcrumbs({
+ crumbs: this.crumbs
+ }));
+ }
+
+ $.when.apply(this, this.establish()).done(function(resp) {
+ _.each(routeObject.views, function(view, selector) {
+ masterLayout.setView(selector, view);
+
+ $.when.apply(null, view.establish()).then(function(resp) {
+ masterLayout.renderView(selector);
+ }, function(resp) {
+ view.establishError = {
+ error: true,
+ reason: resp
+ };
+ masterLayout.renderView(selector);
+ });
+
+ var hooks = masterLayout.hooks[selector];
+
+ if(hooks){
+ _.each(hooks, function(hook){
+ if (_.any(hook.routes, function(route){return route == boundRoute;})){
+ hook.callback(view);
+ }
+ });
+ }
+ });
+ });
+
+ if (this.get('apiUrl')) masterLayout.apiBar.update(this.get('apiUrl'));
+
+ // Track that we've done a full initial render
+ this.renderedState = true;
+ },
+
+ 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;
+ }
+ });
+
app.fauxtonAPI = FauxtonAPI;
return app.fauxtonAPI;
});
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/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 2ba59d7..b7f1dbb 100644
--- a/src/fauxton/app/modules/databases/routes.js
+++ b/src/fauxton/app/modules/databases/routes.js
@@ -16,10 +16,70 @@ define([
"api",
// Modules
- "modules/databases/resources"
+ "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) {
+function(app, FauxtonAPI, Databases, Views) {
+ var AllDbsRouteObject = FauxtonAPI.RouteObject.extend({
+ layout: "with_sidebar",
+
+ crumbs: [
+ {"name": "Databases", "link": "/_all_dbs"}
+ ],
+
+ routes: ["", "index.html", "_all_dbs(:params)"],
+
+ apiUrl: function() {
+ return this.databases.url();
+ },
+
+ initialize: function() {
+ this.databases = new Databases.List();
+ this.deferred = FauxtonAPI.Deferred();
+
+ this.databasesView = this.setView("#dashboard-content", new Views.List({
+ collection: this.databases
+ }));
+ this.sidebarView = this.setView("#sidebar-content", new Views.Sidebar({
+ collection: this.databases
+ }));
+ },
+
+ route: function() {
+ var params = app.getParams();
+ this.databasesView.setPage(params.page);
+ },
+
+ rerender: function() {
+ this.databasesView.render();
+ },
+
+ establish: function() {
+ var databases = this.databases;
+ var deferred = this.deferred;
+
+ databases.fetch().done(function(resp) {
+ $.when.apply(null, databases.map(function(database) {
+ return database.status.fetch();
+ })).done(function(resp) {
+ deferred.resolve();
+ });
+ });
+
+ return [deferred];
+ },
+
+ mrEvent: function() {
+ console.log("Triggering a most excellent event!!!!");
+ },
+
+ events: {
+ "myrandom_event": "mrEvent"
+ }
+ });
+
var allDbsCallback = function() {
var data = {
databases: new Databases.List()
@@ -60,11 +120,15 @@ function(app, FauxtonAPI, Databases) {
};
};
+ /*
Databases.Routes = {
"": allDbsCallback,
"index.html": allDbsCallback,
"_all_dbs(:params)": allDbsCallback
};
+ */
+
+ Databases.RouteObjects = [new AllDbsRouteObject()];
return Databases;
});
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/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 1a02979..6b9cfea 100644
--- a/src/fauxton/app/modules/databases/views.js
+++ b/src/fauxton/app/modules/databases/views.js
@@ -87,6 +87,10 @@ function(app, Fauxton, FauxtonAPI) {
}));
},
+ setPage: function(page) {
+ this.page = page || 1;
+ },
+
afterRender: function() {
var dbLimit = this.dbLimit;
var ajaxReq;
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/src/fauxton/app/modules/documents/resources.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/modules/documents/resources.js b/src/fauxton/app/modules/documents/resources.js
index 3f07238..f1a07c3 100644
--- a/src/fauxton/app/modules/documents/resources.js
+++ b/src/fauxton/app/modules/documents/resources.js
@@ -35,9 +35,11 @@ function(app, FauxtonAPI, Views) {
}
},
- initialize: function() {
+ initialize: function(_attrs, options) {
if (this.collection && this.collection.database) {
this.database = this.collection.database;
+ } else if (options.database) {
+ this.database = options.database;
}
},
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/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 34b00d8..ffed186 100644
--- a/src/fauxton/app/modules/documents/routes.js
+++ b/src/fauxton/app/modules/documents/routes.js
@@ -25,51 +25,69 @@ function(app, FauxtonAPI, Documents, Databases) {
// var Documents = require("modules/documents/models_collections");
// var Databases = require("modules/databases/module");
- var codeEditorCallback = function(databaseName, docID) {
- var data = {
- database: new Databases.Model({id:databaseName}),
- doc: new Documents.Doc({
- "_id": docID
- }),
- selected: "code_editor"
- };
- data.doc.database = data.database;
- data.designDocs = new Documents.AllDocs(null, {
- database: data.database,
- params: {startkey: '"_design"',
- endkey: '"_design1"',
- include_docs: true}
- });
+ // TODO:: expand this for new docs and design docs
+ var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({
+ layout: "one_pane",
- var options = app.getParams();
- options.include_docs = true;
- data.database.buildAllDocs(options);
+ initialize: function() {
+ this.selected = false;
+ },
- return {
- layout: "one_pane",
+ routes: function() {
+ return _.keys(this.selectedRoutes);
+ },
- data: data,
+ selectedRoutes: {
+ "database/:database/:doc/field_editor": "field_editor",
+ "database/:database/:doc/code_editor": "code_editor",
+ "database/:database/:doc": "code_editor"
+ },
- crumbs: [
+ crumbs: function() {
+ return [
{"name": "Databases", "link": "/_all_dbs"},
- {"name": data.database.id, "link": Databases.databaseUrl(data.database)},
- {"name": docID, "link": "#"}
- ],
+ {"name": this.database.id, "link": Databases.databaseUrl(this.database)},
+ {"name": this.docID, "link": "#"}
+ ];
+ },
- views: {
- "#dashboard-content": new Documents.Views.Doc({
- model: data.doc
- }),
+ 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
+ }));
+ }
+ },
- "#tabs": new Documents.Views.FieldEditorTabs({
- selected: data.selected,
- model: data.doc
- })
- },
+ route: function(route, args) {
+ var databaseName = args[0], docID = args[1];
- apiUrl: data.doc.url()
- };
- };
+ 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,
+ model: this.doc
+ }));
+ },
+
+ apiUrl: function() {
+ return this.doc.url();
+ }
+ });
var newViewEditorCallback = function(databaseName) {
var data = {
@@ -161,117 +179,13 @@ function(app, FauxtonAPI, Documents, Databases) {
};
Documents.Routes = {
- "database/:database/:doc/field_editor": function(databaseName, docID) {
- var data = {
- database: new Databases.Model({id:databaseName}),
- doc: new Documents.Doc({
- "_id": docID
- }),
- selected: "field_editor"
- };
- data.doc.database = data.database;
- data.designDocs = new Documents.AllDocs(null, {
- database: data.database,
- params: {startkey: '"_design"',
- endkey: '"_design1"',
- include_docs: true}
- });
-
- var options = app.getParams();
- options.include_docs = true;
- data.database.buildAllDocs(options);
-
- return {
- layout: "one_pane",
-
- data: data,
-
- crumbs: [
- {"name": "Databases", "link": "/_all_dbs"},
- {"name": data.database.id, "link": Databases.databaseUrl(data.database)},
- {"name": docID, "link": "#"}
- ],
-
- views: {
- "#dashboard-content": new Documents.Views.DocFieldEditor({
- model: data.doc
- }),
-
- "#tabs": new Documents.Views.FieldEditorTabs({
- selected: data.selected,
- model: data.doc
- })
- },
-
- apiUrl: data.doc.url()
- };
- },
-
- "database/:database/:doc/code_editor": codeEditorCallback,
- "database/:database/:doc": codeEditorCallback,
+ //"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);
},
- // HACK
- // The ordering of routes is different in this object that the
- // routes object in the Backbone.Router. As a result, the
- // declaration order of show doc and _handler methods has been
- // switched. This is a brittle solution that needs to be fixed.
- // Conflicts with route: "database/:database/_:handler"
- //
- // TODO: add support for regex based rotues
- // Javascript does not handle a regex as an object key very well,
- // and it turns it into its string representation when you use in
- // non object literal form, which does get recast back as a regex
- // when we need it.
- // The inability to use regex based routes here is a design flaw
- // and should be rectified.
- "old_database/:database/:doc": function(databaseName, docID) {
- var data = {
- database: new Databases.Model({id:databaseName}),
- doc: new Documents.Doc({
- "_id": docID
- })
- };
- data.doc.database = data.database;
- data.designDocs = new Documents.AllDocs(null, {
- database: data.database,
- params: {startkey: '"_design"',
- endkey: '"_design1"',
- include_docs: true}
- });
-
- var options = app.getParams();
- options.include_docs = true;
- data.database.buildAllDocs(options);
-
- return {
- layout: "with_sidebar",
-
- data: data,
-
- crumbs: [
- {"name": "Databases", "link": "/_all_dbs"},
- {"name": data.database.id, "link": Databases.databaseUrl(data.database)},
- {"name": docID, "link": "#"}
- ],
-
- views: {
- "#dashboard-content": new Documents.Views.Doc({
- model: data.doc
- }),
-
- "#sidebar-content": new Documents.Views.Sidebar({
- collection: data.designDocs
- })
- },
-
- apiUrl: data.doc.url()
- };
- },
-
"database/:database/_all_docs(:extra)": function(databaseName, page) {
var data = {
database: new Databases.Model({id:databaseName})
@@ -422,5 +336,7 @@ function(app, FauxtonAPI, Documents, Databases) {
}
};
+ Documents.RouteObjects = [new DocEditorRouteObject()];
+
return Documents;
});
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/src/fauxton/app/router.js
----------------------------------------------------------------------
diff --git a/src/fauxton/app/router.js b/src/fauxton/app/router.js
index 77cc36b..45fd282 100644
--- a/src/fauxton/app/router.js
+++ b/src/fauxton/app/router.js
@@ -107,10 +107,21 @@ function(req, app, Initialize, FauxtonAPI, Fauxton, Layout, Databases, Documents
this.route(route, route.toString(), generateRoute(generator, route));
},
+ addModuleRouteObject: function(routeObject) {
+ var masterLayout = this.masterLayout;
+ _.each(routeObject.get('routes'), function(route) {
+ //this.route(route, route.toString(), _.partial(routeObject.renderWith, route, this.masterLayout));
+ this.route(route, route.toString(), function() {
+ routeObject.render(route, masterLayout, Array.prototype.slice.call(arguments));
+ });
+ }, this);
+ },
+
setModuleRoutes: function() {
_.each(modules, function(module) {
if (module){
_.each(module.Routes, this.addModuleRoute, this);
+ _.each(module.RouteObjects, this.addModuleRouteObject, this);
}
}, this);
_.each(LoadAddons.addons, function(module) {
http://git-wip-us.apache.org/repos/asf/couchdb/blob/61419957/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 ecb0e48..bb16d73 100644
--- a/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
+++ b/src/fauxton/app/templates/documents/doc_field_editor_tabs.html
@@ -13,7 +13,7 @@ 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('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>
<ul class="nav pull-right" style="margin:5px 10px 0px 10px;">
<li>