You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2014/01/09 01:07:47 UTC
[32/96] [abbrv] [partial] move sources to src
http://git-wip-us.apache.org/repos/asf/couchdb/blob/941a8236/apps/fauxton/app/modules/documents/views.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/documents/views.js b/apps/fauxton/app/modules/documents/views.js
deleted file mode 100644
index e155435..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/fauxton/base.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/fauxton/base.js b/apps/fauxton/app/modules/fauxton/base.js
deleted file mode 100644
index 01c2928..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/fauxton/components.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/fauxton/components.js b/apps/fauxton/app/modules/fauxton/components.js
deleted file mode 100644
index 6afe046..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/fauxton/layout.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/fauxton/layout.js b/apps/fauxton/app/modules/fauxton/layout.js
deleted file mode 100644
index 1422241..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/pouchdb/base.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/pouchdb/base.js b/apps/fauxton/app/modules/pouchdb/base.js
deleted file mode 100644
index ee323a7..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/pouchdb/pouch.collate.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/pouchdb/pouch.collate.js b/apps/fauxton/app/modules/pouchdb/pouch.collate.js
deleted file mode 100644
index 7cc5f9c..0000000
--- a/apps/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/941a8236/apps/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
----------------------------------------------------------------------
diff --git a/apps/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js b/apps/fauxton/app/modules/pouchdb/pouchdb.mapreduce.js
deleted file mode 100644
index a2d0b91..0000000
--- a/apps/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();
-});