summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarren Smith <garren.smith@gmail.com>2013-09-17 16:23:32 +0200
committerGarren Smith <garren.smith@gmail.com>2013-09-17 16:23:32 +0200
commitb14ba5b55eae8bc5e77beef53f3e1c74090318f9 (patch)
treecc42dab9e14a4218b10ebe936c4aa7379f6546d7
parent8a33322704ca03a09849a6a72ddbb16ff444071f (diff)
downloadcouchdb-fauxton-typeahead.tar.gz
add typeahead viewfauxton-typeahead
-rw-r--r--src/fauxton/app/addons/replication/views.js534
-rw-r--r--src/fauxton/app/modules/databases/views.js36
-rw-r--r--src/fauxton/app/modules/documents/views.js6
-rw-r--r--src/fauxton/app/modules/fauxton/components.js (renamed from src/fauxton/app/modules/fauxton/paginate.js)58
4 files changed, 322 insertions, 312 deletions
diff --git a/src/fauxton/app/addons/replication/views.js b/src/fauxton/app/addons/replication/views.js
index bd3daa157..f4b96fd40 100644
--- a/src/fauxton/app/addons/replication/views.js
+++ b/src/fauxton/app/addons/replication/views.js
@@ -11,303 +11,285 @@
// the License.
define([
- "app",
- "api",
- "addons/replication/resources"
+ "app",
+ "api",
+ "modules/fauxton/components",
+ "addons/replication/resources"
],
-function(app, FauxtonAPI, replication) {
+function(app, FauxtonAPI, Components, replication) {
var View = {},
- Events ={},
- pollingInfo ={
- rate: 5,
- intervalId: null
- };
+ Events ={},
+ pollingInfo ={
+ rate: 5,
+ intervalId: null
+ };
_.extend(Events, Backbone.Events);
-
-// NOTES: http://wiki.apache.org/couchdb/Replication
-// Replication form view is huge
-// -----------------------------------
-// afterRender: autocomplete on the target input field
-// beforeRender: add the status table
-// disableFields: disable non active fields on submit
-// enableFields: enable field when radio btns are clicked
-// establish: get the DB list for autocomplete
-// formValidation: make sure fields aren't empty
-// showProgress: make a call to active_tasks model and show only replication types. Poll every 5 seconds. (make this it's own view)
-// startReplication: saves to the model, starts replication
-// submit: form submit handler
-// swapFields: change to and from target
-// toggleAdvancedOptions: toggle advanced
+ // NOTES: http://wiki.apache.org/couchdb/Replication
+
+ // Replication form view is huge
+ // -----------------------------------
+ // afterRender: autocomplete on the target input field
+ // beforeRender: add the status table
+ // disableFields: disable non active fields on submit
+ // enableFields: enable field when radio btns are clicked
+ // establish: get the DB list for autocomplete
+ // formValidation: make sure fields aren't empty
+ // showProgress: make a call to active_tasks model and show only replication types. Poll every 5 seconds. (make this it's own view)
+ // startReplication: saves to the model, starts replication
+ // submit: form submit handler
+ // swapFields: change to and from target
+ // toggleAdvancedOptions: toggle advanced
View.ReplicationForm = FauxtonAPI.View.extend({
- template: "addons/replication/templates/form",
- events: {
- "submit #replication": "validate",
- "click .btn-group .btn": "showFields",
- "click .swap": "swapFields",
- "click .options": "toggleAdvancedOptions"
- },
- initialize: function(options){
- this.status = options.status;
- this.selectedDB = options.selectedDB;
- this.newRepModel = new replication.Replicate({});
- },
- afterRender: function(){
- var dbLimit = 30;
- var ajaxReq;
- //re-using what we have on DB search
- this.$el.find("input#to_name").typeahead({
- source: function(query, process) {
- var url = [
- app.host,
- "/_all_dbs?startkey=%22",
- query,
- "%22&endkey=%22",
- query,
- "\u9999%22&limit=",
- dbLimit
- ].join('');
- if (ajaxReq) ajaxReq.abort();
- ajaxReq = $.ajax({
- url: url,
- dataType: 'json',
- success: function(data) {
- process(data);
- }
- });
- }
+ template: "addons/replication/templates/form",
+ events: {
+ "submit #replication": "validate",
+ "click .btn-group .btn": "showFields",
+ "click .swap": "swapFields",
+ "click .options": "toggleAdvancedOptions"
+ },
+ initialize: function(options){
+ this.status = options.status;
+ this.selectedDB = options.selectedDB;
+ this.newRepModel = new replication.Replicate({});
+ },
+ afterRender: function(){
+ this.dbSearchTypeahead = new Components.DbSearchTypeahead({
+ dbLimit: 30,
+ el: "input#to_name"
});
- },
+ this.dbSearchTypeahead.render();
- beforeRender: function(){
- this.insertView("#replicationStatus", new View.ReplicationList({
- collection: this.status
- }));
- },
- cleanup: function(){
- clearInterval(pollingInfo.intervalId);
- },
- enableFields: function(){
- this.$el.find('input','select').attr('disabled',false);
- },
- disableFields: function(){
- this.$el.find('input:hidden','select:hidden').attr('disabled',true);
- },
- showFields: function(e){
- var $currentTarget = this.$(e.currentTarget),
- targetVal = $currentTarget.val();
+ },
- if (targetVal === "local"){
- $currentTarget.parents('.form_set').addClass('local');
- }else{
- $currentTarget.parents('.form_set').removeClass('local');
- }
- },
- establish: function(){
- return [ this.collection.fetch(), this.status.fetch()];
- },
- validate: function(e){
- e.preventDefault();
- var notification;
- if (this.formValidation()){
- notification = FauxtonAPI.addNotification({
- msg: "Please enter every field.",
- type: "error",
- clear: true
- });
- }else if (this.$('input#to_name').is(':visible') && !this.$('input[name=create_target]').is(':checked')){
- var alreadyExists = this.collection.where({"name":this.$('input#to_name').val()});
- if (alreadyExists.length === 0){
- notification = FauxtonAPI.addNotification({
- msg: "This database doesn't exist. Check create target if you want to create it.",
- type: "error",
- clear: true
- });
- }
- }else{
- this.submit(e);
- }
- },
- formValidation: function(e){
- var $remote = this.$el.find('input:visible'),
+ beforeRender: function(){
+ this.insertView("#replicationStatus", new View.ReplicationList({
+ collection: this.status
+ }));
+ },
+ cleanup: function(){
+ clearInterval(pollingInfo.intervalId);
+ },
+ enableFields: function(){
+ this.$el.find('input','select').attr('disabled',false);
+ },
+ disableFields: function(){
+ this.$el.find('input:hidden','select:hidden').attr('disabled',true);
+ },
+ showFields: function(e){
+ var $currentTarget = this.$(e.currentTarget),
+ targetVal = $currentTarget.val();
+
+ if (targetVal === "local"){
+ $currentTarget.parents('.form_set').addClass('local');
+ }else{
+ $currentTarget.parents('.form_set').removeClass('local');
+ }
+ },
+ establish: function(){
+ return [ this.collection.fetch(), this.status.fetch()];
+ },
+ validate: function(e){
+ e.preventDefault();
+ var notification;
+ if (this.formValidation()){
+ notification = FauxtonAPI.addNotification({
+ msg: "Please enter every field.",
+ type: "error",
+ clear: true
+ });
+ }else if (this.$('input#to_name').is(':visible') && !this.$('input[name=create_target]').is(':checked')){
+ var alreadyExists = this.collection.where({"name":this.$('input#to_name').val()});
+ if (alreadyExists.length === 0){
+ notification = FauxtonAPI.addNotification({
+ msg: "This database doesn't exist. Check create target if you want to create it.",
+ type: "error",
+ clear: true
+ });
+ }
+ }else{
+ this.submit(e);
+ }
+ },
+ formValidation: function(e){
+ var $remote = this.$el.find('input:visible'),
error = false;
for(var i=0; i<$remote.length; i++){
- if ($remote[i].value =="http://" || $remote[i].value ===""){
- error = true;
- }
+ if ($remote[i].value =="http://" || $remote[i].value ===""){
+ error = true;
+ }
}
- return error;
- },
- serialize: function(){
- return {
- databases: this.collection.toJSON(),
- selectedDB: this.selectedDB
- };
- },
- startReplication: function(json){
- var that = this;
- this.newRepModel.save(json,{
- success: function(resp){
- var notification = FauxtonAPI.addNotification({
- msg: "Replication from "+resp.get('source')+" to "+ resp.get('target')+" has begun.",
- type: "success",
- clear: true
- });
- that.updateButtonText(false);
- Events.trigger('update:tasks');
- },
- error: function(model, xhr, options){
- var errorMessage = JSON.parse(xhr.responseText);
- var notification = FauxtonAPI.addNotification({
- msg: errorMessage.reason,
- type: "error",
- clear: true
- });
- that.updateButtonText(false);
- }
- });
- this.enableFields();
- },
- updateButtonText: function(wait){
- var $button = this.$('#replication button[type=submit]');
- if(wait){
- $button.text('Starting replication...').attr('disabled', true);
- } else {
- $button.text('Replication').attr('disabled', false);
- }
- },
- submit: function(e){
- this.disableFields();
- var formJSON = {};
- _.map(this.$(e.currentTarget).serializeArray(), function(formData){
- if(formData.value !== ''){
- formJSON[formData.name] = (formData.value ==="true"? true: formData.value.replace(/\s/g, '').toLowerCase());
-
- }
- });
+ return error;
+ },
+ serialize: function(){
+ return {
+ databases: this.collection.toJSON(),
+ selectedDB: this.selectedDB
+ };
+ },
+ startReplication: function(json){
+ var that = this;
+ this.newRepModel.save(json,{
+ success: function(resp){
+ var notification = FauxtonAPI.addNotification({
+ msg: "Replication from "+resp.get('source')+" to "+ resp.get('target')+" has begun.",
+ type: "success",
+ clear: true
+ });
+ that.updateButtonText(false);
+ Events.trigger('update:tasks');
+ },
+ error: function(model, xhr, options){
+ var errorMessage = JSON.parse(xhr.responseText);
+ var notification = FauxtonAPI.addNotification({
+ msg: errorMessage.reason,
+ type: "error",
+ clear: true
+ });
+ that.updateButtonText(false);
+ }
+ });
+ this.enableFields();
+ },
+ updateButtonText: function(wait){
+ var $button = this.$('#replication button[type=submit]');
+ if(wait){
+ $button.text('Starting replication...').attr('disabled', true);
+ } else {
+ $button.text('Replication').attr('disabled', false);
+ }
+ },
+ submit: function(e){
+ this.disableFields();
+ var formJSON = {};
+ _.map(this.$(e.currentTarget).serializeArray(), function(formData){
+ if(formData.value !== ''){
+ formJSON[formData.name] = (formData.value ==="true"? true: formData.value.replace(/\s/g, '').toLowerCase());
+ }
+ });
- this.updateButtonText(true);
- this.startReplication(formJSON);
- },
- swapFields: function(e){
- e.preventDefault();
- //WALL O' VARIABLES
- var $fromSelect = this.$('#from_name'),
- $toSelect = this.$('#to_name'),
- $toInput = this.$('#to_url'),
- $fromInput = this.$('#from_url'),
- fromSelectVal = $fromSelect.val(),
- fromInputVal = $fromInput.val(),
- toSelectVal = $toSelect.val(),
- toInputVal = $toInput.val();
+ this.updateButtonText(true);
+ this.startReplication(formJSON);
+ },
+ swapFields: function(e){
+ e.preventDefault();
+ //WALL O' VARIABLES
+ var $fromSelect = this.$('#from_name'),
+ $toSelect = this.$('#to_name'),
+ $toInput = this.$('#to_url'),
+ $fromInput = this.$('#from_url'),
+ fromSelectVal = $fromSelect.val(),
+ fromInputVal = $fromInput.val(),
+ toSelectVal = $toSelect.val(),
+ toInputVal = $toInput.val();
- $fromSelect.val(toSelectVal);
- $toSelect.val(fromSelectVal);
+ $fromSelect.val(toSelectVal);
+ $toSelect.val(fromSelectVal);
- $fromInput.val(toInputVal);
- $toInput.val(fromInputVal);
- }
+ $fromInput.val(toInputVal);
+ $toInput.val(fromInputVal);
+ }
});
-View.ReplicationList = FauxtonAPI.View.extend({
- tagName: "ul",
- initialize: function(){
- Events.bind('update:tasks', this.establish, this);
- this.listenTo(this.collection, "reset", this.render);
- this.$el.prepend("<li class='header'><h4>Active Replication Tasks</h4></li>");
- },
- establish: function(){
- return [this.collection.fetch({reset: true})];
- },
- setPolling: function(){
- var that = this;
- this.cleanup();
- pollingInfo.intervalId = setInterval(function() {
- that.establish();
- }, pollingInfo.rate*1000);
- },
- cleanup: function(){
- clearInterval(pollingInfo.intervalId);
- },
- beforeRender: function(){
- this.collection.forEach(function(item) {
- this.insertView(new View.replicationItem({
- model: item
- }));
- }, this);
- },
- showHeader: function(){
- if (this.collection.length > 0){
- this.$el.parent().addClass('showHeader');
- } else {
- this.$el.parent().removeClass('showHeader');
- }
- },
- afterRender: function(){
- this.showHeader();
- this.setPolling();
- }
-});
+ View.ReplicationList = FauxtonAPI.View.extend({
+ tagName: "ul",
+ initialize: function(){
+ Events.bind('update:tasks', this.establish, this);
+ this.listenTo(this.collection, "reset", this.render);
+ this.$el.prepend("<li class='header'><h4>Active Replication Tasks</h4></li>");
+ },
+ establish: function(){
+ return [this.collection.fetch({reset: true})];
+ },
+ setPolling: function(){
+ var that = this;
+ this.cleanup();
+ pollingInfo.intervalId = setInterval(function() {
+ that.establish();
+ }, pollingInfo.rate*1000);
+ },
+ cleanup: function(){
+ clearInterval(pollingInfo.intervalId);
+ },
+ beforeRender: function(){
+ this.collection.forEach(function(item) {
+ this.insertView(new View.replicationItem({
+ model: item
+ }));
+ }, this);
+ },
+ showHeader: function(){
+ if (this.collection.length > 0){
+ this.$el.parent().addClass('showHeader');
+ } else {
+ this.$el.parent().removeClass('showHeader');
+ }
+ },
+ afterRender: function(){
+ this.showHeader();
+ this.setPolling();
+ }
+ });
- //make this a table row item.
- View.replicationItem = FauxtonAPI.View.extend({
- tagName: "li",
- className: "row",
- template: "addons/replication/templates/progress",
- events: {
- "click .cancel": "cancelReplication"
- },
- initialize: function(){
- this.newRepModel = new replication.Replicate({});
- },
- establish: function(){
- return [this.model.fetch()];
- },
- cancelReplication: function(e){
- //need to pass "cancel": true with source & target
- var $currentTarget = this.$(e.currentTarget),
- repID = $currentTarget.attr('data-rep-id');
- this.newRepModel.save({
- "replication_id": repID,
- "cancel": true
- },
- {
- success: function(model, xhr, options){
- var notification = FauxtonAPI.addNotification({
- msg: "Replication stopped.",
- type: "success",
- clear: true
- });
- },
- error: function(model, xhr, options){
- var errorMessage = JSON.parse(xhr.responseText);
- var notification = FauxtonAPI.addNotification({
- msg: errorMessage.reason,
- type: "error",
- clear: true
- });
- }
- });
- },
- afterRender: function(){
- if (this.model.get('continuous')){
- this.$el.addClass('continuous');
- }
- },
- serialize: function(){
- return {
- progress: this.model.get('progress'),
- target: this.model.get('target'),
- source: this.model.get('source'),
- continuous: this.model.get('continuous'),
- repid: this.model.get('replication_id')
- };
- }
- });
+ //make this a table row item.
+ View.replicationItem = FauxtonAPI.View.extend({
+ tagName: "li",
+ className: "row",
+ template: "addons/replication/templates/progress",
+ events: {
+ "click .cancel": "cancelReplication"
+ },
+ initialize: function(){
+ this.newRepModel = new replication.Replicate({});
+ },
+ establish: function(){
+ return [this.model.fetch()];
+ },
+ cancelReplication: function(e){
+ //need to pass "cancel": true with source & target
+ var $currentTarget = this.$(e.currentTarget),
+ repID = $currentTarget.attr('data-rep-id');
+ this.newRepModel.save({
+ "replication_id": repID,
+ "cancel": true
+ },
+ {
+ success: function(model, xhr, options){
+ var notification = FauxtonAPI.addNotification({
+ msg: "Replication stopped.",
+ type: "success",
+ clear: true
+ });
+ },
+ error: function(model, xhr, options){
+ var errorMessage = JSON.parse(xhr.responseText);
+ var notification = FauxtonAPI.addNotification({
+ msg: errorMessage.reason,
+ type: "error",
+ clear: true
+ });
+ }
+ });
+ },
+ afterRender: function(){
+ if (this.model.get('continuous')){
+ this.$el.addClass('continuous');
+ }
+ },
+ serialize: function(){
+ return {
+ progress: this.model.get('progress'),
+ target: this.model.get('target'),
+ source: this.model.get('source'),
+ continuous: this.model.get('continuous'),
+ repid: this.model.get('replication_id')
+ };
+ }
+ });
return View;
});
diff --git a/src/fauxton/app/modules/databases/views.js b/src/fauxton/app/modules/databases/views.js
index ef7584127..749f79c57 100644
--- a/src/fauxton/app/modules/databases/views.js
+++ b/src/fauxton/app/modules/databases/views.js
@@ -13,11 +13,11 @@
define([
"app",
- "modules/fauxton/paginate",
- "api"
+ "modules/fauxton/components",
+ "api",
],
-function(app, Paginate, FauxtonAPI) {
+function(app, Components, FauxtonAPI) {
var Views = {};
Views.Item = FauxtonAPI.View.extend({
@@ -83,7 +83,7 @@ function(app, Paginate, FauxtonAPI) {
}));
}, this);
- this.insertView("#database-pagination", new Paginate.Pagination({
+ this.insertView("#database-pagination", new Components.Pagination({
page: this.page,
perPage: this.perPage,
total: this.collection.length,
@@ -98,30 +98,12 @@ function(app, Paginate, FauxtonAPI) {
},
afterRender: function() {
- var dbLimit = this.dbLimit;
- var ajaxReq;
-
- this.$el.find("input.search-query").typeahead({
- source: function(query, process) {
- var url = [
- app.host,
- "/_all_dbs?startkey=%22",
- query,
- "%22&endkey=%22",
- query,
- "\u9999%22&limit=",
- dbLimit
- ].join('');
- if (ajaxReq) ajaxReq.abort();
- ajaxReq = $.ajax({
- url: url,
- dataType: 'json',
- success: function(data) {
- process(data);
- }
- });
- }
+ this.dbSearchTypeahead = new Components.DbSearchTypeahead({
+ dbLimit: this.dbLimit,
+ el: "input.search-query"
});
+
+ this.dbSearchTypeahead.render();
},
selectAll: function(evt){
diff --git a/src/fauxton/app/modules/documents/views.js b/src/fauxton/app/modules/documents/views.js
index 40f610ed0..36c6eeb06 100644
--- a/src/fauxton/app/modules/documents/views.js
+++ b/src/fauxton/app/modules/documents/views.js
@@ -14,7 +14,7 @@ define([
"app",
"api",
- "modules/fauxton/paginate",
+ "modules/fauxton/components",
"modules/documents/resources",
"modules/pouchdb/base",
@@ -30,7 +30,7 @@ define([
],
-function(app, FauxtonAPI, Paginate, Documents, pouchdb, Codemirror, JSHint, resizeColumns) {
+function(app, FauxtonAPI, Components, Documents, pouchdb, Codemirror, JSHint, resizeColumns) {
var Views = {};
Views.Tabs = FauxtonAPI.View.extend({
@@ -520,7 +520,7 @@ function(app, FauxtonAPI, Paginate, Documents, pouchdb, Codemirror, JSHint, resi
addPagination: function () {
var collection = this.collection;
- this.pagination = new Paginate.IndexPagination({
+ this.pagination = new Components.IndexPagination({
collection: this.collection,
scrollToSelector: '#dashboard-content',
previousUrlfn: function () {
diff --git a/src/fauxton/app/modules/fauxton/paginate.js b/src/fauxton/app/modules/fauxton/components.js
index 074fb479a..10e08dc57 100644
--- a/src/fauxton/app/modules/fauxton/paginate.js
+++ b/src/fauxton/app/modules/fauxton/components.js
@@ -13,13 +13,13 @@
define([
"app",
// Libs
- "api"
+ "api"
],
function(app, FauxtonAPI) {
- var Paginate = app.module();
-
- Paginate.Pagination = FauxtonAPI.View.extend({
+ var Components = app.module();
+
+ Components.Pagination = FauxtonAPI.View.extend({
template: "templates/fauxton/pagination",
initialize: function(options) {
@@ -41,7 +41,7 @@ function(app, FauxtonAPI) {
}
});
- Paginate.IndexPagination = FauxtonAPI.View.extend({
+ Components.IndexPagination = FauxtonAPI.View.extend({
template: "templates/fauxton/index_pagination",
events: {
"click a": 'scrollTo',
@@ -87,6 +87,52 @@ function(app, FauxtonAPI) {
});
- return Paginate;
+ //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 () {
+ this.$el.typeahead({
+ source: this.source
+ });
+ }
+
+ });
+
+ Components.DbSearchTypeahead = Components.Typeahead.extend({
+ initialize: function (options) {
+ this.dbLimit = options.dbLimit || 30;
+ _.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({
+ url: url,
+ dataType: 'json',
+ success: function(data) {
+ process(data);
+ }
+ });
+ }
+ });
+
+ return Components;
});