couchdb-commits mailing list archives

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

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

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

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

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

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

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


Mime
View raw message