You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by de...@apache.org on 2014/07/23 21:25:11 UTC

[62/64] [abbrv] fauxton commit: updated refs/heads/secondary-indexes to ef01e24

Changed how these files are named so it's easier to read in the addon folders


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

Branch: refs/heads/secondary-indexes
Commit: 893e9881d789f3b8c621bd6148130e1327cde638
Parents: f978779
Author: deathbearbrown <de...@gmail.com>
Authored: Wed Jul 23 14:41:23 2014 -0400
Committer: deathbearbrown <de...@gmail.com>
Committed: Wed Jul 23 14:41:23 2014 -0400

----------------------------------------------------------------------
 app/addons/documents/changesviews.js       |  84 ----
 app/addons/documents/doceditorviews.js     | 416 -----------------
 app/addons/documents/indexviews.js         | 574 ------------------------
 app/addons/documents/queryoptionviews.js   | 270 -----------
 app/addons/documents/routes.js             |   6 +-
 app/addons/documents/sidebarviews.js       | 253 -----------
 app/addons/documents/views-advancedopts.js | 270 +++++++++++
 app/addons/documents/views-changes.js      |  84 ++++
 app/addons/documents/views-doceditor.js    | 416 +++++++++++++++++
 app/addons/documents/views-index.js        | 574 ++++++++++++++++++++++++
 app/addons/documents/views-sidebar.js      | 253 +++++++++++
 app/addons/documents/views.js              |   4 +-
 12 files changed, 1602 insertions(+), 1602 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/changesviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changesviews.js b/app/addons/documents/changesviews.js
deleted file mode 100644
index 2f91c21..0000000
--- a/app/addons/documents/changesviews.js
+++ /dev/null
@@ -1,84 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       "api",
-       // Libs
-       "addons/fauxton/resizeColumns",
-
-       // Plugins
-       "plugins/prettify",
-       // this should never be global available:
-       // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
-       "plugins/zeroclipboard/ZeroClipboard"
-],
-
-function(app, FauxtonAPI, resizeColumns,  prettify, ZeroClipboard) {
-
-  var Views = {};
-
-  Views.Changes = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/changes",
-
-    initialize: function () {
-      this.listenTo( this.model.changes, 'sync', this.render);
-      this.listenTo( this.model.changes, 'cachesync', this.render);
-    },
-
-    events: {
-      "click button.js-toggle-json": "toggleJson"
-    },
-
-    toggleJson: function(event) {
-      event.preventDefault();
-
-      var $button = this.$(event.target),
-          $container = $button.closest('.change-box').find(".js-json-container");
-
-      if (!$container.is(":visible")) {
-        $button
-          .text("Close JSON")
-          .addClass("btn-secondary")
-          .removeClass("btn-primary");
-      } else {
-        $button.text("View JSON")
-          .addClass("btn-primary")
-          .removeClass("btn-secondary");
-      }
-
-      $container.slideToggle();
-    },
-
-    establish: function() {
-      return [ this.model.changes.fetchOnce({prefill: true})];
-    },
-
-    serialize: function () {
-      return {
-        changes: this.model.changes.toJSON(),
-        database: this.model
-      };
-    },
-
-    afterRender: function(){
-      prettyPrint();
-      ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
-      var client = new ZeroClipboard(this.$(".js-copy"));
-    }
-  });
-
-
-
-  return Views;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/doceditorviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/doceditorviews.js b/app/addons/documents/doceditorviews.js
deleted file mode 100644
index add8d8c..0000000
--- a/app/addons/documents/doceditorviews.js
+++ /dev/null
@@ -1,416 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       "api",
-       "addons/fauxton/components",
-
-       "addons/documents/resources",
-       "addons/databases/resources",
-
-       // Libs
-       "addons/fauxton/resizeColumns",
-
-       // Plugins
-       "plugins/prettify"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases,
-         resizeColumns, prettify) {
-
-  var Views = {};
-
-  /* Attachments upload modal */
-
-  Views.UploadModal = Components.ModalView.extend({
-    template: "addons/documents/templates/upload_modal",
-
-    events: {
-      "click #upload-btn": "uploadFile"
-    },
-
-    uploadFile: function (event) {
-      event.preventDefault();
-
-      var docRev = this.model.get('_rev'),
-          that = this,
-          $form = this.$('#file-upload');
-
-      if (!docRev) {
-        return this.set_error_msg('The document needs to be saved before adding an attachment.');
-      }
-
-      if ($('input[type="file"]')[0].files.length === 0) {
-        return this.set_error_msg('Selected a file to be uploaded.');
-      }
-
-      this.$('#_rev').val(docRev);
-
-      $form.ajaxSubmit({
-        url: this.model.url(),
-        type: 'POST',
-        beforeSend: this.beforeSend,
-        uploadProgress: this.uploadProgress,
-        success: this.success,
-        error: function (resp) {
-          console.log('ERR on upload', resp);
-          return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
-        }
-      });
-    },
-
-    success: function (resp) {
-      var hideModal = this.hideModal,
-          $form = this.$('#file-upload');
-
-      FauxtonAPI.triggerRouteEvent('reRenderDoc');
-      //slight delay to make this transistion a little more fluid and less jumpy
-      setTimeout(function () {
-        $form.clearForm();
-        hideModal();
-        $('.modal-backdrop').remove();
-      }, 1000);
-    },
-
-    uploadProgress: function(event, position, total, percentComplete) {
-      this.$('.bar').css({width: percentComplete + '%'});
-    },
-
-    beforeSend: function () {
-      this.$('.progress').removeClass('hide');
-    },
-
-    _showModal: function () {
-      this.$('.bar').css({width: '0%'});
-      this.$('.progress').addClass('hide');
-    }
-  });
-
-
-
-  /* Doc Duplication modal */
-  Views.DuplicateDocModal = Components.ModalView.extend({
-    template: "addons/documents/templates/duplicate_doc_modal",
-
-    initialize: function () {
-      _.bindAll(this);
-    },
-
-    events: {
-      "click #duplicate-btn":"duplicate",
-      "submit #doc-duplicate": "duplicate"
-
-    },
-
-    duplicate: function (event) {
-      event.preventDefault();
-      var newId = this.$('#dup-id').val(),
-          isDDoc = newId.match(/^_design\//),
-          removeDDocID = newId.replace(/^_design\//,""),
-          encodedID = isDDoc? "_design/"+ app.utils.safeURLName(removeDDocID):app.utils.safeURLName(newId);
-
-      this.hideModal();
-      FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
-    },
-
-    _showModal: function () {
-      this.$('.bar').css({width: '0%'});
-      this.$('.progress').addClass('hide');
-      this.clear_error_msg();
-      this.$('.modal').modal();
-      // hack to get modal visible
-      $('.modal-backdrop').css('z-index',1025);
-    },
-
-    showModal: function () {
-      var showModal = this._showModal,
-          setDefaultIdValue = this.setDefaultIdValue,
-          uuid = new FauxtonAPI.UUID();
-
-      uuid.fetch().then(function () {
-        setDefaultIdValue(uuid.next());
-        showModal();
-      });
-    },
-
-    setDefaultIdValue: function (id) {
-      this.$('#dup-id').val(id);
-    }
-  });
-
-  /* Document editor*/
-   Views.CodeEditor = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/code_editor",
-    events: {
-      "click button.save-doc": "saveDoc",
-      "click button.delete": "destroy",
-      "click button.duplicate": "duplicate",
-      "click button.upload": "upload",
-      "click button.cancel-button": "goback"
-    },
-
-    disableLoader: true,
-
-    initialize: function (options) {
-      this.database = options.database;
-      _.bindAll(this);
-    },
-
-    goback: function(){
-      FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
-    },
-
-    destroy: function(event) {
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'This document has not been saved yet.',
-          type: 'warning',
-          clear:  true
-        });
-        return;
-      }
-
-      if (!window.confirm("Are you sure you want to delete this doc?")) {
-        return false;
-      }
-
-      var database = this.model.database;
-
-      this.model.destroy().then(function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Succesfully deleted your doc",
-          clear:  true
-        });
-        FauxtonAPI.navigate(database.url("index"));
-      }, function(resp) {
-        FauxtonAPI.addNotification({
-          msg: "Failed to delete your doc!",
-          type: "error",
-          clear:  true
-        });
-      });
-    },
-
-    beforeRender: function () {
-      this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model}));
-      this.uploadModal.render();
-
-      this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model}));
-      this.duplicateModal.render();
-    },
-
-    upload: function (event) {
-      event.preventDefault();
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'Please save the document before uploading an attachment.',
-          type: 'warning',
-          clear:  true
-        });
-        return;
-      }
-      this.uploadModal.showModal();
-    },
-
-    duplicate: function(event) {
-      if (this.model.isNewDoc()) {
-        FauxtonAPI.addNotification({
-          msg: 'Please save the document before duplicating it.',
-          type: 'warning',
-          clear:  true
-        });
-        return;
-      }
-      event.preventDefault();
-      this.duplicateModal.showModal();
-    },
-
-    updateValues: function() {
-      if (this.model.changedAttributes()) {
-        FauxtonAPI.addNotification({
-          msg: "Document saved successfully.",
-          type: "success",
-          clear: true
-        });
-        this.editor.setValue(this.model.prettyJSON());
-      }
-    },
-
-    establish: function() {
-      var promise = this.model.fetch(),
-          databaseId = this.database.safeID(),
-          deferred = $.Deferred(),
-          that = this;
-
-      promise.then(function () {
-        deferred.resolve();
-      }, function (xhr, reason, msg) {
-        if (xhr.status === 404) {
-          FauxtonAPI.addNotification({
-            msg: 'The document does not exist',
-            type: 'error',
-            clear: true
-          });
-          that.goback();
-        }
-        deferred.reject();
-     });
-
-      return deferred;
-    },
-
-    saveDoc: function(event) {
-      var json,
-      that = this,
-      editor = this.editor,
-      validDoc = this.getDocFromEditor();
-
-      if (validDoc) {
-        this.getDocFromEditor();
-
-        FauxtonAPI.addNotification({msg: "Saving document."});
-
-        this.model.save().then(function () {
-          editor.editSaved();
-          FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
-        }).fail(function(xhr) {
-          var responseText = JSON.parse(xhr.responseText).reason;
-          FauxtonAPI.addNotification({
-            msg: "Save failed: " + responseText,
-            type: "error",
-            fade: false,
-            clear: true,
-            selector: "#doc .errors-container"
-          });
-        });
-      } else if(this.model.validationError && this.model.validationError === 'Cannot change a documents id.') {
-          FauxtonAPI.addNotification({
-            msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
-            type: "error",
-            selector: "#doc .errors-container",
-            clear:  true
-          });
-        delete this.model.validationError;
-      } else {
-        FauxtonAPI.addNotification({
-          msg: "Please fix the JSON errors and try again.",
-          type: "error",
-          selector: "#doc .errors-container",
-          clear:  true
-        });
-      }
-    },
-
-    getDocFromEditor: function () {
-      var json;
-
-      if (!this.hasValidCode()) {
-        return false;
-      }
-
-      json = JSON.parse(this.editor.getValue());
-
-      this.model.clear().set(json, {validate: true});
-      if (this.model.validationError) {
-        return false;
-      }
-
-      return this.model;
-    },
-
-    hasValidCode: function() {
-      var errors = this.editor.getAnnotations();
-      return errors.length === 0;
-    },
-
-    serialize: function() {
-      return {
-        doc: this.model,
-        attachments: this.getAttachments()
-      };
-    },
-
-    getAttachments: function () {
-      var attachments = this.model.get('_attachments');
-
-      if (!attachments) { return false; }
-
-      return _.map(attachments, function (att, key) {
-        return {
-          fileName: key,
-          size: att.length,
-          contentType: att.content_type,
-          url: this.model.url() + '/' + app.utils.safeURLName(key)
-        };
-      }, this);
-    },
-
-    afterRender: function() {
-      var saveDoc = this.saveDoc,
-          editor,
-          model;
-
-      this.editor = new Components.Editor({
-        editorId: "editor-container",
-        forceMissingId: true,
-        commands: [{
-          name: 'save',
-          bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
-          exec: function(editor) {
-            saveDoc();
-          },
-          readOnly: true // false if this command should not apply in readOnly mode
-        }]
-      });
-      this.editor.render();
-
-      editor = this.editor;
-      model = this.model;
-
-      this.listenTo(this.model, "sync", this.updateValues);
-      this.listenTo(editor.editor, "change", function (event) {
-        var changedDoc;
-        try {
-          changedDoc = JSON.parse(editor.getValue());
-        } catch(exception) {
-          //not complete doc. Cannot work with it
-          return;
-        }
-
-        var keyChecked = ["_id"];
-        if (model.get("_rev")) { keyChecked.push("_rev");}
-
-        //check the changedDoc has all the required standard keys
-        if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; }
-
-        editor.setReadOnly(true);
-        setTimeout(function () { editor.setReadOnly(false);}, 400);
-        // use extend so that _id stays at the top of the object with displaying the doc
-        changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc);
-        editor.setValue(JSON.stringify(changedDoc, null, "  "));
-        FauxtonAPI.addNotification({
-          type: "error",
-          msg: "Cannot remove a documents Id or Revision.",
-          clear:  true
-        });
-      });
-    },
-
-    cleanup: function () {
-      if (this.editor) this.editor.remove();
-    }
-  });
-
-  return Views;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/indexviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/indexviews.js b/app/addons/documents/indexviews.js
deleted file mode 100644
index df8c10d..0000000
--- a/app/addons/documents/indexviews.js
+++ /dev/null
@@ -1,574 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-  "app",
-
-  "api",
-  "addons/fauxton/components",
-
-  "addons/documents/resources",
-  "addons/databases/resources",
-  "addons/pouchdb/base",
-  //views
-  "addons/documents/queryoptionviews",
-  // Libs
-  "addons/fauxton/resizeColumns",
-
-  // Plugins
-  "plugins/beautify",
-  "plugins/prettify"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases, pouchdb,
-         QueryOptions, resizeColumns, beautify, prettify) {
-
-  var Views = {};
-
-  Views.ViewEditor = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/view_editor",
-    builtinReduces: ['_sum', '_count', '_stats'],
-
-    events: {
-      "click button.save": "saveView",
-      "click button.delete": "deleteView",
-      "change select#reduce-function-selector": "updateReduce",
-      "click button.preview": "previewView",
-      "click #db-views-tabs-nav": 'toggleIndexNav',
-      "click .beautify_map":  "beautifyCode",
-      "click .beautify_reduce":  "beautifyCode",
-      "click #query-options-wrapper": 'toggleIndexNav'
-    },
-
-    langTemplates: {
-      "javascript": {
-        map: "function(doc) {\n  emit(doc._id, 1);\n}",
-        reduce: "function(keys, values, rereduce){\n  if (rereduce){\n    return sum(values);\n  } else {\n    return values.length;\n  }\n}"
-      }
-    },
-
-    defaultLang: "javascript",
-
-    initialize: function(options) {
-      this.newView = options.newView || false;
-      this.ddocs = options.ddocs;
-      this.params = options.params;
-      this.database = options.database;
-      this.currentDdoc = options.currentddoc;
-      if (this.newView) {
-        this.viewName = 'newView';
-      } else {
-        this.ddocID = options.ddocInfo.id;
-        this.viewName = options.viewName;
-        this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
-      }
-
-      this.showIndex = false;
-      _.bindAll(this);
-    },
-
-    establish: function () {
-      if (this.ddocInfo) {
-        return this.ddocInfo.fetch();
-      }
-    },
-
-    updateValues: function() {
-      var notification;
-      if (this.model.changedAttributes()) {
-        notification = FauxtonAPI.addNotification({
-          msg: "Document saved successfully.",
-          type: "success",
-          clear: true
-        });
-        this.editor.setValue(this.model.prettyJSON());
-      }
-    },
-
-    updateReduce: function(event) {
-      var $ele = $("#reduce-function-selector");
-      var $reduceContainer = $(".control-group.reduce-function");
-      if ($ele.val() == "CUSTOM") {
-        this.createReduceEditor();
-        this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
-        $reduceContainer.show();
-      } else {
-        $reduceContainer.hide();
-      }
-    },
-
-    deleteView: function (event) {
-      event.preventDefault();
-
-      if (this.newView) { return alert('Cannot delete a new view.'); }
-      if (!confirm('Are you sure you want to delete this view?')) {return;}
-
-      var that = this,
-          promise,
-          viewName = this.$('#index-name').val(),
-          ddocName = this.$('#ddoc :selected').val(),
-          ddoc = this.getCurrentDesignDoc();
-
-      ddoc.removeDdocView(viewName);
-
-      if (ddoc.hasViews()) {
-        promise = ddoc.save();
-      } else {
-        promise = ddoc.destroy();
-      }
-
-      promise.then(function () {
-        FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
-        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
-      });
-    },
-
-    saveView: function(event) {
-      var json, notification,
-      that = this;
-
-      if (event) { event.preventDefault();}
-
-      $('#dashboard-content').scrollTop(0); //scroll up
-
-      if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
-        var mapVal = this.mapEditor.getValue(),
-        reduceVal = this.reduceVal(),
-        viewName = this.$('#index-name').val(),
-        ddoc = this.getCurrentDesignDoc(),
-        ddocName = ddoc.id,
-        viewNameChange = false;
-
-        if (this.viewName !== viewName) {
-          ddoc.removeDdocView(this.viewName);
-          this.viewName = viewName;
-          viewNameChange = true;
-        }
-
-        notification = FauxtonAPI.addNotification({
-          msg: "Saving document.",
-          selector: "#define-view .errors-container",
-          clear: true
-        });
-
-        ddoc.setDdocView(viewName, mapVal, reduceVal);
-
-        ddoc.save().then(function () {
-          that.ddocs.add(ddoc);
-
-          that.mapEditor.editSaved();
-          that.reduceEditor && that.reduceEditor.editSaved();
-
-
-          FauxtonAPI.addNotification({
-            msg: "View has been saved.",
-            type: "success",
-            selector: "#define-view .errors-container",
-            clear: true
-          });
-
-          if (that.newView || viewNameChange) {
-            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName);
-
-            FauxtonAPI.navigate(fragment, {trigger: false});
-            that.newView = false;
-            that.ddocID = ddoc.safeID();
-            that.viewName = viewName;
-            that.ddocInfo = ddoc;
-            that.showIndex = true;
-            that.render();
-            FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
-              selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName)
-            });
-          }
-
-          if (that.reduceFunStr !== reduceVal) {
-            that.reduceFunStr = reduceVal;
-            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce());
-          }
-
-          FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
-
-        }, function(xhr) {
-          var responseText = JSON.parse(xhr.responseText).reason;
-          notification = FauxtonAPI.addNotification({
-            msg: "Save failed: " + responseText,
-            type: "error",
-            clear: true
-          });
-        });
-      } else {
-        var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
-        notification = FauxtonAPI.addNotification({
-          msg: errormessage,
-          type: "error",
-          selector: "#define-view .errors-container",
-          clear: true
-        });
-      }
-    },
-
-    updateView: function(event, paramInfo) {
-       event.preventDefault();
-
-       if (this.newView) { return alert('Please save this new view before querying it.'); }
-
-       var errorParams = paramInfo.errorParams,
-           params = paramInfo.params;
-
-       if (_.any(errorParams)) {
-         _.map(errorParams, function(param) {
-
-           // TODO: Where to add this error?
-           // bootstrap wants the error on a control-group div, but we're not using that
-           //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
-           return FauxtonAPI.addNotification({
-             msg: "JSON Parse Error on field: "+param.name,
-             type: "error",
-             selector: ".advanced-options .errors-container",
-             clear: true
-           });
-         });
-         FauxtonAPI.addNotification({
-           msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
-           type: "warning",
-           selector: ".advanced-options .errors-container",
-           clear: true
-         });
-
-         return false;
-      }
-
-       var fragment = window.location.hash.replace(/\?.*$/, '');
-       if (!_.isEmpty(params)) {
-        fragment = fragment + '?' + $.param(params);
-       }
-
-       FauxtonAPI.navigate(fragment, {trigger: false});
-       FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
-    },
-
-
-    previewView: function(event, paramsInfo) {
-      event.preventDefault();
-      var that = this,
-      mapVal = this.mapVal(),
-      reduceVal = this.reduceVal(),
-      paramsArr = [];
-
-      if (paramsInfo && paramsInfo.params) {
-        paramsArr = paramsInfo.params;
-      }
-
-      var params = _.reduce(paramsArr, function (params, param) {
-        params[param.name] = param.value;
-        return params;
-      }, {reduce: false});
-
-      FauxtonAPI.addNotification({
-        msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
-        type: "warning",
-        selector: ".advanced-options .errors-container",
-        fade: true,
-        escape: false // beware of possible XSS when the message changes
-      });
-
-      var promise = FauxtonAPI.Deferred();
-
-      if (!this.database.allDocs || this.database.allDocs.params.include_docs !== true) {
-        this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
-        promise = this.database.allDocs.fetch();
-       } else {
-        promise.resolve();
-       }
-
-      promise.then(function () {
-        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');});
-        var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
-        queryPromise.then(function (results) {
-          FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
-        });
-      });
-    },
-
-    getCurrentDesignDoc: function () {
-      return this.designDocSelector.getCurrentDesignDoc();
-    },
-
-    isCustomReduceEnabled: function() {
-      return $("#reduce-function-selector").val() == "CUSTOM";
-    },
-
-    mapVal: function () {
-      if (this.mapEditor) {
-        return this.mapEditor.getValue();
-      }
-
-      return this.$('#map-function').text();
-    },
-
-    reduceVal: function() {
-      var reduceOption = this.$('#reduce-function-selector :selected').val(),
-      reduceVal = "";
-
-      if (reduceOption === 'CUSTOM') {
-        if (!this.reduceEditor) { this.createReduceEditor(); }
-        reduceVal = this.reduceEditor.getValue();
-      } else if ( reduceOption !== 'NONE') {
-        reduceVal = reduceOption;
-      }
-
-      return reduceVal;
-    },
-
-
-    hasValidCode: function() {
-      return _.every(["mapEditor", "reduceEditor"], function(editorName) {
-        var editor = this[editorName];
-        if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
-          return true;
-        }
-        return editor.hadValidCode();
-      }, this);
-    },
-
-    toggleIndexNav: function (event) {
-      $('#dashboard-content').scrollTop(0); //scroll up
-
-      var $targetId = this.$(event.target).attr('id'),
-          $previousTab = this.$(this.$('li.active a').attr('href')),
-          $targetTab = this.$(this.$(event.target).attr('href'));
-
-      if ($targetTab.attr('id') !== $previousTab.attr('id')) {
-        $previousTab.removeAttr('style');
-      }
-
-      if ($targetId === 'index-nav') {
-        if (this.newView) { return; }
-        var that = this;
-        $('#dashboard-content').scrollTop(0); //scroll up
-        $targetTab.toggle('slow', function(){
-           that.showEditors();
-        });
-      } else {
-        $targetTab.toggle('slow');
-      }
-    },
-
-    serialize: function() {
-      return {
-        ddocs: this.ddocs,
-        ddoc: this.model,
-        ddocName: this.model.id,
-        viewName: this.viewName,
-        reduceFunStr: this.reduceFunStr,
-        isCustomReduce: this.hasCustomReduce(),
-        newView: this.newView,
-        langTemplates: this.langTemplates.javascript
-      };
-    },
-
-    hasCustomReduce: function() {
-      return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
-    },
-
-    hasReduce: function () {
-      return this.reduceFunStr || false;
-    },
-
-    createReduceEditor: function () {
-      if (this.reduceEditor) {
-        this.reduceEditor.remove();
-      }
-
-      this.reduceEditor = new Components.Editor({
-        editorId: "reduce-function",
-        mode: "javascript",
-        couchJSHINT: true
-      });
-      this.reduceEditor.render();
-
-      if (this.reduceEditor.getLines() === 1){
-        this.$('.beautify_reduce').removeClass("hide");
-        $('.beautify-tooltip').tooltip();
-      }
-    },
-    beforeRender: function () {
-
-      if (this.newView) {
-        this.reduceFunStr = '';
-        if (this.ddocs.length === 0) {
-          this.model = new Documents.Doc(null, {database: this.database});
-        } else {
-          this.model = this.ddocs.first().dDocModel();
-        }
-        this.ddocID = this.model.id;
-      } else {
-        var ddocDecode = decodeURIComponent(this.ddocID);
-        this.model = this.ddocs.get(this.ddocID).dDocModel();
-        this.reduceFunStr = this.model.viewHasReduce(this.viewName);
-      }
-
-      var viewFilters = FauxtonAPI.getExtensions('sidebar:viewFilters'),
-          filteredModels = this.ddocs.models,
-          designDocs = this.ddocs.clone();
-
-      if (!_.isEmpty(viewFilters)) {
-        _.each(viewFilters, function (filter) {
-          filteredModels = _.filter(filteredModels, filter);
-        });
-        designDocs.reset(filteredModels, {silent: true});
-      }
-
-      this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
-        collection: designDocs,
-        ddocName: this.currentDdoc || this.model.id,
-        database: this.database
-      }));
-
-      if (!this.newView) {
-        this.eventer = _.extend({}, Backbone.Events);
-
-        this.advancedOptions = this.insertView('#query', new QueryOptions.AdvancedOptions({
-          updateViewFn: this.updateView,
-          previewFn: this.previewView,
-          database: this.database,
-          viewName: this.viewName,
-          ddocName: this.model.id,
-          hasReduce: this.hasReduce(),
-          eventer: this.eventer,
-          showStale: true
-        }));
-      }
-
-    },
-
-    afterRender: function() {
-
-      if (this.params && !this.newView) {
-        this.advancedOptions.updateFromParams(this.params);
-      }
-
-      this.designDocSelector.updateDesignDoc();
-      if (this.newView || this.showIndex) {
-        this.showEditors();
-        this.showIndex = false;
-      } else {
-        this.$('#index').hide();
-        this.$('#index-nav').parent().removeClass('active');
-      }
-
-    },
-
-    showEditors: function () {
-      this.mapEditor = new Components.Editor({
-        editorId: "map-function",
-        mode: "javascript",
-        couchJSHINT: true
-      });
-      this.mapEditor.render();
-
-      if (this.hasCustomReduce()) {
-        this.createReduceEditor();
-      } else {
-        $(".control-group.reduce-function").hide();
-      }
-
-      if (this.newView) {
-        this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
-        //Use a built in view by default
-        //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
-      }
-
-      this.mapEditor.editSaved();
-      this.reduceEditor && this.reduceEditor.editSaved();
-
-      if (this.mapEditor.getLines() === 1){
-        this.$('.beautify_map').removeClass("hide");
-        $('.beautify-tooltip').tooltip();
-      }
-    },
-    beautifyCode: function(e){
-      e.preventDefault();
-      var targetEditor = $(e.currentTarget).hasClass('beautify_reduce')?this.reduceEditor:this.mapEditor;
-      var beautifiedCode = beautify(targetEditor.getValue());
-      targetEditor.setValue(beautifiedCode);
-    },
-    cleanup: function () {
-      this.mapEditor && this.mapEditor.remove();
-      this.reduceEditor && this.reduceEditor.remove();
-    }
-  });
-
-  Views.DesignDocSelector = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/design_doc_selector",
-
-    events: {
-      "change select#ddoc": "updateDesignDoc"
-    },
-
-    initialize: function (options) {
-      this.ddocName = options.ddocName;
-      this.database = options.database;
-      this.listenTo(this.collection, 'add', this.ddocAdded);
-      this.DocModel = options.DocModel || Documents.Doc;
-    },
-
-    ddocAdded: function (ddoc) {
-      this.ddocName = ddoc.id;
-      this.render();
-    },
-
-    serialize: function () {
-      return {
-        ddocName: this.ddocName,
-        ddocs: this.collection
-      };
-    },
-
-    updateDesignDoc: function () {
-      if (this.newDesignDoc()) {
-        this.$('#new-ddoc-section').show();
-      } else {
-        this.$('#new-ddoc-section').hide();
-      }
-    },
-
-    newDesignDoc: function () {
-
-      return this.$('#ddoc').val() === 'new-doc';
-    },
-
-    newDocValidation: function(){
-      return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
-    },
-    getCurrentDesignDoc: function () {
-      if (this.newDesignDoc()) {
-        var doc = {
-          _id: '_design/' + this.$('#new-ddoc').val(),
-          views: {},
-          language: "javascript"
-        };
-        var ddoc = new this.DocModel(doc, {database: this.database});
-        //this.collection.add(ddoc);
-        return ddoc;
-      } else if ( !this.newDesignDoc() ) {
-        var ddocName = this.$('#ddoc').val();
-        return this.collection.find(function (ddoc) {
-          return ddoc.id === ddocName;
-        }).dDocModel();
-      }
-    }
-  });
-
-  return Views;
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/queryoptionviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/queryoptionviews.js b/app/addons/documents/queryoptionviews.js
deleted file mode 100644
index b2e1af5..0000000
--- a/app/addons/documents/queryoptionviews.js
+++ /dev/null
@@ -1,270 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-       "api",
-       // Libs
-       "addons/fauxton/resizeColumns",
-],
-
-function(app, FauxtonAPI, resizeColumns ) {
-
-  var Views = {};
-
-  Views.AdvancedOptions = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/advanced_options",
-    className: "advanced-options well",
-
-    initialize: function (options) {
-      this.database = options.database;
-      this.ddocName = options.ddocName;
-      this.viewName = options.viewName;
-      this.updateViewFn = options.updateViewFn;
-      this.previewFn = options.previewFn;
-      this.showStale = _.isUndefined(options.showStale) ? false : options.showStale;
-      this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce;
-    },
-
-    events: {
-      "change form.js-view-query-update input": "updateFilters",
-      "change form.js-view-query-update select": "updateFilters",
-      "submit form.js-view-query-update": "updateView",
-      "click .toggle-btns > label":  "toggleQuery"
-    },
-
-    toggleQuery: function(e){
-      e.preventDefault();
-
-      if (this.$(e.currentTarget).hasClass("active")){
-        this.$('.js-query-keys-wrapper').addClass("hide");
-        this.$(".toggle-btns > label").removeClass('active');
-        this.$('.js-query-keys-wrapper').find("input,textarea").attr("disabled","true");
-      } else {
-        this.$('.js-query-keys-wrapper').removeClass("hide");
-        var showFunctionName =this.$(e.currentTarget).attr("for");
-        //highlight current
-        this.$(".toggle-btns > label").removeClass('active');
-        this.$(e.currentTarget).addClass("active");
-        this.$("[id^='js-show']").hide();
-        //show section & disable what needs to be disabled
-        this[showFunctionName]();
-      }
-    },
-
-    showKeys: function(){
-      this.$("#js-showKeys, .js-disabled-message").show();
-      this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').attr("disabled","true");
-      this.$('[name="keys"]').removeAttr("disabled");
-    },
-
-    showStartEnd: function(){
-      this.$("#js-showStartEnd").show();
-      this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled");
-      this.$('.js-disabled-message').hide();
-      this.$('[name="keys"]').attr("disabled","true");
-    },
-
-    beforeRender: function () {
-      if (this.viewName && this.ddocName) {
-        var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
-        _.each(buttonViews, function (view) {
-          this.insertView('#button-options', view);
-          view.update(this.database, this.ddocName, this.viewName);
-        }, this);
-      }
-    },
-
-    renderOnUpdatehasReduce: function (hasReduce) {
-      this.hasReduce = hasReduce;
-      this.render();
-    },
-
-    parseJSON: function (value) {
-      try {
-        return JSON.parse(value);
-      } catch(e) {
-        return undefined;
-      }
-    },
-
-    validateKeys:  function(param){
-      var errorMsg = false,
-          parsedValue = this.parseJSON(param.value);
-
-      if (_.isUndefined(parsedValue)) {
-        errorMsg = "Keys must be valid json.";
-      } else if (!_.isArray(parsedValue)) {
-        errorMsg =  "Keys values must be in an array. E.g [1,2,3]";
-      }
-
-      if (errorMsg) {
-        this.$('.js-keys-error').empty();
-        FauxtonAPI.addNotification({
-          type: "error",
-          msg: errorMsg,
-          clear:  false,
-          selector: '.advanced-options .errors-container'
-        });
-        return false;
-      }
-
-      return true;
-    },
-    validateFields: function(params){
-      var errors = false;
-      //so ghetto. Spaghetti code.
-      for (var i= 0; i <params.length; i++){
-        if (params[i].name === "skip"){
-          if (!(/^\d+$/).test(params[i].value)){
-            FauxtonAPI.addNotification({
-              msg: "Numbers only for skip",
-              type: "warn",
-              selector: ".advanced-options .errors-container",
-              clear:  true
-            });
-            errors = true;
-          }
-        }
-      }
-      return errors;
-    },
-    queryParams: function () {
-      var $form = this.$(".js-view-query-update"),
-          keysParam = false;
-
-      var params = _.reduce($form.serializeArray(), function(params, param) {
-        if (!param.value) { return params; }
-        if (param.name === "limit" && param.value === 'None') { return params; }
-        if (param.name === "keys") { keysParam = param; }
-        params.push(param);
-        return params;
-      }, []);
-
-
-      if (keysParam && !this.validateKeys(keysParam)) { return false; }
-
-      if (params && this.validateFields(params)){ return false; }
-
-      // Validate *key* params to ensure they're valid JSON
-      var keyParams = ["keys","startkey","endkey"];
-      var errorParams = _.filter(params, function(param) {
-        if (_.contains(keyParams, param.name) && _.isUndefined(this.parseJSON(param.value))) {
-            return true;
-          }
-
-          return false;
-      }, this);
-
-      return {params: params, errorParams: errorParams};
-    },
-
-    updateView: function (event) {
-      event.preventDefault();
-      var params = this.queryParams();
-      if (!params) { return;}
-      this.updateViewFn(event, params);
-    },
-
-    updateFilters: function(event) {
-      event.preventDefault();
-      var $ele = $(event.currentTarget);
-      var name = $ele.attr('name');
-      this.updateFiltersFor(name, $ele);
-    },
-
-    updateFiltersFor: function(name, $ele) {
-      var $form = $ele.parents("form.js-view-query-update:first");
-      switch (name) {
-        // Reduce constraints
-        //   - Can't include_docs for reduce=true
-        //   - can't include group_level for reduce=false
-        case "reduce":
-          if ($ele.prop('checked') === true) {
-          if ($form.find("input[name=include_docs]").prop("checked") === true) {
-            $form.find("input[name=include_docs]").prop("checked", false);
-            var notification = FauxtonAPI.addNotification({
-              msg: "include_docs has been disabled as you cannot include docs on a reduced view",
-              type: "warn",
-              selector: ".advanced-options .errors-container",
-              clear:  true
-            });
-          }
-          $form.find("input[name=include_docs]").prop("disabled", true);
-          $form.find("select[name=group_level]").prop("disabled", false);
-        } else {
-          $form.find("select[name=group_level]").val("999").prop("disabled", true);
-          $form.find("input[name=include_docs]").prop("disabled", false);
-        }
-        break;
-        case "skip":
-          if (!(/^\d+$/).test($ele.val())){
-            FauxtonAPI.addNotification({
-              msg: "Numbers only for skip",
-              type: "warn",
-              selector: ".advanced-options .errors-container",
-              clear:  true
-            });
-          }
-        break;
-        case "include_docs":
-        break;
-      }
-    },
-
-    updateFromParams: function (params) {
-      var $form = this.$el.find("form.js-view-query-update");
-      _.each(params, function(val, key) {
-        var $ele;
-        switch (key) {
-          case "limit":
-          case "descending":
-          case "group_level":
-            if (!val) { return; }
-            $form.find("select[name='"+key+"']").val(val);
-          break;
-          case "include_docs":
-            case "stale":
-            case "inclusive_end":
-            $form.find("input[name='"+key+"']").prop('checked', true);
-          break;
-          case "reduce":
-            $ele = $form.find("input[name='"+key+"']");
-          if (val == "true") {
-            $ele.prop('checked', true);
-          }
-          this.updateFiltersFor(key, $ele);
-          break;
-          case "key":
-          case "keys":
-            $form.find("textarea[name='"+key+"']").val(val);
-          break;
-          default:
-            $form.find("input[name='"+key+"']").val(val);
-          break;
-        }
-      }, this);
-    },
-
-    serialize: function () {
-      return {
-        hasReduce: this.hasReduce,
-        showPreview: false,
-        showStale: this.showStale
-      };
-    }
-  });
-
-
-  return Views;
-
-});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js
index 2140e04..9c266be 100644
--- a/app/addons/documents/routes.js
+++ b/app/addons/documents/routes.js
@@ -18,9 +18,9 @@ define([
   // Modules
   //views
   "addons/documents/views",
-  "addons/documents/changesviews",
-  "addons/documents/indexviews",
-  "addons/documents/doceditorviews",
+  "addons/documents/views-changes",
+  "addons/documents/views-index",
+  "addons/documents/views-doceditor",
 
   "addons/databases/base",
   "addons/documents/resources"

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/sidebarviews.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/sidebarviews.js b/app/addons/documents/sidebarviews.js
deleted file mode 100644
index e3cc629..0000000
--- a/app/addons/documents/sidebarviews.js
+++ /dev/null
@@ -1,253 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-define([
-       "app",
-
-       "api",
-       "addons/fauxton/components",
-
-       "addons/documents/resources",
-       "addons/databases/resources"
-],
-
-function(app, FauxtonAPI, Components, Documents, Databases) {
-  var Views = {};
-
-  Views.Sidebar = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/sidebar",
-    className: "sidenav",
-    tagName: "nav",
-    events: {
-      "click button#delete-database": "showDeleteDatabaseModal"
-    },
-
-    initialize: function(options) {
-      this.database = options.database;
-      if (options.ddocInfo) {
-        this.ddocID = options.ddocInfo.id;
-        this.currView = options.ddocInfo.currView;
-      }
-    },
-    showDeleteDatabaseModal: function(event){
-      this.deleteDBModal.showModal();
-    },
-
-    serialize: function() {
-      var docLinks = FauxtonAPI.getExtensions('docLinks'),
-          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
-          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
-          extensionList = FauxtonAPI.getExtensions('sidebar:list');
-      return {
-        changes_url: '#' + this.database.url('changes'),
-        permissions_url: '#' + this.database.url('app') + '/permissions',
-        db_url: '#' + this.database.url('index'),
-        database: this.collection.database,
-        database_url: '#' + this.database.url('app'),
-        docLinks: docLinks,
-        addLinks: addLinks,
-        newLinks: newLinks,
-        extensionList: extensionList > 0
-      };
-    },
-
-
-    beforeRender: function(manage) {
-      this.deleteDBModal = this.setView(
-        '#delete-db-modal',
-        new Views.DeleteDBModal({database: this.database})
-      );
-
-      var database = this.collection.database,
-          newurl = "#" + database.url('app') + '/new';
-
-      var newLinks = [{
-        title: 'Add new',
-        links: [{
-          title: 'New Doc',
-          url: newurl,
-          icon: 'fonticon-plus-circled'
-        },{
-          title: 'New Design Doc',
-          url: newurl,
-          icon: 'fonticon-plus-circled'
-        }]
-      }];
-
-      this.insertView("#new-all-docs-button", new Components.MenuDropDown({
-        links: newLinks,
-      }));
-
-      this.insertView("#new-design-docs-button", new Components.MenuDropDown({
-        links: newLinks,
-      }));
-
-      this.collection.each(function(design) {
-        if (design.has('doc')){
-          this.insertView(new Views.DdocSidenav({
-            model: design,
-            collection: this.collection
-          }));
-        }
-      },this);
-    },
-
-    afterRender: function () {
-      if (this.selectedTab) {
-        this.setSelectedTab(this.selectedTab);
-      }
-    },
-
-    setSelectedTab: function (selectedTab) {
-      this.selectedTab = selectedTab;
-      var $selectedTab = this.$('#' + selectedTab);
-
-      this.$('li').removeClass('active');
-      $selectedTab.parent().addClass('active');
-
-      if ($selectedTab.parents(".accordion-body").length !== 0){
-        $selectedTab
-        .parents(".accordion-body")
-        .addClass("in")
-        .parents(".nav-header")
-        .find(">.js-collapse-toggle").addClass("down");
-
-        this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down");
-      }
-    }
-  });
-
-  Views.DdocSidenav = FauxtonAPI.View.extend({
-    tagName: "ul",
-    className:  "nav nav-list",
-    template: "addons/documents/templates/design_doc_menu",
-    events: {
-      "click .js-collapse-toggle": "toggleArrow"
-    },
-
-    toggleArrow:  function(e){
-      this.$(e.currentTarget).toggleClass("down");
-    },
-    buildIndexList: function(collection, selector, ddocType){
-      var design = this.model.id.replace(/^_design\//,"");
-
-      this.insertView(".accordion-body", new Views.IndexItem({
-        selector: selector,
-        ddoc: design,
-        collection: collection[selector],
-        ddocType: ddocType,
-        database: this.model.collection.database.id
-      }));
-    },
-
-    serialize: function(){
-      var ddocName = this.model.id.replace(/^_design\//,"");
-      return{
-        database: this.collection.database,
-        designDoc: ddocName,
-        ddoc_clean: app.utils.removeSpecialCharacters(ddocName),
-        ddoc_encoded: app.utils.safeURLName(ddocName),
-        database_encoded: app.utils.safeURLName(this.model.collection.database.id),
-      };
-    },
-
-    getSidebarLinks: function () {
-      var ddocName = this.model.id.replace(/^_design\//,""),
-          docSafe = app.utils.safeURLName(ddocName), 
-          database = this.collection.database;
-
-      return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) {
-
-        menuLinks.push({
-          title: link.title,
-          url: "#" + database.url('app') + "/" + link.url + "/" + docSafe,
-          icon: 'fonticon-plus-circled'
-        });
-
-        return menuLinks; 
-     }, [{
-      title: 'Secondary View',
-      url: "#" + database.url('app') + "/new_view/" + docSafe,
-      icon: 'fonticon-plus-circled'
-     }]);
-
-    },
-
-    renderIndexLists: function () {
-      var ddocDocs = this.model.get("doc"),
-          sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list');
-
-      if (!ddocDocs){ return; }
-
-      this.buildIndexList(ddocDocs, "views", "view");
-      _.each(sidebarListTypes, function (type) {
-        this.buildIndexList(ddocDocs, type);
-      },this);
-
-    },
-
-    beforeRender: function(manage) {
-      var sideBarMenuLinks = [];
-
-      sideBarMenuLinks.push({
-        title: 'Add new',
-        links: this.getSidebarLinks()
-      });
-
-      this.renderIndexLists();
-      this.insertView(".new-button", new Components.MenuDropDown({
-        links: sideBarMenuLinks,
-      }));
-    }
-  });
-
-  Views.IndexItem = FauxtonAPI.View.extend({
-    template: "addons/documents/templates/index_menu_item",
-    tagName: 'li',
-
-    initialize: function(options){
-      this.index = options.index;
-      this.ddoc = options.ddoc;
-      this.database = options.database;
-      this.selected = !! options.selected;
-      this.selector = options.selector;
-      this.ddocType = options.ddocType || this.selector;
-      this.icons = {
-        "view": "fonticon-sidenav-map-reduce",
-        "indexes": "fonticon-sidenav-search"
-      };
-
-    },
-
-    serialize: function() {
-      return {
-        icon: this.icons[this.ddocType],
-        ddocType:  this.ddocType,
-        index: this.index,
-        ddoc: this.ddoc,
-        database: this.database,
-        selected: this.selected,
-        collection: this.collection
-      };
-    },
-
-    afterRender: function() {
-      if (this.selected) {
-        $(".sidenav ul.nav-list li").removeClass("active");
-        this.$el.addClass("active");
-      }
-    }
-  });
-
-  return Views;
-});
-

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-advancedopts.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-advancedopts.js b/app/addons/documents/views-advancedopts.js
new file mode 100644
index 0000000..b2e1af5
--- /dev/null
+++ b/app/addons/documents/views-advancedopts.js
@@ -0,0 +1,270 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+       "api",
+       // Libs
+       "addons/fauxton/resizeColumns",
+],
+
+function(app, FauxtonAPI, resizeColumns ) {
+
+  var Views = {};
+
+  Views.AdvancedOptions = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/advanced_options",
+    className: "advanced-options well",
+
+    initialize: function (options) {
+      this.database = options.database;
+      this.ddocName = options.ddocName;
+      this.viewName = options.viewName;
+      this.updateViewFn = options.updateViewFn;
+      this.previewFn = options.previewFn;
+      this.showStale = _.isUndefined(options.showStale) ? false : options.showStale;
+      this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce;
+    },
+
+    events: {
+      "change form.js-view-query-update input": "updateFilters",
+      "change form.js-view-query-update select": "updateFilters",
+      "submit form.js-view-query-update": "updateView",
+      "click .toggle-btns > label":  "toggleQuery"
+    },
+
+    toggleQuery: function(e){
+      e.preventDefault();
+
+      if (this.$(e.currentTarget).hasClass("active")){
+        this.$('.js-query-keys-wrapper').addClass("hide");
+        this.$(".toggle-btns > label").removeClass('active');
+        this.$('.js-query-keys-wrapper').find("input,textarea").attr("disabled","true");
+      } else {
+        this.$('.js-query-keys-wrapper').removeClass("hide");
+        var showFunctionName =this.$(e.currentTarget).attr("for");
+        //highlight current
+        this.$(".toggle-btns > label").removeClass('active');
+        this.$(e.currentTarget).addClass("active");
+        this.$("[id^='js-show']").hide();
+        //show section & disable what needs to be disabled
+        this[showFunctionName]();
+      }
+    },
+
+    showKeys: function(){
+      this.$("#js-showKeys, .js-disabled-message").show();
+      this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').attr("disabled","true");
+      this.$('[name="keys"]').removeAttr("disabled");
+    },
+
+    showStartEnd: function(){
+      this.$("#js-showStartEnd").show();
+      this.$('[name="startkey"],[name="endkey"],[name="inclusive_end"]').removeAttr("disabled");
+      this.$('.js-disabled-message').hide();
+      this.$('[name="keys"]').attr("disabled","true");
+    },
+
+    beforeRender: function () {
+      if (this.viewName && this.ddocName) {
+        var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
+        _.each(buttonViews, function (view) {
+          this.insertView('#button-options', view);
+          view.update(this.database, this.ddocName, this.viewName);
+        }, this);
+      }
+    },
+
+    renderOnUpdatehasReduce: function (hasReduce) {
+      this.hasReduce = hasReduce;
+      this.render();
+    },
+
+    parseJSON: function (value) {
+      try {
+        return JSON.parse(value);
+      } catch(e) {
+        return undefined;
+      }
+    },
+
+    validateKeys:  function(param){
+      var errorMsg = false,
+          parsedValue = this.parseJSON(param.value);
+
+      if (_.isUndefined(parsedValue)) {
+        errorMsg = "Keys must be valid json.";
+      } else if (!_.isArray(parsedValue)) {
+        errorMsg =  "Keys values must be in an array. E.g [1,2,3]";
+      }
+
+      if (errorMsg) {
+        this.$('.js-keys-error').empty();
+        FauxtonAPI.addNotification({
+          type: "error",
+          msg: errorMsg,
+          clear:  false,
+          selector: '.advanced-options .errors-container'
+        });
+        return false;
+      }
+
+      return true;
+    },
+    validateFields: function(params){
+      var errors = false;
+      //so ghetto. Spaghetti code.
+      for (var i= 0; i <params.length; i++){
+        if (params[i].name === "skip"){
+          if (!(/^\d+$/).test(params[i].value)){
+            FauxtonAPI.addNotification({
+              msg: "Numbers only for skip",
+              type: "warn",
+              selector: ".advanced-options .errors-container",
+              clear:  true
+            });
+            errors = true;
+          }
+        }
+      }
+      return errors;
+    },
+    queryParams: function () {
+      var $form = this.$(".js-view-query-update"),
+          keysParam = false;
+
+      var params = _.reduce($form.serializeArray(), function(params, param) {
+        if (!param.value) { return params; }
+        if (param.name === "limit" && param.value === 'None') { return params; }
+        if (param.name === "keys") { keysParam = param; }
+        params.push(param);
+        return params;
+      }, []);
+
+
+      if (keysParam && !this.validateKeys(keysParam)) { return false; }
+
+      if (params && this.validateFields(params)){ return false; }
+
+      // Validate *key* params to ensure they're valid JSON
+      var keyParams = ["keys","startkey","endkey"];
+      var errorParams = _.filter(params, function(param) {
+        if (_.contains(keyParams, param.name) && _.isUndefined(this.parseJSON(param.value))) {
+            return true;
+          }
+
+          return false;
+      }, this);
+
+      return {params: params, errorParams: errorParams};
+    },
+
+    updateView: function (event) {
+      event.preventDefault();
+      var params = this.queryParams();
+      if (!params) { return;}
+      this.updateViewFn(event, params);
+    },
+
+    updateFilters: function(event) {
+      event.preventDefault();
+      var $ele = $(event.currentTarget);
+      var name = $ele.attr('name');
+      this.updateFiltersFor(name, $ele);
+    },
+
+    updateFiltersFor: function(name, $ele) {
+      var $form = $ele.parents("form.js-view-query-update:first");
+      switch (name) {
+        // Reduce constraints
+        //   - Can't include_docs for reduce=true
+        //   - can't include group_level for reduce=false
+        case "reduce":
+          if ($ele.prop('checked') === true) {
+          if ($form.find("input[name=include_docs]").prop("checked") === true) {
+            $form.find("input[name=include_docs]").prop("checked", false);
+            var notification = FauxtonAPI.addNotification({
+              msg: "include_docs has been disabled as you cannot include docs on a reduced view",
+              type: "warn",
+              selector: ".advanced-options .errors-container",
+              clear:  true
+            });
+          }
+          $form.find("input[name=include_docs]").prop("disabled", true);
+          $form.find("select[name=group_level]").prop("disabled", false);
+        } else {
+          $form.find("select[name=group_level]").val("999").prop("disabled", true);
+          $form.find("input[name=include_docs]").prop("disabled", false);
+        }
+        break;
+        case "skip":
+          if (!(/^\d+$/).test($ele.val())){
+            FauxtonAPI.addNotification({
+              msg: "Numbers only for skip",
+              type: "warn",
+              selector: ".advanced-options .errors-container",
+              clear:  true
+            });
+          }
+        break;
+        case "include_docs":
+        break;
+      }
+    },
+
+    updateFromParams: function (params) {
+      var $form = this.$el.find("form.js-view-query-update");
+      _.each(params, function(val, key) {
+        var $ele;
+        switch (key) {
+          case "limit":
+          case "descending":
+          case "group_level":
+            if (!val) { return; }
+            $form.find("select[name='"+key+"']").val(val);
+          break;
+          case "include_docs":
+            case "stale":
+            case "inclusive_end":
+            $form.find("input[name='"+key+"']").prop('checked', true);
+          break;
+          case "reduce":
+            $ele = $form.find("input[name='"+key+"']");
+          if (val == "true") {
+            $ele.prop('checked', true);
+          }
+          this.updateFiltersFor(key, $ele);
+          break;
+          case "key":
+          case "keys":
+            $form.find("textarea[name='"+key+"']").val(val);
+          break;
+          default:
+            $form.find("input[name='"+key+"']").val(val);
+          break;
+        }
+      }, this);
+    },
+
+    serialize: function () {
+      return {
+        hasReduce: this.hasReduce,
+        showPreview: false,
+        showStale: this.showStale
+      };
+    }
+  });
+
+
+  return Views;
+
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-changes.js b/app/addons/documents/views-changes.js
new file mode 100644
index 0000000..2f91c21
--- /dev/null
+++ b/app/addons/documents/views-changes.js
@@ -0,0 +1,84 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+
+       "api",
+       // Libs
+       "addons/fauxton/resizeColumns",
+
+       // Plugins
+       "plugins/prettify",
+       // this should never be global available:
+       // https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/security.md
+       "plugins/zeroclipboard/ZeroClipboard"
+],
+
+function(app, FauxtonAPI, resizeColumns,  prettify, ZeroClipboard) {
+
+  var Views = {};
+
+  Views.Changes = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/changes",
+
+    initialize: function () {
+      this.listenTo( this.model.changes, 'sync', this.render);
+      this.listenTo( this.model.changes, 'cachesync', this.render);
+    },
+
+    events: {
+      "click button.js-toggle-json": "toggleJson"
+    },
+
+    toggleJson: function(event) {
+      event.preventDefault();
+
+      var $button = this.$(event.target),
+          $container = $button.closest('.change-box').find(".js-json-container");
+
+      if (!$container.is(":visible")) {
+        $button
+          .text("Close JSON")
+          .addClass("btn-secondary")
+          .removeClass("btn-primary");
+      } else {
+        $button.text("View JSON")
+          .addClass("btn-primary")
+          .removeClass("btn-secondary");
+      }
+
+      $container.slideToggle();
+    },
+
+    establish: function() {
+      return [ this.model.changes.fetchOnce({prefill: true})];
+    },
+
+    serialize: function () {
+      return {
+        changes: this.model.changes.toJSON(),
+        database: this.model
+      };
+    },
+
+    afterRender: function(){
+      prettyPrint();
+      ZeroClipboard.config({ moviePath: "/assets/js/plugins/zeroclipboard/ZeroClipboard.swf" });
+      var client = new ZeroClipboard(this.$(".js-copy"));
+    }
+  });
+
+
+
+  return Views;
+});

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/893e9881/app/addons/documents/views-doceditor.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views-doceditor.js b/app/addons/documents/views-doceditor.js
new file mode 100644
index 0000000..add8d8c
--- /dev/null
+++ b/app/addons/documents/views-doceditor.js
@@ -0,0 +1,416 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+       "app",
+
+       "api",
+       "addons/fauxton/components",
+
+       "addons/documents/resources",
+       "addons/databases/resources",
+
+       // Libs
+       "addons/fauxton/resizeColumns",
+
+       // Plugins
+       "plugins/prettify"
+],
+
+function(app, FauxtonAPI, Components, Documents, Databases,
+         resizeColumns, prettify) {
+
+  var Views = {};
+
+  /* Attachments upload modal */
+
+  Views.UploadModal = Components.ModalView.extend({
+    template: "addons/documents/templates/upload_modal",
+
+    events: {
+      "click #upload-btn": "uploadFile"
+    },
+
+    uploadFile: function (event) {
+      event.preventDefault();
+
+      var docRev = this.model.get('_rev'),
+          that = this,
+          $form = this.$('#file-upload');
+
+      if (!docRev) {
+        return this.set_error_msg('The document needs to be saved before adding an attachment.');
+      }
+
+      if ($('input[type="file"]')[0].files.length === 0) {
+        return this.set_error_msg('Selected a file to be uploaded.');
+      }
+
+      this.$('#_rev').val(docRev);
+
+      $form.ajaxSubmit({
+        url: this.model.url(),
+        type: 'POST',
+        beforeSend: this.beforeSend,
+        uploadProgress: this.uploadProgress,
+        success: this.success,
+        error: function (resp) {
+          console.log('ERR on upload', resp);
+          return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
+        }
+      });
+    },
+
+    success: function (resp) {
+      var hideModal = this.hideModal,
+          $form = this.$('#file-upload');
+
+      FauxtonAPI.triggerRouteEvent('reRenderDoc');
+      //slight delay to make this transistion a little more fluid and less jumpy
+      setTimeout(function () {
+        $form.clearForm();
+        hideModal();
+        $('.modal-backdrop').remove();
+      }, 1000);
+    },
+
+    uploadProgress: function(event, position, total, percentComplete) {
+      this.$('.bar').css({width: percentComplete + '%'});
+    },
+
+    beforeSend: function () {
+      this.$('.progress').removeClass('hide');
+    },
+
+    _showModal: function () {
+      this.$('.bar').css({width: '0%'});
+      this.$('.progress').addClass('hide');
+    }
+  });
+
+
+
+  /* Doc Duplication modal */
+  Views.DuplicateDocModal = Components.ModalView.extend({
+    template: "addons/documents/templates/duplicate_doc_modal",
+
+    initialize: function () {
+      _.bindAll(this);
+    },
+
+    events: {
+      "click #duplicate-btn":"duplicate",
+      "submit #doc-duplicate": "duplicate"
+
+    },
+
+    duplicate: function (event) {
+      event.preventDefault();
+      var newId = this.$('#dup-id').val(),
+          isDDoc = newId.match(/^_design\//),
+          removeDDocID = newId.replace(/^_design\//,""),
+          encodedID = isDDoc? "_design/"+ app.utils.safeURLName(removeDDocID):app.utils.safeURLName(newId);
+
+      this.hideModal();
+      FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
+    },
+
+    _showModal: function () {
+      this.$('.bar').css({width: '0%'});
+      this.$('.progress').addClass('hide');
+      this.clear_error_msg();
+      this.$('.modal').modal();
+      // hack to get modal visible
+      $('.modal-backdrop').css('z-index',1025);
+    },
+
+    showModal: function () {
+      var showModal = this._showModal,
+          setDefaultIdValue = this.setDefaultIdValue,
+          uuid = new FauxtonAPI.UUID();
+
+      uuid.fetch().then(function () {
+        setDefaultIdValue(uuid.next());
+        showModal();
+      });
+    },
+
+    setDefaultIdValue: function (id) {
+      this.$('#dup-id').val(id);
+    }
+  });
+
+  /* Document editor*/
+   Views.CodeEditor = FauxtonAPI.View.extend({
+    template: "addons/documents/templates/code_editor",
+    events: {
+      "click button.save-doc": "saveDoc",
+      "click button.delete": "destroy",
+      "click button.duplicate": "duplicate",
+      "click button.upload": "upload",
+      "click button.cancel-button": "goback"
+    },
+
+    disableLoader: true,
+
+    initialize: function (options) {
+      this.database = options.database;
+      _.bindAll(this);
+    },
+
+    goback: function(){
+      FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
+    },
+
+    destroy: function(event) {
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'This document has not been saved yet.',
+          type: 'warning',
+          clear:  true
+        });
+        return;
+      }
+
+      if (!window.confirm("Are you sure you want to delete this doc?")) {
+        return false;
+      }
+
+      var database = this.model.database;
+
+      this.model.destroy().then(function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Succesfully deleted your doc",
+          clear:  true
+        });
+        FauxtonAPI.navigate(database.url("index"));
+      }, function(resp) {
+        FauxtonAPI.addNotification({
+          msg: "Failed to delete your doc!",
+          type: "error",
+          clear:  true
+        });
+      });
+    },
+
+    beforeRender: function () {
+      this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model}));
+      this.uploadModal.render();
+
+      this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model}));
+      this.duplicateModal.render();
+    },
+
+    upload: function (event) {
+      event.preventDefault();
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'Please save the document before uploading an attachment.',
+          type: 'warning',
+          clear:  true
+        });
+        return;
+      }
+      this.uploadModal.showModal();
+    },
+
+    duplicate: function(event) {
+      if (this.model.isNewDoc()) {
+        FauxtonAPI.addNotification({
+          msg: 'Please save the document before duplicating it.',
+          type: 'warning',
+          clear:  true
+        });
+        return;
+      }
+      event.preventDefault();
+      this.duplicateModal.showModal();
+    },
+
+    updateValues: function() {
+      if (this.model.changedAttributes()) {
+        FauxtonAPI.addNotification({
+          msg: "Document saved successfully.",
+          type: "success",
+          clear: true
+        });
+        this.editor.setValue(this.model.prettyJSON());
+      }
+    },
+
+    establish: function() {
+      var promise = this.model.fetch(),
+          databaseId = this.database.safeID(),
+          deferred = $.Deferred(),
+          that = this;
+
+      promise.then(function () {
+        deferred.resolve();
+      }, function (xhr, reason, msg) {
+        if (xhr.status === 404) {
+          FauxtonAPI.addNotification({
+            msg: 'The document does not exist',
+            type: 'error',
+            clear: true
+          });
+          that.goback();
+        }
+        deferred.reject();
+     });
+
+      return deferred;
+    },
+
+    saveDoc: function(event) {
+      var json,
+      that = this,
+      editor = this.editor,
+      validDoc = this.getDocFromEditor();
+
+      if (validDoc) {
+        this.getDocFromEditor();
+
+        FauxtonAPI.addNotification({msg: "Saving document."});
+
+        this.model.save().then(function () {
+          editor.editSaved();
+          FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
+        }).fail(function(xhr) {
+          var responseText = JSON.parse(xhr.responseText).reason;
+          FauxtonAPI.addNotification({
+            msg: "Save failed: " + responseText,
+            type: "error",
+            fade: false,
+            clear: true,
+            selector: "#doc .errors-container"
+          });
+        });
+      } else if(this.model.validationError && this.model.validationError === 'Cannot change a documents id.') {
+          FauxtonAPI.addNotification({
+            msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
+            type: "error",
+            selector: "#doc .errors-container",
+            clear:  true
+          });
+        delete this.model.validationError;
+      } else {
+        FauxtonAPI.addNotification({
+          msg: "Please fix the JSON errors and try again.",
+          type: "error",
+          selector: "#doc .errors-container",
+          clear:  true
+        });
+      }
+    },
+
+    getDocFromEditor: function () {
+      var json;
+
+      if (!this.hasValidCode()) {
+        return false;
+      }
+
+      json = JSON.parse(this.editor.getValue());
+
+      this.model.clear().set(json, {validate: true});
+      if (this.model.validationError) {
+        return false;
+      }
+
+      return this.model;
+    },
+
+    hasValidCode: function() {
+      var errors = this.editor.getAnnotations();
+      return errors.length === 0;
+    },
+
+    serialize: function() {
+      return {
+        doc: this.model,
+        attachments: this.getAttachments()
+      };
+    },
+
+    getAttachments: function () {
+      var attachments = this.model.get('_attachments');
+
+      if (!attachments) { return false; }
+
+      return _.map(attachments, function (att, key) {
+        return {
+          fileName: key,
+          size: att.length,
+          contentType: att.content_type,
+          url: this.model.url() + '/' + app.utils.safeURLName(key)
+        };
+      }, this);
+    },
+
+    afterRender: function() {
+      var saveDoc = this.saveDoc,
+          editor,
+          model;
+
+      this.editor = new Components.Editor({
+        editorId: "editor-container",
+        forceMissingId: true,
+        commands: [{
+          name: 'save',
+          bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
+          exec: function(editor) {
+            saveDoc();
+          },
+          readOnly: true // false if this command should not apply in readOnly mode
+        }]
+      });
+      this.editor.render();
+
+      editor = this.editor;
+      model = this.model;
+
+      this.listenTo(this.model, "sync", this.updateValues);
+      this.listenTo(editor.editor, "change", function (event) {
+        var changedDoc;
+        try {
+          changedDoc = JSON.parse(editor.getValue());
+        } catch(exception) {
+          //not complete doc. Cannot work with it
+          return;
+        }
+
+        var keyChecked = ["_id"];
+        if (model.get("_rev")) { keyChecked.push("_rev");}
+
+        //check the changedDoc has all the required standard keys
+        if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; }
+
+        editor.setReadOnly(true);
+        setTimeout(function () { editor.setReadOnly(false);}, 400);
+        // use extend so that _id stays at the top of the object with displaying the doc
+        changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc);
+        editor.setValue(JSON.stringify(changedDoc, null, "  "));
+        FauxtonAPI.addNotification({
+          type: "error",
+          msg: "Cannot remove a documents Id or Revision.",
+          clear:  true
+        });
+      });
+    },
+
+    cleanup: function () {
+      if (this.editor) this.editor.remove();
+    }
+  });
+
+  return Views;
+});