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 2014/08/12 16:56:09 UTC

[01/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/backbone.layout-upgrade 753eab5a5 -> 755eb7a75 (forced update)


Fix link for new design 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/b58f613b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b58f613b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b58f613b

Branch: refs/heads/backbone.layout-upgrade
Commit: b58f613b1ba515bcdcae1c294d6450f6f65f3b9e
Parents: ca7843b
Author: Robert Kowalski <ro...@kowalski.gd>
Authored: Thu Jul 31 20:21:00 2014 +0200
Committer: Robert Kowalski <ro...@kowalski.gd>
Committed: Thu Jul 31 20:21:00 2014 +0200

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


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b58f613b/app/addons/documents/views-sidebar.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-sidebar.js b/app/addons/documents/views-sidebar.js
index e3cc629..8699417 100644
--- a/app/addons/documents/views-sidebar.js
+++ b/app/addons/documents/views-sidebar.js
@@ -68,17 +68,17 @@ function(app, FauxtonAPI, Components, Documents, Databases) {
       );
 
       var database = this.collection.database,
-          newurl = "#" + database.url('app') + '/new';
+          newurlPrefix = "#" + database.url('app');
 
       var newLinks = [{
         title: 'Add new',
         links: [{
           title: 'New Doc',
-          url: newurl,
+          url: newurlPrefix + '/new',
           icon: 'fonticon-plus-circled'
         },{
           title: 'New Design Doc',
-          url: newurl,
+          url: newurlPrefix + '/new_view',
           icon: 'fonticon-plus-circled'
         }]
       }];


[13/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Fix changesSpec


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 755eb7a7532f23eb22871ccb36559c6f18b6b941
Parents: 4c4308d
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Aug 12 16:55:28 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:55:28 2014 +0200

----------------------------------------------------------------------
 app/addons/documents/tests/views-changesSpec.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/755eb7a7/app/addons/documents/tests/views-changesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/views-changesSpec.js b/app/addons/documents/tests/views-changesSpec.js
index 94ca585..8fa2f7b 100644
--- a/app/addons/documents/tests/views-changesSpec.js
+++ b/app/addons/documents/tests/views-changesSpec.js
@@ -28,7 +28,7 @@ define([
 
     handlerSpy = sinon.spy(Views.Changes.prototype, 'toggleJson');
 
-    beforeEach(function () {
+    beforeEach(function (done) {
       var database = new Databases.Model({id: 'bla'});
       database.buildChanges({descending: 'true', limit: '100', include_docs: 'true'} );
       filteredView = new Views.Changes({
@@ -39,7 +39,7 @@ define([
         model: model
       });
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(view);
+      viewSandbox.renderView(view, done);
     });
 
     afterEach(function () {


[05/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Configure zeroclipboard for deployment

Move zeroclipboard into its own component. Handle the location of
zeroclipboard for Fauxton deployment and Also allow the moviepath to
be overriddern for custom deployment 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/285d32e7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/285d32e7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/285d32e7

Branch: refs/heads/backbone.layout-upgrade
Commit: 285d32e7d31dcffa586df5e8c354c80fa4c8682b
Parents: 25e74fa
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Aug 6 15:30:01 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Aug 6 15:30:01 2014 +0200

----------------------------------------------------------------------
 Gruntfile.js                          | 10 ++++++++--
 app/addons/documents/views-changes.js | 10 ++++------
 app/addons/fauxton/base.js            |  9 ++++++---
 app/addons/fauxton/components.js      | 27 +++++++++++++++++++++++++--
 tasks/couchserver.js                  |  2 ++
 5 files changed, 45 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/285d32e7/Gruntfile.js
----------------------------------------------------------------------
diff --git a/Gruntfile.js b/Gruntfile.js
index dbcdd2c..f6d2347 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -346,6 +346,12 @@ module.exports = function(grunt) {
         ]
       },
 
+      zeroclip: {
+        files: [
+          {src: "assets/js/plugins/zeroclipboard/ZeroClipboard.swf", dest: "dist/release/js/zeroclipboard/ZeroClipboard.swf"},
+        ]
+      },
+
       dist:{
         files:[
           {src: "dist/debug/index.html", dest: "dist/release/index.html"},
@@ -466,8 +472,8 @@ module.exports = function(grunt) {
 
   grunt.registerTask('watchRun', ['clean:watch', 'dependencies', 'jshint']);
   // build a release
-  grunt.registerTask('release', ['clean' ,'dependencies', "gen_initialize:release", 'jshint', 'build', 'minify', 'copy:dist', 'copy:ace']);
-  grunt.registerTask('couchapp_release', ['clean' ,'dependencies', "gen_initialize:couchapp", 'jshint', 'build', 'minify', 'copy:dist', 'copy:ace']);
+  grunt.registerTask('release', ['clean' ,'dependencies', "gen_initialize:release", 'jshint', 'build', 'minify', 'copy:dist', 'copy:ace', 'copy:zeroclip']);
+  grunt.registerTask('couchapp_release', ['clean' ,'dependencies', "gen_initialize:couchapp", 'jshint', 'build', 'minify', 'copy:dist', 'copy:ace', 'copy:zeroclip']);
 
   /*
    * Install into CouchDB in either debug, release, or couchapp mode

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/285d32e7/app/addons/documents/views-changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-changes.js b/app/addons/documents/views-changes.js
index 3404346..fad88b9 100644
--- a/app/addons/documents/views-changes.js
+++ b/app/addons/documents/views-changes.js
@@ -19,10 +19,7 @@ define([
        "addons/fauxton/components",
 
        // Plugins
-       "plugins/prettify",
-       // this should never be global available:
-       // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
-       "plugins/zeroclipboard/ZeroClipboard"
+       "plugins/prettify"
 ],
 
 function(app, FauxtonAPI, resizeColumns, Components, prettify, ZeroClipboard) {
@@ -118,8 +115,9 @@ function(app, FauxtonAPI, resizeColumns, Components, prettify, ZeroClipboard) {
 
     afterRender: function(){
       prettyPrint();
-      ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
-      var client = new ZeroClipboard(this.$(".js-copy"));
+      var client = new Components.Clipboard({
+        $el: this.$('.js-copy')
+      });
     }
   });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/285d32e7/app/addons/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js
index 7a3ab8f..00f73a7 100644
--- a/app/addons/fauxton/base.js
+++ b/app/addons/fauxton/base.js
@@ -14,10 +14,11 @@ define([
   "app",
   "api",
   "addons/fauxton/resizeColumns",
+  "addons/fauxton/components",
   "plugins/zeroclipboard/ZeroClipboard"
 ],
 
-function(app, FauxtonAPI, resizeColumns, ZeroClipboard) {
+function(app, FauxtonAPI, resizeColumns, Components, ZeroClipboard) {
 
   var Fauxton = FauxtonAPI.addon();
   FauxtonAPI.addNotification = function (options) {
@@ -298,8 +299,10 @@ function(app, FauxtonAPI, resizeColumns, ZeroClipboard) {
       this.render();
     },
     afterRender: function(){
-      ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
-      var client = new ZeroClipboard(this.$(".copy-url"));
+      var client = new Components.Clipboard({
+        $el: this.$('.copy-url')
+      });
+
       client.on("load", function(e){
         var $apiInput = $('#api-navbar input');
         var copyURLTimer;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/285d32e7/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index d77af4a..c863ba7 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -25,10 +25,13 @@ define([
   // Libs
   "api",
   "ace_configuration",
-  "spin"
+  "spin",
+  // this should never be global available:
+  // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
+  "plugins/zeroclipboard/ZeroClipboard"
 ],
 
-function(app, FauxtonAPI, ace, spin) {
+function(app, FauxtonAPI, ace, spin, ZeroClipboard) {
   var Components = FauxtonAPI.addon();
 
   Components.Pagination = FauxtonAPI.View.extend({
@@ -630,6 +633,25 @@ function(app, FauxtonAPI, ace, spin) {
     }
   });
 
+  Components.Clipboard = FauxtonAPI.View.extend({
+    initialize: function (options) {
+      this.$el = options.$el;
+      this.moviePath = FauxtonAPI.getExtensions('zeroclipboard:movielist')[0];
+
+      if (_.isUndefined(this.moviePath)) {
+       this.moviePath = app.host + app.root + "js/zeroclipboard/ZeroClipboard.swf";
+      }
+
+      ZeroClipboard.config({ moviePath: this.moviePath });
+      this.client = new ZeroClipboard(this.$el);
+    },
+
+    on: function () {
+      return this.client.on.apply(this.client, arguments);
+    }
+
+  });
+
 
   //need to make this into a backbone view...
   var routeObjectSpinner;
@@ -710,6 +732,7 @@ function(app, FauxtonAPI, ace, spin) {
     removeRouteObjectSpinner();
   });
 
+
   return Components;
 });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/285d32e7/tasks/couchserver.js
----------------------------------------------------------------------
diff --git a/tasks/couchserver.js b/tasks/couchserver.js
index 45a4f9c..e576219 100644
--- a/tasks/couchserver.js
+++ b/tasks/couchserver.js
@@ -67,6 +67,8 @@ module.exports = function (grunt) {
       } else if (!!url.match(/\.js$|\.html$/)) {
         // server js from app directory
         filePath = path.join(app_dir, url.replace('/_utils/fauxton/',''));
+      } else if (!!url.match(/ZeroClipboard/)) {
+        filePath = "./assets/js/plugins/zeroclipboard/ZeroClipboard.swf"
       } else if (!!url.match(/testrunner/)) {
         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);


[04/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Fixes broken icons in firefox

This fixes COUCHDB-2288


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 25e74fab1b3fe0b125a06f481cf5a670bd4d87d4
Parents: 07945ec
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Aug 4 14:03:55 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Mon Aug 4 16:03:09 2014 +0200

----------------------------------------------------------------------
 assets/fonts/README.md        |   4 ++--
 assets/fonts/fauxtonicon.eot  | Bin 16314 -> 17640 bytes
 assets/fonts/fauxtonicon.svg  |   8 ++++----
 assets/fonts/fauxtonicon.ttf  | Bin 16130 -> 17452 bytes
 assets/fonts/fauxtonicon.woff | Bin 5804 -> 10000 bytes
 assets/less/icons.less        |   2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/fonts/README.md
----------------------------------------------------------------------
diff --git a/assets/fonts/README.md b/assets/fonts/README.md
index 27311ca..fade249 100644
--- a/assets/fonts/README.md
+++ b/assets/fonts/README.md
@@ -19,7 +19,7 @@ That should install the gem in a path like below:
 
 Don't forget to update `fontcustom.yml` with the correct paths where it says `PUT_YOUR_PATH_HERE`.
 
-From there, you can run the command `$ fontcustom compile` to compile the svgs located in the ./icons directory into updated fauxtonicon font files. 
+From there, you can run the command `$ bundle exec fontcustom compile` to compile the svgs located in the ./icons directory into updated fauxtonicon font files. 
 
 It's setup to generate the following 
 - an `icons.less` file [LOCAL_COUCHDB_REPO]/src/couchdb-fauxton/assets/less
@@ -36,4 +36,4 @@ For more info on Fontcustom, check out their documenation: [Fontcustom documenta
 For more info on Bundler, check out their documentation:  [Bundler documentation](http://bundler.io)
 
 
-[Licenses](https://github.com/FontCustom/fontcustom/blob/master/LICENSES.txt)
\ No newline at end of file
+[Licenses](https://github.com/FontCustom/fontcustom/blob/master/LICENSES.txt)

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/fonts/fauxtonicon.eot
----------------------------------------------------------------------
diff --git a/assets/fonts/fauxtonicon.eot b/assets/fonts/fauxtonicon.eot
index 20af5ca..85d7c01 100644
Binary files a/assets/fonts/fauxtonicon.eot and b/assets/fonts/fauxtonicon.eot differ

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/fonts/fauxtonicon.svg
----------------------------------------------------------------------
diff --git a/assets/fonts/fauxtonicon.svg b/assets/fonts/fauxtonicon.svg
index 7da516c..7b77755 100644
--- a/assets/fonts/fauxtonicon.svg
+++ b/assets/fonts/fauxtonicon.svg
@@ -1,13 +1,13 @@
 <?xml version="1.0" standalone="no"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
 <!--
-2014-7-21: Created.
+2014-8-4: Created.
 -->
 <svg xmlns="http://www.w3.org/2000/svg">
 <metadata>
-Created by FontForge 20120731 at Mon Jul 21 16:28:03 2014
- By Sean Barclay
-Created by Sean Barclay with FontForge 2.0 (http://fontforge.sf.net)
+Created by FontForge 20120731 at Mon Aug  4 13:55:25 2014
+ By Garren Smith
+Created by Garren Smith with FontForge 2.0 (http://fontforge.sf.net)
 </metadata>
 <defs>
 <font id="fauxtonicon" horiz-adv-x="512" >

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/fonts/fauxtonicon.ttf
----------------------------------------------------------------------
diff --git a/assets/fonts/fauxtonicon.ttf b/assets/fonts/fauxtonicon.ttf
index b1b0085..3b59a2f 100644
Binary files a/assets/fonts/fauxtonicon.ttf and b/assets/fonts/fauxtonicon.ttf differ

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/fonts/fauxtonicon.woff
----------------------------------------------------------------------
diff --git a/assets/fonts/fauxtonicon.woff b/assets/fonts/fauxtonicon.woff
index 471ce74..d228017 100644
Binary files a/assets/fonts/fauxtonicon.woff and b/assets/fonts/fauxtonicon.woff differ

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/25e74fab/assets/less/icons.less
----------------------------------------------------------------------
diff --git a/assets/less/icons.less b/assets/less/icons.less
index 28ff310..8b8559e 100644
--- a/assets/less/icons.less
+++ b/assets/less/icons.less
@@ -274,4 +274,4 @@ https://github.com/seanbarclay/fontcustom/blob/1c3ad3d2633d3a8add39e8827115394e9
 .fonticon-up-open:before { content: "\f16b"; }
 .fonticon-user:before { content: "\f16c"; }
 .fonticon-users:before { content: "\f16d"; }
-.fonticon-wrench:before { content: "\f16e"; }
+.fonticon-wrench:before { content: "\f16e"; }
\ No newline at end of file


[03/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Link local docs in Fauxton

Instead of linking to the latest version online, we link to the
docs for the locally installed version. The docs are
generated automatically when running make / make install, if you
have Sphinx installed. For development, the dev-server will just
proxy the request.


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 07945ecfacb57c9a0d31f07708e08018e265f49a
Parents: 4382f43
Author: Robert Kowalski <ro...@kowalski.gd>
Authored: Sat Aug 2 17:24:51 2014 +0200
Committer: Robert Kowalski <ro...@kowalski.gd>
Committed: Sat Aug 2 17:24:51 2014 +0200

----------------------------------------------------------------------
 .../templates/design_doc_selector.html          |  2 +-
 app/addons/documents/templates/view_editor.html |  6 ++--
 app/addons/fauxton/templates/api_bar.html       |  2 +-
 app/addons/fauxton/templates/nav_bar.html       |  2 +-
 app/addons/permissions/templates/section.html   |  2 +-
 app/addons/replication/templates/form.html      |  2 +-
 app/helpers.js                                  | 31 ++++++++++----------
 tasks/couchserver.js                            |  7 +++--
 8 files changed, 27 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/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
index 828b5a5..d12cd64 100644
--- a/app/addons/documents/templates/design_doc_selector.html
+++ b/app/addons/documents/templates/design_doc_selector.html
@@ -12,7 +12,7 @@ License for the specific language governing permissions and limitations under
 the License.
 -->
 <div class="span3">
-  <label for="ddoc">Save to Design Document <a class="help-link" href="<%-getDocUrl('design_doc')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+  <label for="ddoc">Save to Design Document <a class="help-link" data-bypass="true" 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>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/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 e6fbbc1..769deed 100644
--- a/app/addons/documents/templates/view_editor.html
+++ b/app/addons/documents/templates/view_editor.html
@@ -35,13 +35,13 @@ the License.
           </div>
 
           <div class="control-group">
-            <label for="index-name">Index name <a class="help-link" href="<%-getDocUrl('view_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+            <label for="index-name">Index name <a class="help-link" data-bypass="true" 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 class="help-link" href="<%-getDocUrl('map_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+            <label for="map-function">Map function <a class="help-link" data-bypass="true" 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 { %>
@@ -52,7 +52,7 @@ the License.
 
 
           <div class="control-group">
-            <label for="reduce-function-selector">Reduce (optional) <a class="help-link" href="<%-getDocUrl('reduce_functions')%>" target="_blank"><i class="icon-question-sign"></i></a></label>
+            <label for="reduce-function-selector">Reduce (optional) <a class="help-link" data-bypass="true" 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>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/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 773ccbd..f56741c 100644
--- a/app/addons/fauxton/templates/api_bar.html
+++ b/app/addons/fauxton/templates/api_bar.html
@@ -21,7 +21,7 @@ the License.
     <div class="input-prepend input-append">
       <span class="add-on">
         API URL
-        <a class="help-link" href="<%-getDocUrl(documentation)%>" target="_blank">
+        <a class="help-link" data-bypass="true" href="<%-getDocUrl(documentation)%>" target="_blank">
           <i class="icon-question-sign"></i>
         </a>
       </span>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/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 3de8a80..f33399d 100644
--- a/app/addons/fauxton/templates/nav_bar.html
+++ b/app/addons/fauxton/templates/nav_bar.html
@@ -34,7 +34,7 @@ the License.
   <div id="bottom-nav">
   	<ul id="bottom-nav-links" class="nav">
         <li data-nav-name= "Documentation">
-            <a href="<%-getDocUrl('docs')%>" target="_blank">
+            <a data-bypass="true" href="<%-getDocUrl('docs')%>" target="_blank">
               <i class="fonticon-bookmark fonticon"></i>
                 Documentation
             </a>

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/app/addons/permissions/templates/section.html
----------------------------------------------------------------------
diff --git a/app/addons/permissions/templates/section.html b/app/addons/permissions/templates/section.html
index 6b54185..a320c90 100644
--- a/app/addons/permissions/templates/section.html
+++ b/app/addons/permissions/templates/section.html
@@ -13,7 +13,7 @@ the License.
 -->
 <header class="page-header">
 <h3> <%- section %> </h3>
-<p class="help"> <%- help %> <a class="help-link" href="<%-getDocUrl('database_permission')%>" target="_blank"><i class="icon-question-sign"> </i> </a></p>
+<p class="help"> <%- help %> <a class="help-link" data-bypass="true" href="<%-getDocUrl('database_permission')%>" target="_blank"><i class="icon-question-sign"> </i> </a></p>
 </header>
 
 <div class="row-fluid">

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/app/addons/replication/templates/form.html
----------------------------------------------------------------------
diff --git a/app/addons/replication/templates/form.html b/app/addons/replication/templates/form.html
index 99e2d3d..e354bc0 100644
--- a/app/addons/replication/templates/form.html
+++ b/app/addons/replication/templates/form.html
@@ -63,7 +63,7 @@ the License.
 
 			<label for="createTarget">
 				<input type="checkbox" name="create_target" value="true" id="createTarget">
-				Create Target <a class="help-link" href="<%-getDocUrl('replication_doc')%>" target="_blank"><i class="icon-question-sign" rel="tooltip" title="Create the target database"></i></a>
+				Create Target <a class="help-link" data-bypass="true" href="<%-getDocUrl('replication_doc')%>" target="_blank"><i class="icon-question-sign" rel="tooltip" title="Create the target database"></i></a>
 			</label>
 		</div>
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/app/helpers.js
----------------------------------------------------------------------
diff --git a/app/helpers.js b/app/helpers.js
index 208b0d9..6fa8481 100644
--- a/app/helpers.js
+++ b/app/helpers.js
@@ -36,25 +36,24 @@ function(utils, d3) {
     return path;
   };
 
-
   // Get the URL for documentation, wiki, wherever we store it.
   // update the URLs in documentation_urls.js
   Helpers.docs =  {
-    "docs": "http://docs.couchdb.org/en/latest/intro/api.html#documents",
-    "all_dbs": "http://docs.couchdb.org/en/latest/api/server/common.html?highlight=all_dbs#get--_all_dbs",
-    "replication_doc": "http://docs.couchdb.org/en/latest/replication/replicator.html#basics",
-    "design_doc": "http://docs.couchdb.org/en/latest/couchapp/ddocs.html#design-docs",
-    "view_functions": "http://docs.couchdb.org/en/latest/couchapp/ddocs.html#view-functions",
-    "map_functions": "http://docs.couchdb.org/en/latest/couchapp/ddocs.html#map-functions",
-    "reduce_functions": "http://docs.couchdb.org/en/latest/couchapp/ddocs.html#reduce-and-rereduce-functions",
-    "api_reference": "http://docs.couchdb.org/en/latest/http-api.html",
-    "database_permission": "http://docs.couchdb.org/en/latest/api/database/security.html#db-security",
-    "stats": "http://docs.couchdb.org/en/latest/api/server/common.html?highlight=stats#get--_stats",
-    "_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",
-    "changes": "http://docs.couchdb.org/en/latest/api/database/changes.html?highlight=changes#post--db-_changes"
+    "docs": "/_utils/docs/intro/api.html#documents",
+    "all_dbs": "/_utils/docs/api/server/common.html?highlight=all_dbs#get--_all_dbs",
+    "replication_doc": "/_utils/docs/replication/replicator.html#basics",
+    "design_doc": "/_utils/docs/couchapp/ddocs.html#design-docs",
+    "view_functions": "/_utils/docs/couchapp/ddocs.html#view-functions",
+    "map_functions": "/_utils/docs/couchapp/ddocs.html#map-functions",
+    "reduce_functions": "/_utils/docs/couchapp/ddocs.html#reduce-and-rereduce-functions",
+    "api_reference": "/_utils/docs/http-api.html",
+    "database_permission": "/_utils/docs/api/database/security.html#db-security",
+    "stats": "/_utils/docs/api/server/common.html?highlight=stats#get--_stats",
+    "_active_tasks": "/_utils/docs/api/server/common.html?highlight=stats#active-tasks",
+    "log": "/_utils/docs/api/server/common.html?highlight=stats#log",
+    "config": "/_utils/docs/config/index.html",
+    "views": "/_utils/docs/intro/overview.html#views",
+    "changes": "/_utils/docs/api/database/changes.html?highlight=changes#post--db-_changes"
   };
 
   Helpers.getDocUrl = function(docKey){

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/07945ecf/tasks/couchserver.js
----------------------------------------------------------------------
diff --git a/tasks/couchserver.js b/tasks/couchserver.js
index b12e8c2..45a4f9c 100644
--- a/tasks/couchserver.js
+++ b/tasks/couchserver.js
@@ -64,9 +64,6 @@ module.exports = function (grunt) {
       } else if (!!url.match(/\.css|img/)) {
         url = url.replace(/\?.*/, '');
         filePath = path.join(dist_dir,url);
-      /*} else if (!!url.match(/\/js\//)) {
-        // serve any javascript or files from dist debug dir
-        filePath = path.join(dist_dir,req.url);*/
       } else if (!!url.match(/\.js$|\.html$/)) {
         // server js from app directory
         filePath = path.join(app_dir, url.replace('/_utils/fauxton/',''));
@@ -80,6 +77,10 @@ module.exports = function (grunt) {
         filePath = path.join(dist_dir, 'index.html');
       };
 
+      if (/_utils\/docs/.test(filePath)) {
+        filePath = false;
+      }
+
       if (filePath) {
         return send(req, filePath)
           .on('error', function (err) {


[07/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Upgrade d3 to version 3.4.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/b7fc5f44
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b7fc5f44
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b7fc5f44

Branch: refs/heads/backbone.layout-upgrade
Commit: b7fc5f444e3878f506acfa48469ec2396d73d75c
Parents: 79c11d7
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Aug 12 15:42:37 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 15:42:37 2014 +0200

----------------------------------------------------------------------
 assets/js/libs/d3.js | 907 ++++++++++++++++++++++------------------------
 1 file changed, 433 insertions(+), 474 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b7fc5f44/assets/js/libs/d3.js
----------------------------------------------------------------------
diff --git a/assets/js/libs/d3.js b/assets/js/libs/d3.js
index b57c8d0..38a2047 100644
--- a/assets/js/libs/d3.js
+++ b/assets/js/libs/d3.js
@@ -1,6 +1,6 @@
 !function() {
   var d3 = {
-    version: "3.4.3"
+    version: "3.4.11"
   };
   if (!Date.now) Date.now = function() {
     return +new Date();
@@ -32,9 +32,10 @@
       d3_style_setProperty.call(this, name, value + "", priority);
     };
   }
-  d3.ascending = function(a, b) {
+  d3.ascending = d3_ascending;
+  function d3_ascending(a, b) {
     return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
-  };
+  }
   d3.descending = function(a, b) {
     return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
   };
@@ -90,13 +91,13 @@
     return x != null && !isNaN(x);
   }
   d3.mean = function(array, f) {
-    var n = array.length, a, m = 0, i = -1, j = 0;
+    var s = 0, n = array.length, a, i = -1, j = n;
     if (arguments.length === 1) {
-      while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
+      while (++i < n) if (d3_number(a = array[i])) s += a; else --j;
     } else {
-      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
+      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) s += a; else --j;
     }
-    return j ? m : undefined;
+    return j ? s / j : undefined;
   };
   d3.quantile = function(values, p) {
     var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
@@ -105,16 +106,16 @@
   d3.median = function(array, f) {
     if (arguments.length > 1) array = array.map(f);
     array = array.filter(d3_number);
-    return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
+    return array.length ? d3.quantile(array.sort(d3_ascending), .5) : undefined;
   };
-  d3.bisector = function(f) {
+  function d3_bisector(compare) {
     return {
       left: function(a, x, lo, hi) {
         if (arguments.length < 3) lo = 0;
         if (arguments.length < 4) hi = a.length;
         while (lo < hi) {
           var mid = lo + hi >>> 1;
-          if (f.call(a, a[mid], mid) < x) lo = mid + 1; else hi = mid;
+          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
         }
         return lo;
       },
@@ -123,17 +124,20 @@
         if (arguments.length < 4) hi = a.length;
         while (lo < hi) {
           var mid = lo + hi >>> 1;
-          if (x < f.call(a, a[mid], mid)) hi = mid; else lo = mid + 1;
+          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
         }
         return lo;
       }
     };
+  }
+  var d3_bisect = d3_bisector(d3_ascending);
+  d3.bisectLeft = d3_bisect.left;
+  d3.bisect = d3.bisectRight = d3_bisect.right;
+  d3.bisector = function(f) {
+    return d3_bisector(f.length === 1 ? function(d, x) {
+      return d3_ascending(f(d), x);
+    } : f);
   };
-  var d3_bisector = d3.bisector(function(d) {
-    return d;
-  });
-  d3.bisectLeft = d3_bisector.left;
-  d3.bisect = d3.bisectRight = d3_bisector.right;
   d3.shuffle = function(array) {
     var m = array.length, t, i;
     while (m) {
@@ -488,16 +492,14 @@
     return n.querySelector(s);
   }, d3_selectAll = function(s, n) {
     return n.querySelectorAll(s);
-  }, d3_selectMatcher = d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) {
+  }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) {
     return d3_selectMatcher.call(n, s);
   };
   if (typeof Sizzle === "function") {
     d3_select = function(s, n) {
       return Sizzle(s, n)[0] || null;
     };
-    d3_selectAll = function(s, n) {
-      return Sizzle.uniqueSort(Sizzle(s, n));
-    };
+    d3_selectAll = Sizzle;
     d3_selectMatches = Sizzle.matchesSelector;
   }
   d3.selection = function() {
@@ -625,7 +627,7 @@
     return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
   }
   function d3_selection_classes(name) {
-    return name.trim().split(/^|\s+/);
+    return (name + "").trim().split(/^|\s+/);
   }
   function d3_selection_classed(name, value) {
     name = d3_selection_classes(name).map(d3_selection_classedName);
@@ -872,7 +874,7 @@
     return this.order();
   };
   function d3_selection_sortComparator(comparator) {
-    if (!arguments.length) comparator = d3.ascending;
+    if (!arguments.length) comparator = d3_ascending;
     return function(a, b) {
       return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
     };
@@ -1123,46 +1125,42 @@
     }) : [];
   };
   d3.behavior.drag = function() {
-    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, "mousemove", "mouseup"), touchstart = dragstart(touchid, touchposition, "touchmove", "touchend");
+    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend");
     function drag() {
       this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
     }
-    function touchid() {
-      return d3.event.changedTouches[0].identifier;
-    }
-    function touchposition(parent, id) {
-      return d3.touches(parent).filter(function(p) {
-        return p.identifier === id;
-      })[0];
-    }
-    function dragstart(id, position, move, end) {
+    function dragstart(id, position, subject, move, end) {
       return function() {
-        var target = this, parent = target.parentNode, event_ = event.of(target, arguments), eventTarget = d3.event.target, eventId = id(), drag = eventId == null ? "drag" : "drag-" + eventId, origin_ = position(parent, eventId), dragged = 0, offset, w = d3.select(d3_window).on(move + "." + drag, moved).on(end + "." + drag, ended), dragRestore = d3_event_dragSuppress();
+        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);
         if (origin) {
-          offset = origin.apply(target, arguments);
-          offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
+          dragOffset = origin.apply(that, arguments);
+          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
         } else {
-          offset = [ 0, 0 ];
+          dragOffset = [ 0, 0 ];
         }
-        event_({
+        dispatch({
           type: "dragstart"
         });
         function moved() {
-          var p = position(parent, eventId), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
+          var position1 = position(parent, dragId), dx, dy;
+          if (!position1) return;
+          dx = position1[0] - position0[0];
+          dy = position1[1] - position0[1];
           dragged |= dx | dy;
-          origin_ = p;
-          event_({
+          position0 = position1;
+          dispatch({
             type: "drag",
-            x: p[0] + offset[0],
-            y: p[1] + offset[1],
+            x: position1[0] + dragOffset[0],
+            y: position1[1] + dragOffset[1],
             dx: dx,
             dy: dy
           });
         }
         function ended() {
-          w.on(move + "." + drag, null).on(end + "." + drag, null);
-          dragRestore(dragged && d3.event.target === eventTarget);
-          event_({
+          if (!position(parent, dragId)) return;
+          dragSubject.on(move + dragName, null).on(end + dragName, null);
+          dragRestore(dragged && d3.event.target === target);
+          dispatch({
             type: "dragend"
           });
         }
@@ -1175,6 +1173,15 @@
     };
     return d3.rebind(drag, event, "on");
   };
+  function d3_behavior_dragTouchId() {
+    return d3.event.changedTouches[0].identifier;
+  }
+  function d3_behavior_dragTouchSubject() {
+    return d3.event.target;
+  }
+  function d3_behavior_dragMouseSubject() {
+    return d3_window;
+  }
   var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;
   function d3_sgn(x) {
     return x > 0 ? 1 : x < 0 ? -1 : 0;
@@ -1220,13 +1227,13 @@
       x: 0,
       y: 0,
       k: 1
-    }, translate0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
+    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
     function zoom(g) {
-      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on(mousemove, mousewheelreset).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
+      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
     }
     zoom.event = function(g) {
       g.each(function() {
-        var event_ = event.of(this, arguments), view1 = view;
+        var dispatch = event.of(this, arguments), view1 = view;
         if (d3_transitionInheritId) {
           d3.select(this).transition().each("start.zoom", function() {
             view = this.__chart__ || {
@@ -1234,7 +1241,7 @@
               y: 0,
               k: 1
             };
-            zoomstarted(event_);
+            zoomstarted(dispatch);
           }).tween("zoom:zoom", function() {
             var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
             return function(t) {
@@ -1244,16 +1251,16 @@
                 y: cy - l[1] * k,
                 k: k
               };
-              zoomed(event_);
+              zoomed(dispatch);
             };
           }).each("end.zoom", function() {
-            zoomended(event_);
+            zoomended(dispatch);
           });
         } else {
           this.__chart__ = view;
-          zoomstarted(event_);
-          zoomed(event_);
-          zoomended(event_);
+          zoomstarted(dispatch);
+          zoomed(dispatch);
+          zoomended(dispatch);
         }
       });
     };
@@ -1336,46 +1343,46 @@
         return (y - view.y) / view.k;
       }).map(y0.invert));
     }
-    function zoomstarted(event) {
-      event({
+    function zoomstarted(dispatch) {
+      dispatch({
         type: "zoomstart"
       });
     }
-    function zoomed(event) {
+    function zoomed(dispatch) {
       rescale();
-      event({
+      dispatch({
         type: "zoom",
         scale: view.k,
         translate: [ view.x, view.y ]
       });
     }
-    function zoomended(event) {
-      event({
+    function zoomended(dispatch) {
+      dispatch({
         type: "zoomend"
       });
     }
     function mousedowned() {
-      var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, dragged = 0, w = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), l = location(d3.mouse(target)), dragRestore = d3_event_dragSuppress();
-      d3_selection_interrupt.call(target);
-      zoomstarted(event_);
+      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      zoomstarted(dispatch);
       function moved() {
         dragged = 1;
-        translateTo(d3.mouse(target), l);
-        zoomed(event_);
+        translateTo(d3.mouse(that), location0);
+        zoomed(dispatch);
       }
       function ended() {
-        w.on(mousemove, d3_window === target ? mousewheelreset : null).on(mouseup, null);
-        dragRestore(dragged && d3.event.target === eventTarget);
-        zoomended(event_);
+        subject.on(mousemove, null).on(mouseup, null);
+        dragRestore(dragged && d3.event.target === target);
+        zoomended(dispatch);
       }
     }
     function touchstarted() {
-      var target = this, event_ = event.of(target, arguments), locations0 = {}, distance0 = 0, scale0, eventId = d3.event.changedTouches[0].identifier, touchmove = "touchmove.zoom-" + eventId, touchend = "touchend.zoom-" + eventId, w = d3.select(d3_window).on(touchmove, moved).on(touchend, ended), t = d3.select(target).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress();
-      d3_selection_interrupt.call(target);
+      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
       started();
-      zoomstarted(event_);
+      zoomstarted(dispatch);
       function relocate() {
-        var touches = d3.touches(target);
+        var touches = d3.touches(that);
         scale0 = view.k;
         touches.forEach(function(t) {
           if (t.identifier in locations0) locations0[t.identifier] = location(t);
@@ -1383,6 +1390,9 @@
         return touches;
       }
       function started() {
+        var target = d3.event.target;
+        d3.select(target).on(touchmove, moved).on(touchend, ended);
+        targets.push(target);
         var changed = d3.event.changedTouches;
         for (var i = 0, n = changed.length; i < n; ++i) {
           locations0[changed[i].identifier] = null;
@@ -1394,7 +1404,7 @@
             scaleTo(view.k * 2);
             translateTo(p, l);
             d3_eventPreventDefault();
-            zoomed(event_);
+            zoomed(dispatch);
           }
           touchtime = now;
         } else if (touches.length > 1) {
@@ -1403,7 +1413,7 @@
         }
       }
       function moved() {
-        var touches = d3.touches(target), p0, l0, p1, l1;
+        var touches = d3.touches(that), p0, l0, p1, l1;
         for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
           p1 = touches[i];
           if (l1 = locations0[p1.identifier]) {
@@ -1419,7 +1429,7 @@
         }
         touchtime = null;
         translateTo(p0, l0);
-        zoomed(event_);
+        zoomed(dispatch);
       }
       function ended() {
         if (d3.event.touches.length) {
@@ -1431,37 +1441,32 @@
             return void relocate();
           }
         }
-        w.on(touchmove, null).on(touchend, null);
-        t.on(mousedown, mousedowned).on(touchstart, touchstarted);
+        d3.selectAll(targets).on(zoomName, null);
+        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
         dragRestore();
-        zoomended(event_);
+        zoomended(dispatch);
       }
     }
     function mousewheeled() {
-      var event_ = event.of(this, arguments);
-      if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), 
-      zoomstarted(event_);
+      var dispatch = event.of(this, arguments);
+      if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), 
+      d3_selection_interrupt.call(this), zoomstarted(dispatch);
       mousewheelTimer = setTimeout(function() {
         mousewheelTimer = null;
-        zoomended(event_);
+        zoomended(dispatch);
       }, 50);
       d3_eventPreventDefault();
-      var point = center || d3.mouse(this);
-      if (!translate0) translate0 = location(point);
       scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
-      translateTo(point, translate0);
-      zoomed(event_);
-    }
-    function mousewheelreset() {
-      translate0 = null;
+      translateTo(center0, translate0);
+      zoomed(dispatch);
     }
     function dblclicked() {
-      var event_ = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
-      zoomstarted(event_);
+      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
+      zoomstarted(dispatch);
       scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
       translateTo(p, l);
-      zoomed(event_);
-      zoomended(event_);
+      zoomed(dispatch);
+      zoomended(dispatch);
     }
     return d3.rebind(zoom, event, "on");
   };
@@ -1473,29 +1478,23 @@
   }, "mousewheel") : (d3_behavior_zoomDelta = function() {
     return -d3.event.detail;
   }, "MozMousePixelScroll");
-  function d3_Color() {}
-  d3_Color.prototype.toString = function() {
+  d3.color = d3_color;
+  function d3_color() {}
+  d3_color.prototype.toString = function() {
     return this.rgb() + "";
   };
-  d3.hsl = function(h, s, l) {
-    return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
-  };
+  d3.hsl = d3_hsl;
   function d3_hsl(h, s, l) {
-    return new d3_Hsl(h, s, l);
-  }
-  function d3_Hsl(h, s, l) {
-    this.h = h;
-    this.s = s;
-    this.l = l;
+    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
   }
-  var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
+  var d3_hslPrototype = d3_hsl.prototype = new d3_color();
   d3_hslPrototype.brighter = function(k) {
     k = Math.pow(.7, arguments.length ? k : 1);
-    return d3_hsl(this.h, this.s, this.l / k);
+    return new d3_hsl(this.h, this.s, this.l / k);
   };
   d3_hslPrototype.darker = function(k) {
     k = Math.pow(.7, arguments.length ? k : 1);
-    return d3_hsl(this.h, this.s, k * this.l);
+    return new d3_hsl(this.h, this.s, k * this.l);
   };
   d3_hslPrototype.rgb = function() {
     return d3_hsl_rgb(this.h, this.s, this.l);
@@ -1517,25 +1516,18 @@
     function vv(h) {
       return Math.round(v(h) * 255);
     }
-    return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
   }
-  d3.hcl = function(h, c, l) {
-    return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);
-  };
+  d3.hcl = d3_hcl;
   function d3_hcl(h, c, l) {
-    return new d3_Hcl(h, c, l);
-  }
-  function d3_Hcl(h, c, l) {
-    this.h = h;
-    this.c = c;
-    this.l = l;
+    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
   }
-  var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
+  var d3_hclPrototype = d3_hcl.prototype = new d3_color();
   d3_hclPrototype.brighter = function(k) {
-    return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
   };
   d3_hclPrototype.darker = function(k) {
-    return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
   };
   d3_hclPrototype.rgb = function() {
     return d3_hcl_lab(this.h, this.c, this.l).rgb();
@@ -1543,27 +1535,20 @@
   function d3_hcl_lab(h, c, l) {
     if (isNaN(h)) h = 0;
     if (isNaN(c)) c = 0;
-    return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
   }
-  d3.lab = function(l, a, b) {
-    return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
-  };
+  d3.lab = d3_lab;
   function d3_lab(l, a, b) {
-    return new d3_Lab(l, a, b);
-  }
-  function d3_Lab(l, a, b) {
-    this.l = l;
-    this.a = a;
-    this.b = b;
+    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
   }
   var d3_lab_K = 18;
   var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
-  var d3_labPrototype = d3_Lab.prototype = new d3_Color();
+  var d3_labPrototype = d3_lab.prototype = new d3_color();
   d3_labPrototype.brighter = function(k) {
-    return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
   };
   d3_labPrototype.darker = function(k) {
-    return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
   };
   d3_labPrototype.rgb = function() {
     return d3_lab_rgb(this.l, this.a, this.b);
@@ -1573,10 +1558,10 @@
     x = d3_lab_xyz(x) * d3_lab_X;
     y = d3_lab_xyz(y) * d3_lab_Y;
     z = d3_lab_xyz(z) * d3_lab_Z;
-    return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
   }
   function d3_lab_hcl(l, a, b) {
-    return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l);
+    return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
   }
   function d3_lab_xyz(x) {
     return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
@@ -1587,36 +1572,29 @@
   function d3_xyz_rgb(r) {
     return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
   }
-  d3.rgb = function(r, g, b) {
-    return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
-  };
+  d3.rgb = d3_rgb;
+  function d3_rgb(r, g, b) {
+    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
+  }
   function d3_rgbNumber(value) {
-    return d3_rgb(value >> 16, value >> 8 & 255, value & 255);
+    return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
   }
   function d3_rgbString(value) {
     return d3_rgbNumber(value) + "";
   }
-  function d3_rgb(r, g, b) {
-    return new d3_Rgb(r, g, b);
-  }
-  function d3_Rgb(r, g, b) {
-    this.r = r;
-    this.g = g;
-    this.b = b;
-  }
-  var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();
+  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
   d3_rgbPrototype.brighter = function(k) {
     k = Math.pow(.7, arguments.length ? k : 1);
     var r = this.r, g = this.g, b = this.b, i = 30;
-    if (!r && !g && !b) return d3_rgb(i, i, i);
+    if (!r && !g && !b) return new d3_rgb(i, i, i);
     if (r && r < i) r = i;
     if (g && g < i) g = i;
     if (b && b < i) b = i;
-    return d3_rgb(Math.min(255, ~~(r / k)), Math.min(255, ~~(g / k)), Math.min(255, ~~(b / k)));
+    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
   };
   d3_rgbPrototype.darker = function(k) {
     k = Math.pow(.7, arguments.length ? k : 1);
-    return d3_rgb(~~(k * this.r), ~~(k * this.g), ~~(k * this.b));
+    return new d3_rgb(k * this.r, k * this.g, k * this.b);
   };
   d3_rgbPrototype.hsl = function() {
     return d3_rgb_hsl(this.r, this.g, this.b);
@@ -1628,7 +1606,7 @@
     return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
   }
   function d3_rgb_parse(format, rgb, hsl) {
-    var r = 0, g = 0, b = 0, m1, m2, name;
+    var r = 0, g = 0, b = 0, m1, m2, color;
     m1 = /([a-z]+)\((.*)\)/i.exec(format);
     if (m1) {
       m2 = m1[2].split(",");
@@ -1644,23 +1622,20 @@
         }
       }
     }
-    if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
-    if (format != null && format.charAt(0) === "#") {
+    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);
+    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.substring(1), 16))) {
       if (format.length === 4) {
-        r = format.charAt(1);
-        r += r;
-        g = format.charAt(2);
-        g += g;
-        b = format.charAt(3);
-        b += b;
+        r = (color & 3840) >> 4;
+        r = r >> 4 | r;
+        g = color & 240;
+        g = g >> 4 | g;
+        b = color & 15;
+        b = b << 4 | b;
       } else if (format.length === 7) {
-        r = format.substring(1, 3);
-        g = format.substring(3, 5);
-        b = format.substring(5, 7);
+        r = (color & 16711680) >> 16;
+        g = (color & 65280) >> 8;
+        b = color & 255;
       }
-      r = parseInt(r, 16);
-      g = parseInt(g, 16);
-      b = parseInt(b, 16);
     }
     return rgb(r, g, b);
   }
@@ -1674,7 +1649,7 @@
       h = NaN;
       s = l > 0 && l < 1 ? 0 : h;
     }
-    return d3_hsl(h, s, l);
+    return new d3_hsl(h, s, l);
   }
   function d3_rgb_lab(r, g, b) {
     r = d3_rgb_xyz(r);
@@ -2043,6 +2018,14 @@
   };
   d3.csv = d3.dsv(",", "text/csv");
   d3.tsv = d3.dsv("	", "text/tab-separated-values");
+  d3.touch = function(container, touches, identifier) {
+    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
+    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
+      if ((touch = touches[i]).identifier === identifier) {
+        return d3_mousePoint(container, touch);
+      }
+    }
+  };
   var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) {
     setTimeout(callback, 17);
   };
@@ -2116,7 +2099,7 @@
       if (value < 0) value *= -1;
       if (precision) value = d3.round(value, d3_format_precision(value, precision));
       i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
-      i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
+      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
     }
     return d3_formatPrefixes[8 + i / 3];
   };
@@ -2678,7 +2661,7 @@
     return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
   }
   function d3_time_parseZone(date, string, i) {
-    return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = +string, 
+    return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = -string, 
     i + 5) : -1;
   }
   function d3_time_expandYear(d) {
@@ -3227,7 +3210,6 @@
           clip.lineEnd = ringEnd;
           segments = [];
           polygon = [];
-          listener.polygonStart();
         },
         polygonEnd: function() {
           clip.point = point;
@@ -3236,13 +3218,15 @@
           segments = d3.merge(segments);
           var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
           if (segments.length) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
             d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
           } else if (clipStartInside) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
             listener.lineStart();
             interpolate(null, null, 1, listener);
             listener.lineEnd();
           }
-          listener.polygonEnd();
+          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
           segments = polygon = null;
         },
         sphere: function() {
@@ -3270,7 +3254,7 @@
         line.lineEnd();
       }
       var segments;
-      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygon, ring;
+      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
       function pointRing(λ, φ) {
         ring.push([ λ, φ ]);
         var point = rotate(λ, φ);
@@ -3291,9 +3275,12 @@
         if (clean & 1) {
           segment = ringSegments[0];
           var n = segment.length - 1, i = -1, point;
-          listener.lineStart();
-          while (++i < n) listener.point((point = segment[i])[0], point[1]);
-          listener.lineEnd();
+          if (n > 0) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+            listener.lineStart();
+            while (++i < n) listener.point((point = segment[i])[0], point[1]);
+            listener.lineEnd();
+          }
           return;
         }
         if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
@@ -4598,7 +4585,12 @@
     }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
     if (!n) return d3_geo_mercator;
     function forward(λ, φ) {
-      var ρ = abs(abs(φ) - halfπ) < ε ? 0 : F / Math.pow(t(φ), n);
+      if (F > 0) {
+        if (φ < -halfπ + ε) φ = -halfπ + ε;
+      } else {
+        if (φ > halfπ - ε) φ = halfπ - ε;
+      }
+      var ρ = F / Math.pow(t(φ), n);
       return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
     }
     forward.invert = function(x, y) {
@@ -4688,13 +4680,13 @@
   (d3.geo.transverseMercator = function() {
     var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
     projection.center = function(_) {
-      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ -_[1], _[0] ]);
+      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
     };
     projection.rotate = function(_) {
       return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
       [ _[0], _[1], _[2] - 90 ]);
     };
-    return projection.rotate([ 0, 0 ]);
+    return rotate([ 0, 0, 90 ]);
   }).raw = d3_geo_transverseMercator;
   d3.geom = {};
   function d3_geom_pointX(d) {
@@ -5615,71 +5607,38 @@
   }
   d3.interpolateString = d3_interpolateString;
   function d3_interpolateString(a, b) {
-    var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
+    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
     a = a + "", b = b + "";
-    d3_interpolate_number.lastIndex = 0;
-    for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
-      if (m.index) s.push(b.substring(s0, s1 = m.index));
-      q.push({
-        i: s.length,
-        x: m[0]
-      });
-      s.push(null);
-      s0 = d3_interpolate_number.lastIndex;
-    }
-    if (s0 < b.length) s.push(b.substring(s0));
-    for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
-      o = q[i];
-      if (o.x == m[0]) {
-        if (o.i) {
-          if (s[o.i + 1] == null) {
-            s[o.i - 1] += o.x;
-            s.splice(o.i, 1);
-            for (j = i + 1; j < n; ++j) q[j].i--;
-          } else {
-            s[o.i - 1] += o.x + s[o.i + 1];
-            s.splice(o.i, 2);
-            for (j = i + 1; j < n; ++j) q[j].i -= 2;
-          }
-        } else {
-          if (s[o.i + 1] == null) {
-            s[o.i] = o.x;
-          } else {
-            s[o.i] = o.x + s[o.i + 1];
-            s.splice(o.i + 1, 1);
-            for (j = i + 1; j < n; ++j) q[j].i--;
-          }
-        }
-        q.splice(i, 1);
-        n--;
-        i--;
-      } else {
-        o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
+    while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
+      if ((bs = bm.index) > bi) {
+        bs = b.substring(bi, bs);
+        if (s[i]) s[i] += bs; else s[++i] = bs;
       }
-    }
-    while (i < n) {
-      o = q.pop();
-      if (s[o.i + 1] == null) {
-        s[o.i] = o.x;
+      if ((am = am[0]) === (bm = bm[0])) {
+        if (s[i]) s[i] += bm; else s[++i] = bm;
       } else {
-        s[o.i] = o.x + s[o.i + 1];
-        s.splice(o.i + 1, 1);
+        s[++i] = null;
+        q.push({
+          i: i,
+          x: d3_interpolateNumber(am, bm)
+        });
       }
-      n--;
+      bi = d3_interpolate_numberB.lastIndex;
     }
-    if (s.length === 1) {
-      return s[0] == null ? (o = q[0].x, function(t) {
-        return o(t) + "";
-      }) : function() {
-        return b;
-      };
+    if (bi < b.length) {
+      bs = b.substring(bi);
+      if (s[i]) s[i] += bs; else s[++i] = bs;
     }
-    return function(t) {
-      for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
+    return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
+      return b(t) + "";
+    }) : function() {
+      return b;
+    } : (b = q.length, function(t) {
+      for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
       return s.join("");
-    };
+    });
   }
-  var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
+  var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
   d3.interpolate = d3_interpolate;
   function d3_interpolate(a, b) {
     var i = d3.interpolators.length, f;
@@ -5688,7 +5647,7 @@
   }
   d3.interpolators = [ function(a, b) {
     var t = typeof b;
-    return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_Color ? d3_interpolateRgb : t === "object" ? Array.isArray(b) ? d3_interpolateArray : d3_interpolateObject : d3_interpolateNumber)(a, b);
+    return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
   } ];
   d3.interpolateArray = d3_interpolateArray;
   function d3_interpolateArray(a, b) {
@@ -6359,41 +6318,30 @@
   var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
   d3.layout.hierarchy = function() {
     var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
-    function recurse(node, depth, nodes) {
-      var childs = children.call(hierarchy, node, depth);
-      node.depth = depth;
-      nodes.push(node);
-      if (childs && (n = childs.length)) {
-        var i = -1, n, c = node.children = new Array(n), v = 0, j = depth + 1, d;
-        while (++i < n) {
-          d = c[i] = recurse(childs[i], j, nodes);
-          d.parent = node;
-          v += d.value;
-        }
-        if (sort) c.sort(sort);
-        if (value) node.value = v;
-      } else {
-        delete node.children;
-        if (value) {
-          node.value = +value.call(hierarchy, node, depth) || 0;
+    function hierarchy(root) {
+      var stack = [ root ], nodes = [], node;
+      root.depth = 0;
+      while ((node = stack.pop()) != null) {
+        nodes.push(node);
+        if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
+          var n, childs, child;
+          while (--n >= 0) {
+            stack.push(child = childs[n]);
+            child.parent = node;
+            child.depth = node.depth + 1;
+          }
+          if (value) node.value = 0;
+          node.children = childs;
+        } else {
+          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
+          delete node.children;
         }
       }
-      return node;
-    }
-    function revalue(node, depth) {
-      var children = node.children, v = 0;
-      if (children && (n = children.length)) {
-        var i = -1, n, j = depth + 1;
-        while (++i < n) v += revalue(children[i], j);
-      } else if (value) {
-        v = +value.call(hierarchy, node, depth) || 0;
-      }
-      if (value) node.value = v;
-      return v;
-    }
-    function hierarchy(d) {
-      var nodes = [];
-      recurse(d, 0, nodes);
+      d3_layout_hierarchyVisitAfter(root, function(node) {
+        var childs, parent;
+        if (sort && (childs = node.children)) childs.sort(sort);
+        if (value && (parent = node.parent)) parent.value += node.value;
+      });
       return nodes;
     }
     hierarchy.sort = function(x) {
@@ -6412,7 +6360,16 @@
       return hierarchy;
     };
     hierarchy.revalue = function(root) {
-      revalue(root, 0);
+      if (value) {
+        d3_layout_hierarchyVisitBefore(root, function(node) {
+          if (node.children) node.value = 0;
+        });
+        d3_layout_hierarchyVisitAfter(root, function(node) {
+          var parent;
+          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
+          if (parent = node.parent) parent.value += node.value;
+        });
+      }
       return root;
     };
     return hierarchy;
@@ -6423,6 +6380,29 @@
     object.links = d3_layout_hierarchyLinks;
     return object;
   }
+  function d3_layout_hierarchyVisitBefore(node, callback) {
+    var nodes = [ node ];
+    while ((node = nodes.pop()) != null) {
+      callback(node);
+      if ((children = node.children) && (n = children.length)) {
+        var n, children;
+        while (--n >= 0) nodes.push(children[n]);
+      }
+    }
+  }
+  function d3_layout_hierarchyVisitAfter(node, callback) {
+    var nodes = [ node ], nodes2 = [];
+    while ((node = nodes.pop()) != null) {
+      nodes2.push(node);
+      if ((children = node.children) && (n = children.length)) {
+        var i = -1, n, children;
+        while (++i < n) nodes.push(children[i]);
+      }
+    }
+    while ((node = nodes2.pop()) != null) {
+      callback(node);
+    }
+  }
   function d3_layout_hierarchyChildren(d) {
     return d.children;
   }
@@ -6738,185 +6718,6 @@
   function d3_layout_histogramRange(values) {
     return [ d3.min(values), d3.max(values) ];
   }
-  d3.layout.tree = function() {
-    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
-    function tree(d, i) {
-      var nodes = hierarchy.call(this, d, i), root = nodes[0];
-      function firstWalk(node, previousSibling) {
-        var children = node.children, layout = node._tree;
-        if (children && (n = children.length)) {
-          var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
-          while (++i < n) {
-            child = children[i];
-            firstWalk(child, previousChild);
-            ancestor = apportion(child, previousChild, ancestor);
-            previousChild = child;
-          }
-          d3_layout_treeShift(node);
-          var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
-          if (previousSibling) {
-            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
-            layout.mod = layout.prelim - midpoint;
-          } else {
-            layout.prelim = midpoint;
-          }
-        } else {
-          if (previousSibling) {
-            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
-          }
-        }
-      }
-      function secondWalk(node, x) {
-        node.x = node._tree.prelim + x;
-        var children = node.children;
-        if (children && (n = children.length)) {
-          var i = -1, n;
-          x += node._tree.mod;
-          while (++i < n) {
-            secondWalk(children[i], x);
-          }
-        }
-      }
-      function apportion(node, previousSibling, ancestor) {
-        if (previousSibling) {
-          var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
-          while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
-            vom = d3_layout_treeLeft(vom);
-            vop = d3_layout_treeRight(vop);
-            vop._tree.ancestor = node;
-            shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
-            if (shift > 0) {
-              d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
-              sip += shift;
-              sop += shift;
-            }
-            sim += vim._tree.mod;
-            sip += vip._tree.mod;
-            som += vom._tree.mod;
-            sop += vop._tree.mod;
-          }
-          if (vim && !d3_layout_treeRight(vop)) {
-            vop._tree.thread = vim;
-            vop._tree.mod += sim - sop;
-          }
-          if (vip && !d3_layout_treeLeft(vom)) {
-            vom._tree.thread = vip;
-            vom._tree.mod += sip - som;
-            ancestor = node;
-          }
-        }
-        return ancestor;
-      }
-      d3_layout_treeVisitAfter(root, function(node, previousSibling) {
-        node._tree = {
-          ancestor: node,
-          prelim: 0,
-          mod: 0,
-          change: 0,
-          shift: 0,
-          number: previousSibling ? previousSibling._tree.number + 1 : 0
-        };
-      });
-      firstWalk(root);
-      secondWalk(root, -root._tree.prelim);
-      var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
-      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
-        node.x *= size[0];
-        node.y = node.depth * size[1];
-        delete node._tree;
-      } : function(node) {
-        node.x = (node.x - x0) / (x1 - x0) * size[0];
-        node.y = node.depth / y1 * size[1];
-        delete node._tree;
-      });
-      return nodes;
-    }
-    tree.separation = function(x) {
-      if (!arguments.length) return separation;
-      separation = x;
-      return tree;
-    };
-    tree.size = function(x) {
-      if (!arguments.length) return nodeSize ? null : size;
-      nodeSize = (size = x) == null;
-      return tree;
-    };
-    tree.nodeSize = function(x) {
-      if (!arguments.length) return nodeSize ? size : null;
-      nodeSize = (size = x) != null;
-      return tree;
-    };
-    return d3_layout_hierarchyRebind(tree, hierarchy);
-  };
-  function d3_layout_treeSeparation(a, b) {
-    return a.parent == b.parent ? 1 : 2;
-  }
-  function d3_layout_treeLeft(node) {
-    var children = node.children;
-    return children && children.length ? children[0] : node._tree.thread;
-  }
-  function d3_layout_treeRight(node) {
-    var children = node.children, n;
-    return children && (n = children.length) ? children[n - 1] : node._tree.thread;
-  }
-  function d3_layout_treeSearch(node, compare) {
-    var children = node.children;
-    if (children && (n = children.length)) {
-      var child, n, i = -1;
-      while (++i < n) {
-        if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
-          node = child;
-        }
-      }
-    }
-    return node;
-  }
-  function d3_layout_treeRightmost(a, b) {
-    return a.x - b.x;
-  }
-  function d3_layout_treeLeftmost(a, b) {
-    return b.x - a.x;
-  }
-  function d3_layout_treeDeepest(a, b) {
-    return a.depth - b.depth;
-  }
-  function d3_layout_treeVisitAfter(node, callback) {
-    function visit(node, previousSibling) {
-      var children = node.children;
-      if (children && (n = children.length)) {
-        var child, previousChild = null, i = -1, n;
-        while (++i < n) {
-          child = children[i];
-          visit(child, previousChild);
-          previousChild = child;
-        }
-      }
-      callback(node, previousSibling);
-    }
-    visit(node, null);
-  }
-  function d3_layout_treeShift(node) {
-    var shift = 0, change = 0, children = node.children, i = children.length, child;
-    while (--i >= 0) {
-      child = children[i]._tree;
-      child.prelim += shift;
-      child.mod += shift;
-      shift += child.shift + (change += child.change);
-    }
-  }
-  function d3_layout_treeMove(ancestor, node, shift) {
-    ancestor = ancestor._tree;
-    node = node._tree;
-    var change = shift / (node.number - ancestor.number);
-    ancestor.change += change;
-    node.change -= change;
-    node.shift += shift;
-    node.prelim += shift;
-    node.mod += shift;
-  }
-  function d3_layout_treeAncestor(vim, node, ancestor) {
-    return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
-  }
   d3.layout.pack = function() {
     var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
     function pack(d, i) {
@@ -6924,17 +6725,17 @@
         return radius;
       };
       root.x = root.y = 0;
-      d3_layout_treeVisitAfter(root, function(d) {
+      d3_layout_hierarchyVisitAfter(root, function(d) {
         d.r = +r(d.value);
       });
-      d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
       if (padding) {
         var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
-        d3_layout_treeVisitAfter(root, function(d) {
+        d3_layout_hierarchyVisitAfter(root, function(d) {
           d.r += dr;
         });
-        d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
-        d3_layout_treeVisitAfter(root, function(d) {
+        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
+        d3_layout_hierarchyVisitAfter(root, function(d) {
           d.r -= dr;
         });
       }
@@ -7071,11 +6872,158 @@
       c.y = a.y;
     }
   }
+  d3.layout.tree = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
+    function tree(d, i) {
+      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
+      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
+      d3_layout_hierarchyVisitBefore(root1, secondWalk);
+      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
+        var left = root0, right = root0, bottom = root0;
+        d3_layout_hierarchyVisitBefore(root0, function(node) {
+          if (node.x < left.x) left = node;
+          if (node.x > right.x) right = node;
+          if (node.depth > bottom.depth) bottom = node;
+        });
+        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
+        d3_layout_hierarchyVisitBefore(root0, function(node) {
+          node.x = (node.x + tx) * kx;
+          node.y = node.depth * ky;
+        });
+      }
+      return nodes;
+    }
+    function wrapTree(root0) {
+      var root1 = {
+        A: null,
+        children: [ root0 ]
+      }, queue = [ root1 ], node1;
+      while ((node1 = queue.pop()) != null) {
+        for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
+          queue.push((children[i] = child = {
+            _: children[i],
+            parent: node1,
+            children: (child = children[i].children) && child.slice() || [],
+            A: null,
+            a: null,
+            z: 0,
+            m: 0,
+            c: 0,
+            s: 0,
+            t: null,
+            i: i
+          }).a = child);
+        }
+      }
+      return root1.children[0];
+    }
+    function firstWalk(v) {
+      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
+      if (children.length) {
+        d3_layout_treeShift(v);
+        var midpoint = (children[0].z + children[children.length - 1].z) / 2;
+        if (w) {
+          v.z = w.z + separation(v._, w._);
+          v.m = v.z - midpoint;
+        } else {
+          v.z = midpoint;
+        }
+      } else if (w) {
+        v.z = w.z + separation(v._, w._);
+      }
+      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
+    }
+    function secondWalk(v) {
+      v._.x = v.z + v.parent.m;
+      v.m += v.parent.m;
+    }
+    function apportion(v, w, ancestor) {
+      if (w) {
+        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
+        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
+          vom = d3_layout_treeLeft(vom);
+          vop = d3_layout_treeRight(vop);
+          vop.a = v;
+          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
+          if (shift > 0) {
+            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
+            sip += shift;
+            sop += shift;
+          }
+          sim += vim.m;
+          sip += vip.m;
+          som += vom.m;
+          sop += vop.m;
+        }
+        if (vim && !d3_layout_treeRight(vop)) {
+          vop.t = vim;
+          vop.m += sim - sop;
+        }
+        if (vip && !d3_layout_treeLeft(vom)) {
+          vom.t = vip;
+          vom.m += sip - som;
+          ancestor = v;
+        }
+      }
+      return ancestor;
+    }
+    function sizeNode(node) {
+      node.x *= size[0];
+      node.y = node.depth * size[1];
+    }
+    tree.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return tree;
+    };
+    tree.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null ? sizeNode : null;
+      return tree;
+    };
+    tree.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) == null ? null : sizeNode;
+      return tree;
+    };
+    return d3_layout_hierarchyRebind(tree, hierarchy);
+  };
+  function d3_layout_treeSeparation(a, b) {
+    return a.parent == b.parent ? 1 : 2;
+  }
+  function d3_layout_treeLeft(v) {
+    var children = v.children;
+    return children.length ? children[0] : v.t;
+  }
+  function d3_layout_treeRight(v) {
+    var children = v.children, n;
+    return (n = children.length) ? children[n - 1] : v.t;
+  }
+  function d3_layout_treeMove(wm, wp, shift) {
+    var change = shift / (wp.i - wm.i);
+    wp.c -= change;
+    wp.s += shift;
+    wm.c += change;
+    wp.z += shift;
+    wp.m += shift;
+  }
+  function d3_layout_treeShift(v) {
+    var shift = 0, change = 0, children = v.children, i = children.length, w;
+    while (--i >= 0) {
+      w = children[i];
+      w.z += shift;
+      w.m += shift;
+      shift += w.s + (change += w.c);
+    }
+  }
+  function d3_layout_treeAncestor(vim, v, ancestor) {
+    return vim.a.parent === v.parent ? vim.a : ancestor;
+  }
   d3.layout.cluster = function() {
     var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
     function cluster(d, i) {
       var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
-      d3_layout_treeVisitAfter(root, function(node) {
+      d3_layout_hierarchyVisitAfter(root, function(node) {
         var children = node.children;
         if (children && children.length) {
           node.x = d3_layout_clusterX(children);
@@ -7087,7 +7035,7 @@
         }
       });
       var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
-      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
+      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
         node.x = (node.x - root.x) * size[0];
         node.y = (root.y - node.y) * size[1];
       } : function(node) {
@@ -7466,9 +7414,24 @@
   }
   function d3_scale_linearTickFormat(domain, m, format) {
     var range = d3_scale_linearTickRange(domain, m);
-    return d3.format(format ? format.replace(d3_format_re, function(a, b, c, d, e, f, g, h, i, j) {
-      return [ b, c, d, e, f, g, h, i || "." + d3_scale_linearFormatPrecision(j, range), j ].join("");
-    }) : ",." + d3_scale_linearPrecision(range[2]) + "f");
+    if (format) {
+      var match = d3_format_re.exec(format);
+      match.shift();
+      if (match[8] === "s") {
+        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
+        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
+        match[8] = "f";
+        format = d3.format(match.join(""));
+        return function(d) {
+          return format(prefix.scale(d)) + prefix.symbol;
+        };
+      }
+      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
+      format = match.join("");
+    } else {
+      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
+    }
+    return d3.format(format);
   }
   var d3_scale_linearFormatSignificant = {
     s: 1,
@@ -7482,7 +7445,7 @@
   }
   function d3_scale_linearFormatPrecision(type, range) {
     var p = d3_scale_linearPrecision(range[2]);
-    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(Math.abs(range[0]), Math.abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
+    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
   }
   d3.scale.log = function() {
     return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
@@ -7610,7 +7573,7 @@
   function d3_scale_ordinal(domain, ranger) {
     var index, range, rangeBand;
     function scale(x) {
-      return range[((index.get(x) || ranger.t === "range" && index.set(x, domain.push(x))) - 1) % range.length];
+      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
     }
     function steps(start, step) {
       return d3.range(domain.length).map(function(i) {
@@ -7715,9 +7678,7 @@
     }
     scale.domain = function(x) {
       if (!arguments.length) return domain;
-      domain = x.filter(function(d) {
-        return !isNaN(d);
-      }).sort(d3.ascending);
+      domain = x.filter(d3_number).sort(d3_ascending);
       return rescale();
     };
     scale.range = function(x) {
@@ -8558,6 +8519,7 @@
   };
   d3_transitionPrototype.delay = function(value) {
     var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].delay;
     return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
       node.__transition__[id].delay = +value.call(node, node.__data__, i, j);
     } : (value = +value, function(node) {
@@ -8566,6 +8528,7 @@
   };
   d3_transitionPrototype.duration = function(value) {
     var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].duration;
     return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
       node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));
     } : (value = Math.max(1, value), function(node) {
@@ -8664,7 +8627,7 @@
       g.each(function() {
         var g = d3.select(this);
         var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
-        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
+        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickTransform;
         var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
         d3.transition(path));
         tickEnter.append("line");
@@ -9214,7 +9177,7 @@
   } ], [ "%Y", d3_true ] ]);
   var d3_time_scaleMilliseconds = {
     range: function(start, stop, step) {
-      return d3.range(+start, +stop, step).map(d3_time_scaleDate);
+      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
     },
     floor: d3_identity,
     ceil: d3_identity
@@ -9265,11 +9228,7 @@
   d3.xml = d3_xhrType(function(request) {
     return request.responseXML;
   });
-  if (typeof define === "function" && define.amd) {
-    define(d3);
-  } else if (typeof module === "object" && module.exports) {
-    module.exports = d3;
-  } else {
-    this.d3 = d3;
-  }
-}();
\ No newline at end of file
+  if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3;
+  this.d3 = d3;
+}();
+


[10/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Remove comments


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 4c4308dc5d726f73f7c1494b35a0129967ad4791
Parents: 53ae8ee
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Aug 12 15:59:04 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:49:56 2014 +0200

----------------------------------------------------------------------
 app/core/base.js | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4c4308dc/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index e1f5331..b9d0f7f 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -62,8 +62,6 @@ function(Backbone, LayoutManager) {
     manage: true,
     disableLoader: false,
 
-    // Either tests or source are expecting synchronous renders, so disable
-    // asynchronous rendering improvements.
     useRAF: true,
 
     forceRender: function () {


[09/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Refactored Layout and View, upgraded to latest LM

The Layout object was a simple wrapper over the Layout constructor
instead of extending the constructor itself.  I've patched this to make
it more consistent and removed duplicative methods.  I've also removed
the tests for `removeView` since that is now a built-in method.

The latest LM contains bugfixes and render performance updates that
unforuntately have to be opt-out.  Areas in the source or tests that are
expecting synchronous renders must be patched to work asynchronously to
take advantage.


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 3d1dd842bdc1f69c59e9cf3bb0d2eeb00e3b73f6
Parents: b7fc5f4
Author: Tim Branyen <ti...@tabdeveloper.com>
Authored: Fri Aug 1 10:18:13 2014 -0400
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:49:56 2014 +0200

----------------------------------------------------------------------
 app/core/base.js                            |   4 +
 app/core/layout.js                          |  77 ++------
 app/core/tests/layoutSpec.js                |  38 +---
 assets/js/plugins/backbone.layoutmanager.js | 240 ++++++++++++++++++-----
 4 files changed, 217 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/3d1dd842/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 15499b3..9fbb7a0 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -62,6 +62,10 @@ function(Backbone, LayoutManager) {
     manage: true,
     disableLoader: false,
 
+    // Either tests or source are expecting synchronous renders, so disable
+    // asynchronous rendering improvements.
+    useRAF: false,
+
     forceRender: function () {
       this.hasRendered = false;
     }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/3d1dd842/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
index ff339c7..0a45e62 100644
--- a/app/core/layout.js
+++ b/app/core/layout.js
@@ -10,82 +10,31 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-define([
-  "backbone", 
-  "plugins/backbone.layoutmanager"
-], function(Backbone) {
+define(function(require, exports, module) {
+  var Backbone = require("backbone");
+  var LayoutManager = require("plugins/backbone.layoutmanager");
 
-  // 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",
-    });
+  var Layout = Backbone.Layout.extend({
+    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();
-    },
+    // Either tests or source are expecting synchronous renders, so disable
+    // asynchronous rendering improvements.
+    useRAF: false,
 
     setTemplate: function(template) {
       if (template.prefix){
-        this.layout.template = template.prefix + template.name;
+        this.template = template.prefix + template.name;
       } else{
-        this.layout.template = "templates/layouts/" + template;
+        this.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.removeView();
       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;
+  module.exports = Layout;
 
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/3d1dd842/app/core/tests/layoutSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/layoutSpec.js b/app/core/tests/layoutSpec.js
index 40b1947..2b87173 100644
--- a/app/core/tests/layoutSpec.js
+++ b/app/core/tests/layoutSpec.js
@@ -27,24 +27,20 @@ define([
       it("Should set template without prefix", function () {
         layout.setTemplate('myTemplate');
 
-        assert.equal(layout.layout.template, 'templates/layouts/myTemplate');
+        assert.equal(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');
+        assert.equal(layout.template, 'myPrefix/myTemplate');
       });
 
       it("Should remove old views", function () {
-        var view = {
-          remove: function () {}
-        };
+        var view = new FauxtonAPI.Layout();
 
-        layout.layoutViews = {
-          'selector': view
-        };
+        layout.setView('selector', view);
 
         var mockRemove = sinon.spy(view, 'remove');
         layout.setTemplate('myTemplate');
@@ -62,31 +58,5 @@ define([
       });
 
     });
-
-    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/3d1dd842/assets/js/plugins/backbone.layoutmanager.js
----------------------------------------------------------------------
diff --git a/assets/js/plugins/backbone.layoutmanager.js b/assets/js/plugins/backbone.layoutmanager.js
index c5d4a80..e20bf5a 100644
--- a/assets/js/plugins/backbone.layoutmanager.js
+++ b/assets/js/plugins/backbone.layoutmanager.js
@@ -1,22 +1,35 @@
 /*!
- * backbone.layoutmanager.js v0.9.4
+ * backbone.layoutmanager.js v0.9.5
  * Copyright 2013, Tim Branyen (@tbranyen)
  * backbone.layoutmanager.js may be freely distributed under the MIT license.
  */
 (function(window, factory) {
   "use strict";
-  var Backbone = window.Backbone;
 
   // AMD. Register as an anonymous module.  Wrap in function so we have access
   // to root via `this`.
   if (typeof define === "function" && define.amd) {
-    return define(["backbone", "underscore", "jquery"], function() {
+    define(["backbone", "underscore", "jquery"], function() {
       return factory.apply(window, arguments);
     });
   }
 
+  // Node. Does not work with strict CommonJS, but only CommonJS-like
+  // environments that support module.exports, like Node.
+  else if (typeof exports === "object") {
+    var Backbone = require("backbone");
+    var _ = require("underscore");
+    // In a browserify build, since this is the entry point, Backbone.$
+    // is not bound. Ensure that it is.
+    Backbone.$ = Backbone.$ || require("jquery");
+
+    module.exports = factory.call(window, Backbone, _, Backbone.$);
+  }
+
   // Browser globals.
-  Backbone.Layout = factory.call(window, Backbone, window._, Backbone.$);
+  else {
+    factory.call(window, window.Backbone, window._, window.Backbone.$);
+  }
 }(typeof global === "object" ? global : this, function (Backbone, _, $) {
 "use strict";
 
@@ -236,20 +249,33 @@ var LayoutManager = Backbone.View.extend({
     return this.__manager__.renderDeferred.promise();
   },
 
+  // Proxy `then` for easier invocation.
+  then: function() {
+    return this.promise().then.apply(this, arguments);
+  },
+
   // Sometimes it's desirable to only render the child views under the parent.
   // This is typical for a layout that does not change.  This method will
-  // iterate over the child Views and aggregate all child render promises and
-  // return the parent View.  The internal `promise()` method will return the
-  // aggregate promise that resolves once all children have completed their
-  // render.
-  renderViews: function() {
+  // iterate over the provided views or delegate to `getViews` to fetch child
+  // Views and aggregate all render promises and return the parent View.
+  // The internal `promise()` method will return the aggregate promise that
+  // resolves once all children have completed their render.
+  renderViews: function(views) {
     var root = this;
     var manager = root.__manager__;
     var newDeferred = root.deferred();
 
+    // If the caller provided an array of views then render those, otherwise
+    // delegate to getViews.
+    if (views && _.isArray(views)) {
+      views = _.chain(views);
+    } else {
+      views = root.getViews(views);
+    }
+
     // Collect all promises from rendering the child views and wait till they
     // all complete.
-    var promises = root.getViews().map(function(view) {
+    var promises = views.map(function(view) {
       return view.render().__manager__.renderDeferred;
     }).value();
 
@@ -392,16 +418,12 @@ var LayoutManager = Backbone.View.extend({
     // Code path is less complex for Views that are not being inserted.  Simply
     // remove existing Views and bail out with the assignment.
     if (!insert) {
-      // If the View we are adding has already been rendered, simply inject it
-      // into the parent.
-      if (view.hasRendered) {
-        // Apply the partial.
-        view.partial(root.$el, view.$el, root.__manager__, manager);
+      // Ensure remove is called only when swapping in a new view (when the
+      // view is the same, it does not need to be removed or cleaned up).
+      if (root.getView(name) !== view) {
+        root.removeView(name);
       }
 
-      // Ensure remove is called when swapping View's.
-      root.removeView(name);
-
       // Assign to main views object and return for chainability.
       return root.views[selector] = view;
     }
@@ -450,7 +472,6 @@ var LayoutManager = Backbone.View.extend({
 
     // Triggered once the render has succeeded.
     function resolve() {
-      var next;
 
       // Insert all subViews into the parent at once.
       _.each(root.views, function(views, selector) {
@@ -465,8 +486,7 @@ var LayoutManager = Backbone.View.extend({
       if (parent && !manager.insertedViaFragment) {
         if (!root.contains(parent.el, root.el)) {
           // Apply the partial using parent's html() method.
-          parent.partial(parent.$el, root.$el, rentManager,
-            manager);
+          parent.partial(parent.$el, root.$el, rentManager, manager);
         }
       }
 
@@ -475,21 +495,24 @@ var LayoutManager = Backbone.View.extend({
 
       // Set this View as successfully rendered.
       root.hasRendered = true;
+      manager.renderInProgress = false;
+
+      // Clear triggeredByRAF flag.
+      delete manager.triggeredByRAF;
 
       // Only process the queue if it exists.
-      if (next = manager.queue.shift()) {
+      if (manager.queue && manager.queue.length) {
         // Ensure that the next render is only called after all other
         // `done` handlers have completed.  This will prevent `render`
         // callbacks from firing out of order.
-        next();
+        (manager.queue.shift())();
       } else {
         // Once the queue is depleted, remove it, the render process has
         // completed.
         delete manager.queue;
       }
 
-      // Reusable function for triggering the afterRender callback and event
-      // and setting the hasRendered flag.
+      // Reusable function for triggering the afterRender callback and event.
       function completeRender() {
         var console = window.console;
         var afterRender = root.afterRender;
@@ -520,10 +543,10 @@ var LayoutManager = Backbone.View.extend({
 
       // If the parent is currently rendering, wait until it has completed
       // until calling the nested View's `afterRender`.
-      if (rentManager && rentManager.queue) {
+      if (rentManager && (rentManager.renderInProgress || rentManager.queue)) {
         // Wait until the parent View has finished rendering, which could be
         // asynchronous, and trigger afterRender on this View once it has
-        // compeleted.
+        // completed.
         parent.once("afterRender", completeRender);
       } else {
         // This View and its parent have both rendered.
@@ -574,23 +597,21 @@ var LayoutManager = Backbone.View.extend({
       });
     }
 
-    // Another render is currently happening if there is an existing queue, so
-    // push a closure to render later into the queue.
-    if (manager.queue) {
-      aPush.call(manager.queue, actuallyRender);
-    } else {
-      manager.queue = [];
+    // Mark this render as in progress. This will prevent
+    // afterRender from being fired until the entire chain has rendered.
+    manager.renderInProgress = true;
 
-      // This the first `render`, preceeding the `queue` so render
-      // immediately.
-      actuallyRender(root, def);
-    }
+    // Start the render.
+    // Register this request & cancel any that conflict.
+    root._registerWithRAF(actuallyRender, def);
 
     // Put the deferred inside of the `__manager__` object, since we don't want
     // end users accessing this directly anymore in favor of the `afterRender`
     // event.  So instead of doing `render().then(...` do
     // `render().once("afterRender", ...`.
-    root.__manager__.renderDeferred = def;
+    // FIXME: I think we need to move back to promises so that we don't
+    // miss events, regardless of sync/async (useRAF setting)
+    manager.renderDeferred = def;
 
     // Return the actual View for chainability purposes.
     return root;
@@ -603,6 +624,75 @@ var LayoutManager = Backbone.View.extend({
 
     // Call the original remove function.
     return this._remove.apply(this, arguments);
+  },
+
+  // Register a view render with RAF.
+  _registerWithRAF: function(callback, deferred) {
+    var root = this;
+    var manager = root.__manager__;
+    var rentManager = manager.parent && manager.parent.__manager__;
+
+    // Allow RAF processing to be shut off using `useRAF`:false.
+    if (this.useRAF === false) {
+      if (manager.queue) {
+        aPush.call(manager.queue, callback);
+      } else {
+        manager.queue = [];
+        callback();
+      }
+      return;
+    }
+
+    // Keep track of all deferreds so we can resolve them.
+    manager.deferreds = manager.deferreds || [];
+    manager.deferreds.push(deferred);
+
+    // Schedule resolving all deferreds that are waiting.
+    deferred.done(resolveDeferreds);
+
+    // Cancel any other renders on this view that are queued to execute.
+    this._cancelQueuedRAFRender();
+
+    // Trigger immediately if the parent was triggered by RAF.
+    // The flag propagates downward so this view's children are also
+    // rendered immediately.
+    if (rentManager && rentManager.triggeredByRAF) {
+      return finish();
+    }
+
+    // Register this request with requestAnimationFrame.
+    manager.rafID = root.requestAnimationFrame(finish);
+
+    function finish() {
+      // Remove this ID as it is no longer valid.
+      manager.rafID = null;
+
+      // Set flag (will propagate to children) so they render
+      // without waiting for RAF.
+      manager.triggeredByRAF = true;
+
+      // Call original cb.
+      callback();
+    }
+
+    // Resolve all deferreds that were cancelled previously, if any.
+    // This allows the user to bind callbacks to any render callback,
+    // even if it was cancelled above.
+    function resolveDeferreds() {
+      for (var i = 0; i < manager.deferreds.length; i++){
+        manager.deferreds[i].resolveWith(root, [root]);
+      }
+      manager.deferreds = [];
+    }
+  },
+
+  // Cancel any queued render requests.
+  _cancelQueuedRAFRender: function() {
+    var root = this;
+    var manager = root.__manager__;
+    if (manager.rafID != null) {
+      root.cancelAnimationFrame(manager.rafID);
+    }
   }
 },
 
@@ -652,6 +742,9 @@ var LayoutManager = Backbone.View.extend({
       // Remove the View completely.
       view.$el.remove();
 
+      // Cancel any pending renders, if present.
+      view._cancelQueuedRAFRender();
+
       // Bail out early if no parent exists.
       if (!manager.parent) { return; }
 
@@ -735,12 +828,18 @@ var LayoutManager = Backbone.View.extend({
     if (options.suppressWarnings === true) {
       Backbone.View.prototype.suppressWarnings = true;
     }
+
+    // Allow global configuration of `useRAF`.
+    if (options.useRAF === false) {
+      Backbone.View.prototype.useRAF = false;
+    }
   },
 
   // Configure a View to work with the LayoutManager plugin.
   setupView: function(views, options) {
-    // Don't break the options object (passed into Backbone.View#initialize).
-    options = options || {};
+    // Ensure that options is always an object, and clone it so that
+    // changes to the original object don't screw up this view.
+    options = _.extend({}, options);
 
     // Set up all Views passed.
     _.each(aConcat.call([], views), function(view) {
@@ -819,14 +918,14 @@ var LayoutManager = Backbone.View.extend({
   }
 });
 
-LayoutManager.VERSION = "0.9.4";
+LayoutManager.VERSION = "0.9.5";
 
 // Expose through Backbone object.
 Backbone.Layout = LayoutManager;
 
 // Override _configure to provide extra functionality that is necessary in
 // order for the render function reference to be bound during initialize.
-Backbone.View = function(options) {
+Backbone.View.prototype.constructor = function(options) {
   var noel;
 
   // Ensure options is always an object.
@@ -854,6 +953,8 @@ Backbone.View = function(options) {
   ViewConstructor.apply(this, arguments);
 };
 
+Backbone.View = Backbone.View.prototype.constructor;
+
 // Copy over the extend method.
 Backbone.View.extend = ViewConstructor.extend;
 
@@ -865,6 +966,10 @@ var defaultOptions = {
   // Prefix template/layout paths.
   prefix: "",
 
+  // Use requestAnimationFrame to queue up view rendering and cancel
+  // repeat requests. Leave on for better performance.
+  useRAF: true,
+
   // Can be used to supply a different deferred implementation.
   deferred: function() {
     return $.Deferred();
@@ -878,7 +983,7 @@ var defaultOptions = {
 
   // By default, render using underscore's templating and trim output.
   renderTemplate: function(template, context) {
-    return trim(template(context));
+    return trim(template.call(this, context));
   },
 
   // By default, pass model attributes to the templates
@@ -964,7 +1069,54 @@ var defaultOptions = {
   // A method to determine if a View contains another.
   contains: function(parent, child) {
     return $.contains(parent, child);
-  }
+  },
+
+  // Based on:
+  // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+  // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and
+  // Tino Zijdel.
+  requestAnimationFrame: (function() {
+    var lastTime = 0;
+    var vendors = ["ms", "moz", "webkit", "o"];
+    var requestAnimationFrame = window.requestAnimationFrame;
+
+    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
+      requestAnimationFrame = window[vendors[i] + "RequestAnimationFrame"];
+    }
+
+    if (!requestAnimationFrame){
+      requestAnimationFrame = function(callback) {
+        var currTime = new Date().getTime();
+        var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+        var id = window.setTimeout(function() {
+          callback(currTime + timeToCall);
+        }, timeToCall);
+        lastTime = currTime + timeToCall;
+        return id;
+      };
+    }
+
+    return _.bind(requestAnimationFrame, window);
+  })(),
+
+  cancelAnimationFrame: (function() {
+    var vendors = ["ms", "moz", "webkit", "o"];
+    var cancelAnimationFrame = window.cancelAnimationFrame;
+
+    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
+      cancelAnimationFrame =
+        window[vendors[i] + "CancelAnimationFrame"] ||
+        window[vendors[i] + "CancelRequestAnimationFrame"];
+    }
+
+    if (!cancelAnimationFrame) {
+      cancelAnimationFrame = function(id) {
+        clearTimeout(id);
+      };
+    }
+
+    return _.bind(cancelAnimationFrame, window);
+  })()
 };
 
 // Extend LayoutManager with default options.


[06/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
remove unneeded z-index


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 79c11d768aecc14b2aebb3afc4bbc635d87f5892
Parents: 285d32e
Author: Garren Smith <ga...@gmail.com>
Authored: Wed Aug 6 16:11:46 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Wed Aug 6 16:11:46 2014 +0200

----------------------------------------------------------------------
 assets/less/fauxton.less | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/79c11d76/assets/less/fauxton.less
----------------------------------------------------------------------
diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less
index 463b1e0..10b1e78 100644
--- a/assets/less/fauxton.less
+++ b/assets/less/fauxton.less
@@ -363,7 +363,6 @@ table.databases {
         padding: 22px 0 0 18px;
         position: fixed;
         top: 0;
-        z-index: 100;
         background-color: @primaryNav;
         width: @navWidth;
         div{


[08/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Enable RAF and fix tests


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 53ae8ee367782c4ef5ef03b593dc2af0c70006ce
Parents: b82b8ed
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Aug 12 15:20:58 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:49:56 2014 +0200

----------------------------------------------------------------------
 app/addons/activetasks/tests/viewsSpec.js  | 15 ++++++++-------
 app/addons/config/tests/resourcesSpec.js   |  4 ++--
 app/addons/fauxton/tests/baseSpec.js       | 12 ++++++++----
 app/addons/fauxton/tests/filterViewSpec.js | 21 +++++++++++++--------
 app/addons/fauxton/tests/paginateSpec.js   |  4 ++--
 app/addons/permissions/tests/viewsSpec.js  | 12 ++++++------
 app/core/base.js                           |  2 +-
 app/core/layout.js                         |  2 +-
 test/mocha/testUtils.js                    |  8 ++++++--
 9 files changed, 47 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/activetasks/tests/viewsSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/activetasks/tests/viewsSpec.js b/app/addons/activetasks/tests/viewsSpec.js
index 19c5b65..8731200 100644
--- a/app/addons/activetasks/tests/viewsSpec.js
+++ b/app/addons/activetasks/tests/viewsSpec.js
@@ -27,9 +27,9 @@ define([
 
     describe("on change polling rate", function () {
       var viewSandbox;
-      beforeEach(function () {
+      beforeEach(function (done) {
         viewSandbox = new ViewSandbox();
-        viewSandbox.renderView(tabMenu);
+        viewSandbox.renderView(tabMenu, done);
       });
 
       afterEach(function () {
@@ -66,7 +66,7 @@ define([
 
     describe('on request by type', function () {
       var viewSandbox, mainView;
-      beforeEach(function () {
+      beforeEach(function (done) {
 
         mainView = new Views.View({
           collection: new Activetasks.AllTasks(),
@@ -74,8 +74,9 @@ define([
         });
 
         viewSandbox = new ViewSandbox();
-        viewSandbox.renderView(tabMenu);
-        viewSandbox.renderView(mainView);
+        viewSandbox.renderView(tabMenu).promise().then(function () {
+          viewSandbox.renderView(mainView, done);
+        });
       });
 
       afterEach(function () {
@@ -99,14 +100,14 @@ define([
 
   describe('DataSection', function () {
     var viewSandbox, mainView;
-    beforeEach(function () {
+    beforeEach(function (done) {
       mainView = new Views.View({
         collection: new Activetasks.AllTasks(),
         currentView: "all"
       });
 
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(mainView);
+      viewSandbox.renderView(mainView, done);
     });
 
     afterEach(function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/config/tests/resourcesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/config/tests/resourcesSpec.js b/app/addons/config/tests/resourcesSpec.js
index 1cc9e62..8699e36 100644
--- a/app/addons/config/tests/resourcesSpec.js
+++ b/app/addons/config/tests/resourcesSpec.js
@@ -37,9 +37,9 @@ define([
 
     describe("editing Items", function () {
       var viewSandbox;
-      beforeEach(function () {
+      beforeEach(function (done) {
         viewSandbox = new ViewSandbox();
-        viewSandbox.renderView(tabMenu);
+        viewSandbox.renderView(tabMenu, done);
       });
 
       afterEach(function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/fauxton/tests/baseSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/baseSpec.js b/app/addons/fauxton/tests/baseSpec.js
index a7ff7a1..b9814bc 100644
--- a/app/addons/fauxton/tests/baseSpec.js
+++ b/app/addons/fauxton/tests/baseSpec.js
@@ -88,15 +88,19 @@ describe('Fauxton Notifications', function () {
       delete window.fauxton_xss_test_escaped;
     });
 
-    it('should be able to render unescaped', function () {
+    it('should be able to render unescaped', function (done) {
       var view = FauxtonAPI.addNotification({
         msg: '<script>window.fauxton_xss_test_unescaped = true;</script>',
         selector: 'body',
         escape: false
       });
-      view.$el.remove();
-      assert.ok(window.fauxton_xss_test_unescaped);
-      delete window.fauxton_xss_test_unescaped;
+
+      view.promise().then(function () {
+        view.$el.remove();
+        assert.ok(window.fauxton_xss_test_unescaped);
+        delete window.fauxton_xss_test_unescaped;
+        done();
+      });
     });
 
     it('should render escaped if the escape value is not explicitly false,' +

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/fauxton/tests/filterViewSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/filterViewSpec.js b/app/addons/fauxton/tests/filterViewSpec.js
index 1eefa05..0d9e7d0 100644
--- a/app/addons/fauxton/tests/filterViewSpec.js
+++ b/app/addons/fauxton/tests/filterViewSpec.js
@@ -27,26 +27,29 @@ define([
       FauxtonAPI.router.triggerRouteEvent = function () {};
     }
 
-    beforeEach(function () {
+    beforeEach(function (done) {
       filterView = new Components.FilterView({
         eventNamespace: 'mynamespace'
       });
 
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(filterView);
+      viewSandbox.renderView(filterView, done);
     });
 
     afterEach(function () {
       viewSandbox.remove();
     });
 
-    it('should add filter markup', function () {
+    it('should add filter markup', function (done) {
       filterView.$('[name="filter"]').val('i was a lonely filter');
       filterView.$('.js-filter-form').submit();
-
       filterView.$('[name="filter"]').val('i am a filter');
       filterView.$('.js-filter-form').submit();
-      assert.equal(2, filterView.$('.js-remove-filter').length);
+
+      setTimeout(function () {
+        assert.equal(2, filterView.$('.js-remove-filter').length);
+        done();
+      }, 300);
     });
 
     it('should remove filter markup', function () {
@@ -70,13 +73,15 @@ define([
       assert.equal(0, filterView.$('.js-filter-tooltip').length);
     });
 
-    it('should add tooltips when a text for it is defined', function () {
+    it('should add tooltips when a text for it is defined', function (done) {
       filterView = new Components.FilterView({
         eventNamespace: 'mynamespace',
         tooltipText: 'ente ente'
       });
-      viewSandbox.renderView(filterView);
-      assert.equal(1, filterView.$('.js-filter-tooltip').length);
+      viewSandbox.renderView(filterView).promise().then(function () {
+        assert.equal(1, filterView.$('.js-filter-tooltip').length);
+        done();
+      });
     });
   });
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/fauxton/tests/paginateSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/paginateSpec.js b/app/addons/fauxton/tests/paginateSpec.js
index d336ea8..f97b255 100644
--- a/app/addons/fauxton/tests/paginateSpec.js
+++ b/app/addons/fauxton/tests/paginateSpec.js
@@ -22,7 +22,7 @@ define([
 
   describe('IndexPaginate', function () {
     var viewSandbox, paginate, collection, navigateMock;
-    beforeEach(function () {
+    beforeEach(function (done) {
       collection = new Models.IndexCollection([{
         id:'myId1',
         doc: 'num1'
@@ -43,7 +43,7 @@ define([
         canShowNextfn: function () { return true;}
       });
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(paginate); 
+      viewSandbox.renderView(paginate, done); 
     });
 
     afterEach(function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/addons/permissions/tests/viewsSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/permissions/tests/viewsSpec.js b/app/addons/permissions/tests/viewsSpec.js
index c22d405..147cee4 100644
--- a/app/addons/permissions/tests/viewsSpec.js
+++ b/app/addons/permissions/tests/viewsSpec.js
@@ -21,7 +21,7 @@ define([
   describe('Permission View', function () {
     var security, section, viewSandbox;
 
-    beforeEach(function () {
+    beforeEach(function (done) {
       security = new Models.Security({'admins': {
         'names': ['_user'],
         'roles': []
@@ -34,7 +34,7 @@ define([
       });
 
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(section); 
+      viewSandbox.renderView(section, done); 
     });
 
     afterEach(function () {
@@ -67,7 +67,7 @@ define([
         security,
         viewSandbox;
 
-    beforeEach(function () {
+    beforeEach(function (done) {
       security = new Models.Security({'admins': {
         'names': ['_user'],
         'roles': []
@@ -80,7 +80,7 @@ define([
       });
 
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(section); 
+      viewSandbox.renderView(section, done); 
     });
 
     afterEach(function () {
@@ -130,13 +130,13 @@ define([
     var item,
         viewSandbox;
 
-    beforeEach(function () {
+    beforeEach(function (done) {
       item = new Views.PermissionItem({
         item: '_user'
       });
 
       viewSandbox = new ViewSandbox();
-      viewSandbox.renderView(item); 
+      viewSandbox.renderView(item, done); 
     });
 
     afterEach(function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/core/base.js
----------------------------------------------------------------------
diff --git a/app/core/base.js b/app/core/base.js
index 9fbb7a0..e1f5331 100644
--- a/app/core/base.js
+++ b/app/core/base.js
@@ -64,7 +64,7 @@ function(Backbone, LayoutManager) {
 
     // Either tests or source are expecting synchronous renders, so disable
     // asynchronous rendering improvements.
-    useRAF: false,
+    useRAF: true,
 
     forceRender: function () {
       this.hasRendered = false;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
index 84fc71e..8d589e7 100644
--- a/app/core/layout.js
+++ b/app/core/layout.js
@@ -19,7 +19,7 @@ define([
   // 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",
+      template: "templates/layouts/with_sidebar"
     });
 
     this.layoutViews = {};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/53ae8ee3/test/mocha/testUtils.js
----------------------------------------------------------------------
diff --git a/test/mocha/testUtils.js b/test/mocha/testUtils.js
index 2c418f9..6b9e57f 100644
--- a/test/mocha/testUtils.js
+++ b/test/mocha/testUtils.js
@@ -29,15 +29,19 @@ function(FauxtonAPI,chai, sinonChai) {
       this.$ = this.$el.find;
     },
     views: [],
-    renderView: function (view) {
+    renderView: function (view, done) {
       this.views.push(view);
       this.$el.append(view.el);
       view.render();
+      if (done) { 
+        view.promise().done(function () { done(); });
+      }
+      return view;
     },
 
     remove: function () {
       _.each(this.views, function (view) {
-        view.remove();
+        view.removeView();
       }, this);
     }
   });


[11/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Upgrade backbone.layoutmanager

Work off Tim's initial commits and adjust to cater for the use of
establish functions in views and routeObjects.
We don't want to immediately render the view. We first want any pending
promises returned from a routeObjects establish and a view's establish
to complete before rendering the view.


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 09805dd97406b0ec11fb2af7eb2ff0983816f59f
Parents: 3d1dd84
Author: Garren Smith <ga...@gmail.com>
Authored: Mon Aug 11 12:06:21 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:49:56 2014 +0200

----------------------------------------------------------------------
 app/core/layout.js      | 84 ++++++++++++++++++++++++++++++++++++++++++--
 app/core/routeObject.js | 11 ++++--
 2 files changed, 90 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/09805dd9/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
index 0a45e62..11992cb 100644
--- a/app/core/layout.js
+++ b/app/core/layout.js
@@ -10,7 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-define(function(require, exports, module) {
+/*define(function(require, exports, module) {
   var Backbone = require("backbone");
   var LayoutManager = require("plugins/backbone.layoutmanager");
 
@@ -19,7 +19,7 @@ define(function(require, exports, module) {
 
     // Either tests or source are expecting synchronous renders, so disable
     // asynchronous rendering improvements.
-    useRAF: false,
+    useRAF: true,
 
     setTemplate: function(template) {
       if (template.prefix){
@@ -37,4 +37,84 @@ define(function(require, exports, module) {
 
   module.exports = Layout;
 
+});*/
+
+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.removeView();});
+      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;
+        }
+
+      this.layout.removeView(selector);
+      
+      if (this.layoutViews[selector]) {
+        delete this.layoutViews[selector];
+      }
+
+      return true;
+    }
+
+  });
+
+  return Layout;
+
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/09805dd9/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
index f8a238f..898afcb 100644
--- a/app/core/routeObject.js
+++ b/app/core/routeObject.js
@@ -149,12 +149,17 @@ function(FauxtonAPI, Backbone) {
     },
 
     renderViewOnLayout: function(viewInfo, resp, xhr){
-      var masterLayout = viewInfo.masterLayout;
+      var masterLayout = viewInfo.masterLayout,
+          triggerBroadcast = _.bind(this.triggerBroadcast, this);
 
       masterLayout.setView(viewInfo.selector, viewInfo.view);
-      masterLayout.renderView(viewInfo.selector);
+      var promise = masterLayout.renderView(viewInfo.selector).promise();
 
-      this.triggerBroadcast('afterRender', viewInfo.view, viewInfo.selector);
+      promise.then(function () {
+        triggerBroadcast('afterRender', viewInfo.view, viewInfo.selector);
+      });
+
+      return promise;
     },
 
     establishError: function(resp){


[02/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Add tests for documents/views-changes

Closes COUCHDB-2282


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

Branch: refs/heads/backbone.layout-upgrade
Commit: 4382f43efbf6ed435a3881a3b5323509fb77dc40
Parents: b58f613
Author: Robert Kowalski <ro...@kowalski.gd>
Authored: Tue Jul 29 20:04:46 2014 +0200
Committer: Robert Kowalski <ro...@kowalski.gd>
Committed: Fri Aug 1 18:17:28 2014 +0200

----------------------------------------------------------------------
 app/addons/documents/tests/views-changesSpec.js | 43 +++++++++++++++++++-
 1 file changed, 41 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/4382f43e/app/addons/documents/tests/views-changesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/views-changesSpec.js b/app/addons/documents/tests/views-changesSpec.js
index 4d4b2b3..94ca585 100644
--- a/app/addons/documents/tests/views-changesSpec.js
+++ b/app/addons/documents/tests/views-changesSpec.js
@@ -14,16 +14,36 @@ define([
         'addons/databases/base',
         'testUtils'
 ], function (Views, Databases, testUtils) {
-  var assert = testUtils.assert;
+  var assert = testUtils.assert,
+      ViewSandbox = testUtils.ViewSandbox,
+      viewSandbox;
 
   describe('Documents Changes', function () {
-    var filteredView;
+    var model = new Databases.Model({id: 'foo'}),
+        filteredView,
+        view,
+        handlerSpy;
+
+    model.buildChanges();
+
+    handlerSpy = sinon.spy(Views.Changes.prototype, 'toggleJson');
+
     beforeEach(function () {
       var database = new Databases.Model({id: 'bla'});
       database.buildChanges({descending: 'true', limit: '100', include_docs: 'true'} );
       filteredView = new Views.Changes({
         model: database
       });
+
+      view = new Views.Changes({
+        model: model
+      });
+      viewSandbox = new ViewSandbox();
+      viewSandbox.renderView(view);
+    });
+
+    afterEach(function () {
+      viewSandbox.remove();
     });
 
     it('filter false in case of deleted documents in the changes feed', function () {
@@ -36,5 +56,24 @@ define([
 
       assert.equal(res.length, 2);
     });
+
+    it('the toggle-json button calls a handler', function () {
+      view.$('.js-toggle-json').trigger('click');
+      assert.ok(handlerSpy.calledOnce);
+    });
+
+    it('rerenders on the sync event', function () {
+      var spy = sinon.spy(view, 'afterRender');
+      model.changes.trigger('sync');
+      view.afterRender.restore();
+      assert.ok(spy.calledOnce);
+    });
+
+    it('rerenders on the cachesync event', function () {
+      var spy = sinon.spy(view, 'afterRender');
+      model.changes.trigger('cachesync');
+      assert.ok(spy.calledOnce);
+      view.afterRender.restore();
+    });
   });
 });


[12/13] fauxton commit: updated refs/heads/backbone.layout-upgrade to 755eb7a

Posted by ga...@apache.org.
Fix failing tests and add more tests


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

Branch: refs/heads/backbone.layout-upgrade
Commit: b82b8ed50a5a6087e1e530f6fbefb9034bc9f51a
Parents: 09805dd
Author: Garren Smith <ga...@gmail.com>
Authored: Tue Aug 12 13:13:48 2014 +0200
Committer: Garren Smith <ga...@gmail.com>
Committed: Tue Aug 12 16:49:56 2014 +0200

----------------------------------------------------------------------
 app/core/layout.js                | 33 ++------------
 app/core/tests/layoutSpec.js      | 79 +++++++++++++++++++++++++++++++---
 app/core/tests/routeObjectSpec.js |  6 +++
 3 files changed, 83 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b82b8ed5/app/core/layout.js
----------------------------------------------------------------------
diff --git a/app/core/layout.js b/app/core/layout.js
index 11992cb..84fc71e 100644
--- a/app/core/layout.js
+++ b/app/core/layout.js
@@ -10,35 +10,6 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
-/*define(function(require, exports, module) {
-  var Backbone = require("backbone");
-  var LayoutManager = require("plugins/backbone.layoutmanager");
-
-  var Layout = Backbone.Layout.extend({
-    template: "templates/layouts/with_sidebar",
-
-    // Either tests or source are expecting synchronous renders, so disable
-    // asynchronous rendering improvements.
-    useRAF: true,
-
-    setTemplate: function(template) {
-      if (template.prefix){
-        this.template = template.prefix + template.name;
-      } else{
-        this.template = "templates/layouts/" + template;
-      }
-
-      // If we're changing layouts all bets are off, so kill off all the
-      // existing views in the layout.
-      this.removeView();
-      this.render();
-    }
-  });
-
-  module.exports = Layout;
-
-});*/
-
 define([
   "backbone", 
   "plugins/backbone.layoutmanager"
@@ -52,6 +23,8 @@ define([
     });
 
     this.layoutViews = {};
+    //this views don't ever get removed. An example of this is the main navigation sidebar
+    this.permanentViews = {};
     this.el = this.layout.el;
   };
 
@@ -83,6 +56,8 @@ define([
 
       if (!keep) {
         this.layoutViews[selector] = view;
+      } else {
+        this.permanentViews[selector] = view;
       }
 
       return view;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b82b8ed5/app/core/tests/layoutSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/layoutSpec.js b/app/core/tests/layoutSpec.js
index 2b87173..1ae5675 100644
--- a/app/core/tests/layoutSpec.js
+++ b/app/core/tests/layoutSpec.js
@@ -27,24 +27,24 @@ define([
       it("Should set template without prefix", function () {
         layout.setTemplate('myTemplate');
 
-        assert.equal(layout.template, 'templates/layouts/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.template, 'myPrefix/myTemplate');
+        assert.equal(layout.layout.template, 'myPrefix/myTemplate');
       });
 
       it("Should remove old views", function () {
-        var view = new FauxtonAPI.Layout();
+        var view = new FauxtonAPI.View();
 
-        layout.setView('selector', view);
+        layout.setView('#selector', view);
 
-        var mockRemove = sinon.spy(view, 'remove');
+        var removeSpy = sinon.spy(view, 'removeView');
         layout.setTemplate('myTemplate');
-        assert.ok(mockRemove.calledOnce);
+        assert.ok(removeSpy.calledOnce);
 
       });
 
@@ -58,5 +58,72 @@ define([
       });
 
     });
+
+    describe('#setView', function () {
+      var view;
+      beforeEach(function () {
+        view = new FauxtonAPI.View();
+      });
+
+      it("Should keep record of view", function () {
+        layout.setView('.selector', view);
+        assert.equal(view, layout.layoutViews['.selector']);
+      });
+
+      it("Should not keep record of view if keep is false", function () {
+        layout.setView('.selector', view, true);
+        assert.ok(_.isUndefined(layout.layoutViews['.selector']));
+        assert.equal(view, layout.permanentViews['.selector']);
+      });
+
+    });
+
+    describe('#removeView', function () {
+      var view;
+
+      beforeEach(function () {
+        view = new FauxtonAPI.View();
+        layout.setView('#selector', view);
+      });
+
+      it('Should remove view from layout', function () {
+        var removeSpy = sinon.spy(layout.layout, 'removeView');
+
+        layout.removeView('#selector');
+        assert.ok(removeSpy.calledOnce);
+      });
+
+      it('Should remove view from list of active views', function () {
+        layout.setView('#selector', view);
+        layout.removeView('#selector');
+
+        assert.ok(_.isUndefined(layout.layoutViews['#selector']));
+      });
+
+      it("should return false if view doesn't exist", function () {
+        assert.notOk(layout.removeView('#fake'));
+      });
+
+    });
+
+    describe('#renderView', function () {
+      var view;
+
+      beforeEach(function () {
+        view = new FauxtonAPI.View();
+        layout.setView('#selector', view);
+      });
+
+      it('should render view', function () {
+        var renderSpy = sinon.spy(view, 'render');
+        layout.renderView('#selector');
+        assert.ok(renderSpy.calledOnce);
+      });
+
+      it('should not render a non-existing view', function () {
+        assert.notOk(layout.renderView('#fake'));
+      });
+
+    });
   });
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b82b8ed5/app/core/tests/routeObjectSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/routeObjectSpec.js b/app/core/tests/routeObjectSpec.js
index 2fca94d..f3f4b48 100644
--- a/app/core/tests/routeObjectSpec.js
+++ b/app/core/tests/routeObjectSpec.js
@@ -71,7 +71,13 @@ define([
             viewSpy = sinon.stub(view, "establish");
         
         view.hasRendered = false;
+        view.promise = function () { 
+          var promise = $.Deferred();
+          promise.resolve();
+          return promise;
+        };
         getViewsSpy.returns({'#view': view});
+        mockLayout.renderView = function () { return view;};
 
         testRouteObject.renderWith('the-route', mockLayout, 'args');
         assert.ok(viewSpy.calledOnce, 'Should render view');