summaryrefslogtreecommitdiff
path: root/share/www/script
diff options
context:
space:
mode:
authorChristopher Lenz <cmlenz@apache.org>2008-04-15 00:07:08 +0000
committerChristopher Lenz <cmlenz@apache.org>2008-04-15 00:07:08 +0000
commit01060528e2f94e0ae4374eb3746093a868b6a2f2 (patch)
treece7c28082894a84e6ad7a494e5fb034b274d1d6d /share/www/script
parent4c6263150674c231239b4e1aeee804a3c5974c9a (diff)
Merged futon-async branch back into trunk.
git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@648074 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'share/www/script')
-rw-r--r--share/www/script/browse.js647
-rw-r--r--share/www/script/jquery.couch.js271
-rw-r--r--share/www/script/jquery.dialog.js15
3 files changed, 651 insertions, 282 deletions
diff --git a/share/www/script/browse.js b/share/www/script/browse.js
index 8ae1e589..332b73d8 100644
--- a/share/www/script/browse.js
+++ b/share/www/script/browse.js
@@ -18,35 +18,50 @@ function CouchIndexPage() {
this.addDatabase = function() {
$.showDialog("_create_database.html", {
- submit: function(data) {
+ submit: function(data, callback) {
if (!data.name || data.name.length == 0) {
- return {name: "Please enter a name."};
- }
- try {
- new CouchDB(data.name).createDb();
- } catch (e) {
- return {name: e.reason};
+ callback({name: "Please enter a name."});
+ return;
}
- if (window !== parent) parent.setTimeout("updateDatabaseList()", 500);
- window.open("database.html?" + data.name, "content");
+ $.couch.db(data.name).create({
+ error: function(status, id, reason) { callback({name: reason}) },
+ success: function(resp) {
+ if (window !== parent) parent.setTimeout("updateDatabaseList()", 500);
+ location.href = "database.html?" + encodeURIComponent(data.name);
+ callback();
+ }
+ });
}
});
return false;
}
this.updateDatabaseListing = function() {
- var allDbs = CouchDB.allDbs();
- for (var i = 0; i < allDbs.length; i++) {
- var dbName = allDbs[i];
- var info = new CouchDB(dbName).info();
- $("#databases tbody.content").append(
- "<tr><th><a href='database.html?" + dbName + "'>" +
- dbName + "</a></th><td class='size'>" + prettyPrintSize(info.disk_size) +
- "</td><td class='count'>" + info.doc_count +
- "</td><td class='seq'>" + info.update_seq + "</td></tr>");
- $("#databases tbody tr:odd").addClass("odd");
- $("#databases tbody.footer tr td").text(allDbs.length + " database(s)");
- }
+ $(document.body).addClass("loading");
+ $.couch.allDbs({
+ success: function(dbs) {
+ $.each(dbs, function(idx, dbName) {
+ $("#databases tbody.content").append("<tr>" +
+ "<th><a href='database.html?" + encodeURIComponent(dbName) + "'>" +
+ dbName + "</a></th>" +
+ "<td class='size'></td><td class='count'></td>" +
+ "<td class='seq'></td></tr>");
+ $.couch.db(dbName).info({
+ success: function(info) {
+ $("#databases tbody.content tr:eq(" + idx + ")")
+ .find("td.size").text(prettyPrintSize(info.disk_size)).end()
+ .find("td.count").text(info.doc_count).end()
+ .find("td.seq").text(info.update_seq);
+ if (idx == dbs.length - 1) {
+ $(document.body).removeClass("loading");
+ }
+ }
+ });
+ });
+ $("#databases tbody tr:odd").addClass("odd");
+ $("#databases tbody.footer tr td").text(dbs.length + " database(s)");
+ }
+ });
}
}
@@ -56,7 +71,7 @@ function CouchIndexPage() {
*/
function CouchDatabasePage() {
var urlParts = location.search.substr(1).split("/");
- var dbName = urlParts.shift();
+ var dbName = decodeURIComponent(urlParts.shift());
var viewName = (urlParts.length > 0) ? urlParts.join("/") : null;
if (viewName) {
viewName = decodeURIComponent(viewName);
@@ -64,7 +79,7 @@ function CouchDatabasePage() {
} else {
viewName = $.cookies.get(dbName + ".view") || "";
}
- var db = new CouchDB(dbName);
+ var db = $.couch.db(dbName);
this.dbName = dbName;
this.viewName = viewName;
@@ -74,100 +89,138 @@ function CouchDatabasePage() {
this.addDocument = function() {
$.showDialog("_create_document.html", {
- submit: function(data) {
- try {
- var result = db.save(data.docid ? {_id: data.docid} : {});
- } catch (err) {
- return {docid: err.reason};
- }
- location.href = "document.html?" + dbName + "/" + result.id;
+ submit: function(data, callback) {
+ db.saveDoc(data.docid ? {_id: data.docid} : {}, {
+ error: function(status, error, reason) {
+ callback({docid: reason});
+ },
+ success: function(resp) {
+ location.href = "document.html?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(resp.id);
+ }
+ });
}
});
}
this.compactDatabase = function() {
$.showDialog("_compact_database.html", {
- submit: function() {
- db.compact();
+ submit: function(data, callback) {
+ db.compact({
+ success: function(resp) {
+ callback();
+ }
+ });
}
});
}
this.deleteDatabase = function() {
$.showDialog("_delete_database.html", {
- submit: function() {
- db.deleteDb();
- location.href = "index.html";
- if (window !== null) {
- parent.$("#dbs li").filter(function(index) {
- return $("a", this).text() == dbName;
- }).remove();
- }
+ submit: function(data, callback) {
+ db.drop({
+ success: function(resp) {
+ callback();
+ location.href = "index.html";
+ if (window !== null) {
+ parent.$("#dbs li").filter(function(index) {
+ return $("a", this).text() == dbName;
+ }).remove();
+ }
+ }
+ });
}
});
}
this.populateViewEditor = function() {
if (viewName.match(/^_design\//)) {
- page.revertViewChanges();
- var dirtyTimeout = null;
- function updateDirtyState() {
- clearTimeout(dirtyTimeout);
- dirtyTimeout = setTimeout(function() {
- var buttons = $("#viewcode button.save, #viewcode button.revert");
- page.isDirty = $("#viewcode textarea").val() != page.storedViewCode;
- if (page.isDirty) {
- buttons.removeAttr("disabled");
- } else {
- buttons.attr("disabled", "disabled");
- }
- }, 100);
- }
- $("#viewcode textarea").bind("input", updateDirtyState);
- if ($.browser.msie) { // sorry, browser detection
- $("#viewcode textarea").get(0).onpropertychange = updateDirtyState
- } else if ($.browser.safari) {
- $("#viewcode textarea").bind("paste", updateDirtyState)
- .bind("change", updateDirtyState)
- .bind("keydown", updateDirtyState)
- .bind("keypress", updateDirtyState)
- .bind("keyup", updateDirtyState)
- .bind("textInput", updateDirtyState);
- }
+ page.revertViewChanges(function() {
+ var dirtyTimeout = null;
+ function updateDirtyState() {
+ clearTimeout(dirtyTimeout);
+ dirtyTimeout = setTimeout(function() {
+ var buttons = $("#viewcode button.save, #viewcode button.revert");
+ page.isDirty = $("#viewcode textarea").val() != page.storedViewCode;
+ if (page.isDirty) {
+ buttons.removeAttr("disabled");
+ } else {
+ buttons.attr("disabled", "disabled");
+ }
+ }, 100);
+ }
+ $("#viewcode textarea").bind("input", updateDirtyState);
+ if ($.browser.msie) { // sorry, browser detection
+ $("#viewcode textarea").get(0).onpropertychange = updateDirtyState
+ } else if ($.browser.safari) {
+ $("#viewcode textarea").bind("paste", updateDirtyState)
+ .bind("change", updateDirtyState)
+ .bind("keydown", updateDirtyState)
+ .bind("keypress", updateDirtyState)
+ .bind("keyup", updateDirtyState)
+ .bind("textInput", updateDirtyState);
+ }
+ });
}
}
this.populateViewsMenu = function() {
- var designDocs = db.allDocs({startkey: "_design/", endkey: "_design/ZZZ"});
- $("#switch select").each(function() {
- this.options.length = 3;
- for (var i = 0; i < designDocs.rows.length; i++) {
- var doc = db.open(designDocs.rows[i].id);
- var optGroup = $("<optgroup></optgroup>").attr("label", doc._id.substr(8));
- for (var name in doc.views) {
- if (!doc.views.hasOwnProperty(name)) continue;
- $("<option></option>").attr("value", doc._id + "/" + name).text(name)
- .appendTo(optGroup);
+ var select = $("#switch select");
+ db.allDocs({startkey: "_design/", endkey: "_design/ZZZ",
+ success: function(resp) {
+ select[0].options.length = 3;
+ for (var i = 0; i < resp.rows.length; i++) {
+ db.openDoc(resp.rows[i].id, {
+ success: function(doc) {
+ var optGroup = $("<optgroup></optgroup>").attr("label", doc._id.substr(8));
+ for (var name in doc.views) {
+ if (!doc.views.hasOwnProperty(name)) continue;
+ var option = $("<option></option>").attr("value", doc._id + "/" + name).text(name)
+ .appendTo(optGroup);
+ if (doc._id + "/" + name == viewName) {
+ option[0].selected = true;
+ }
+ }
+ optGroup.appendTo(select);
+ }
+ });
}
- optGroup.appendTo(this);
}
- this.autocomplete = false;
});
+ if (!viewName.match(/^_design\//)) {
+ $.each(["_all_docs", "_design_docs", "_temp_view"], function(idx, name) {
+ if (viewName == name) {
+ select[0].options[idx].selected = true;
+ }
+ });
+ }
}
- this.revertViewChanges = function() {
+ this.revertViewChanges = function(callback) {
if (!page.storedViewCode) {
var viewNameParts = viewName.split("/");
var designDocId = viewNameParts[1];
var localViewName = viewNameParts[2];
- var designDoc = db.open(["_design", designDocId].join("/"));
- if (designDoc) {
- page.storedViewCode = designDoc.views[localViewName];
- }
+ db.openDoc(["_design", designDocId].join("/"), {
+ error: function(status, error, reason) {
+ if (status == 404) {
+ $.cookies.remove(dbName + ".view");
+ location.reload();
+ }
+ },
+ success: function(resp) {
+ page.storedViewCode = resp.views[localViewName];
+ $("#viewcode textarea").val(page.storedViewCode);
+ $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
+ if (callback) callback();
+ }
+ });
+ } else {
+ $("#viewcode textarea").val(page.storedViewCode);
+ page.isDirty = false;
+ $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
+ if (callback) callback();
}
- $("#viewcode textarea").val(page.storedViewCode);
- page.isDirty = false;
- $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
}
this.saveViewAs = function() {
@@ -181,49 +234,68 @@ function CouchDatabasePage() {
$.showDialog("_save_view_as.html", {
load: function(elem) {
$("#input_docid", elem).val(designDocId).suggest(function(text, callback) {
- var matches = [];
- var docs = db.allDocs({
+ db.allDocs({
count: 10, startkey: "_design/" + text,
- endkey: "_design/" + text + "ZZZZ"
+ endkey: "_design/" + text + "ZZZZ",
+ success: function(docs) {
+ var matches = [];
+ for (var i = 0; i < docs.rows.length; i++) {
+ matches[i] = docs.rows[i].id.substr(8);
+ }
+ callback(matches);
+ }
});
- for (var i = 0; i < docs.rows.length; i++) {
- matches[i] = docs.rows[i].id.substr(8);
- }
- callback(matches);
});
$("#input_name", elem).val(localViewName).suggest(function(text, callback) {
- var matches = [];
- try {
- var doc = db.open("_design/" + $("#input_docid").val());
- } catch (err) {
- return;
- }
- if (!doc || !doc.views) return;
- for (var viewName in doc.views) {
- if (!doc.views.hasOwnProperty(viewName) || !viewName.match("^" + text)) {
- continue;
+ db.openDoc("_design/" + $("#input_docid").val(), {
+ error: function() {}, // ignore
+ success: function(doc) {
+ var matches = [];
+ if (!doc.views) return;
+ for (var viewName in doc.views) {
+ if (!doc.views.hasOwnProperty(viewName) || !viewName.match("^" + text)) {
+ continue;
+ }
+ matches.push(viewName);
+ }
+ callback(matches);
}
- matches.push(viewName);
- }
- callback(matches);
+ });
});
},
- submit: function(data) {
+ submit: function(data, callback) {
if (!data.docid || !data.name) {
var errors = {};
if (!data.docid) errors.docid = "Please enter a document ID";
if (!data.name) errors.name = "Please enter a view name";
- return errors;
+ callback(errors);
+ } else {
+ var viewCode = $("#viewcode textarea").val();
+ var docId = ["_design", data.docid].join("/");
+ function save(doc) {
+ if (!doc) doc = {_id: docId, language: "text/javascript"};
+ if (doc.views === undefined) doc.views = {};
+ doc.views[data.name] = viewCode;
+ db.saveDoc(doc, {
+ success: function(resp) {
+ callback();
+ page.isDirty = false;
+ location.href = "database.html?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(doc._id) +
+ "/" + encodeURIComponent(data.name);
+ }
+ });
+ }
+ db.openDoc(docId, {
+ error: function(status, error, reason) {
+ if (status == 404) save(null);
+ else alert(reason);
+ },
+ success: function(doc) {
+ save(doc);
+ }
+ });
}
- var viewCode = $("#viewcode textarea").val();
- var docId = ["_design", data.docid].join("/");
- var designDoc = db.open(docId);
- if (!designDoc) designDoc = {_id: docId, language: "text/javascript"};
- if (designDoc.views === undefined) designDoc.views = {};
- designDoc.views[data.name] = viewCode;
- db.save(designDoc);
- page.isDirty = false;
- location.href = "database.html?" + dbName + "/" + designDoc._id + "/" + data.name;
}
});
}
@@ -232,24 +304,34 @@ function CouchDatabasePage() {
var viewNameParts = viewName.split("/");
var designDocId = viewNameParts[1];
var localViewName = viewNameParts[2];
- var designDoc = db.open(["_design", designDocId].join("/"));
- var viewCode = $("#viewcode textarea").val();
- designDoc.views[localViewName] = viewCode;
- db.save(designDoc);
- page.isDirty = false;
- $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled");
+ $(document.body).addClass("loading");
+ db.openDoc(["_design", designDocId].join("/"), {
+ success: function(doc) {
+ doc.views[localViewName] = $("#viewcode textarea").val();
+ db.saveDoc(doc, {
+ success: function(resp) {
+ page.isDirty = false;
+ $("#viewcode button.revert, #viewcode button.save")
+ .attr("disabled", "disabled");
+ $(document.body).removeClass("loading");
+ }
+ });
+ }
+ });
}
this.updateDesignDocLink = function() {
if (viewName && /^_design/.test(viewName)) {
var docId = "_design/" + viewName.split("/")[1];
- $("#designdoc-link").attr("href", "document.html?" + dbName + "/" + docId).text(docId);
+ $("#designdoc-link").attr("href", "document.html?" +
+ encodeURIComponent(dbName) + "/" + encodeURIComponent(docId)).text(docId);
} else {
$("#designdoc-link").removeAttr("href").text("");
}
}
this.updateDocumentListing = function(options) {
+ $(document.body).addClass("loading");
if (options === undefined) options = {};
if (options.count === undefined) {
options.count = parseInt($("#perpage").val(), 10);
@@ -265,99 +347,92 @@ function CouchDatabasePage() {
$("#documents tbody.content").empty();
this.updateDesignDocLink();
- var result = null;
+ function handleResults(resp) {
+ if (resp.offset === undefined) {
+ resp.offset = 0;
+ }
+ if (resp.offset > 0) {
+ $("#paging a.prev").attr("href", "#" + (resp.offset - options.count)).click(function() {
+ var firstDoc = resp.rows[0];
+ page.updateDocumentListing({
+ startkey: firstDoc.key !== undefined ? firstDoc.key : null,
+ startkey_docid: firstDoc.id,
+ skip: 1,
+ count: -options.count
+ });
+ return false;
+ });
+ } else {
+ $("#paging a.prev").removeAttr("href");
+ }
+ if (resp.total_rows - resp.offset > options.count) {
+ $("#paging a.next").attr("href", "#" + (resp.offset + options.count)).click(function() {
+ var lastDoc = resp.rows[resp.rows.length - 1];
+ page.updateDocumentListing({
+ startkey: lastDoc.key !== undefined ? lastDoc.key : null,
+ startkey_docid: lastDoc.id,
+ skip: 1,
+ count: options.count
+ });
+ return false;
+ });
+ } else {
+ $("#paging a.next").removeAttr("href");
+ }
+
+ for (var i = 0; i < resp.rows.length; i++) {
+ var row = resp.rows[i];
+ var tr = $("<tr></tr>");
+ var key = row.key;
+ $("<td class='key'><a href='document.html?" + encodeURIComponent(db.name) +
+ "/" + encodeURIComponent(row.id) + "'><em></em><br>" +
+ "<span class='docid'>ID:&nbsp;" + row.id + "</span></a></td>")
+ .find("em").text(key !== null ? prettyPrintJSON(key, 0, "") : "null").end()
+ .appendTo(tr);
+ var value = row.value;
+ $("<td class='value'></td>").text(
+ value !== null ? prettyPrintJSON(value, 0, "") : "null"
+ ).appendTo(tr).dblclick(function() {
+ location.href = this.previousSibling.firstChild.href;
+ });
+ tr.appendTo("#documents tbody.content");
+ }
+
+ $("#documents tbody tr:odd").addClass("odd");
+ $("#documents tbody.footer td span").text(
+ "Showing " + Math.min(resp.total_rows, resp.offset + 1) + "-" +
+ (resp.offset + resp.rows.length) + " of " + resp.total_rows +
+ " document" + (resp.total_rows != 1 ? "s" : ""));
+ $(document.body).removeClass("loading");
+ }
+ options.success = handleResults;
+ options.error = function(error, reason) {
+ alert(reason);
+ }
+
if (!viewName) {
$("#switch select").get(0).selectedIndex = 0;
- result = db.allDocs(options);
+ db.allDocs(options);
} else {
- $("#switch select").each(function() {
- for (var i = 0; i < this.options.length; i++) {
- if (this.options[i].value == viewName) {
- this.selectedIndex = i;
- break;
- }
- }
- });
- docs = [];
if (viewName == "_temp_view") {
$("#viewcode").show().addClass("expanded");
var query = $("#viewcode textarea").val();
$.cookies.set(db.name + ".query", query);
- try {
- result = db.query(query, options);
- } catch (e) {
- alert(e.reason ? e.reason : e.message);
- return;
- }
+ db.query(query, options);
} else if (viewName == "_design_docs") {
options.startkey = options.descending ? "_design/ZZZZ" : "_design/";
options.endkey = options.descending ? "_design/" : "_design/ZZZZ";
- result = db.allDocs(options);
+ db.allDocs(options);
} else {
$("#viewcode").show();
var currentViewCode = $("#viewcode textarea").val();
- if (currentViewCode != page.storedViewCode) {
- result = db.query(currentViewCode, options);
+ if (page.isDirty) {
+ db.query(currentViewCode, options);
} else {
- result = db.view(viewName.substr(8), options);
+ db.view(viewName.substr(8), options);
}
}
}
- if (result.offset === undefined) {
- result.offset = 0;
- }
- if (result.offset > 0) {
- $("#paging a.prev").attr("href", "#" + (result.offset - options.count)).click(function() {
- var firstDoc = result.rows[0];
- page.updateDocumentListing({
- startkey: firstDoc.key !== undefined ? firstDoc.key : null,
- startkey_docid: firstDoc.id,
- skip: 1,
- count: -options.count
- });
- return false;
- });
- } else {
- $("#paging a.prev").removeAttr("href");
- }
- if (result.total_rows - result.offset > options.count) {
- $("#paging a.next").attr("href", "#" + (result.offset + options.count)).click(function() {
- var lastDoc = result.rows[result.rows.length - 1];
- page.updateDocumentListing({
- startkey: lastDoc.key !== undefined ? lastDoc.key : null,
- startkey_docid: lastDoc.id,
- skip: 1,
- count: options.count
- });
- return false;
- });
- } else {
- $("#paging a.next").removeAttr("href");
- }
-
- for (var i = 0; i < result.rows.length; i++) {
- var row = result.rows[i];
- var tr = $("<tr></tr>");
- var key = row.key;
- $("<td class='key'><a href='document.html?" + db.name + "/" + row.id + "'>" +
- "<em></em><br><span class='docid'>ID:&nbsp;" + row.id +
- "</span></a></td>").find("em").text(
- key !== null ? prettyPrintJSON(key, 0, "") : "null"
- ).end().appendTo(tr);
- var value = row.value;
- $("<td class='value'></td>").text(
- value !== null ? prettyPrintJSON(value, 0, "") : "null"
- ).appendTo(tr).dblclick(function() {
- location.href = this.previousSibling.firstChild.href;
- });
- tr.appendTo("#documents tbody.content");
- }
-
- $("#documents tbody tr:odd").addClass("odd");
- $("#documents tbody.footer td span").text(
- "Showing " + Math.min(result.total_rows, result.offset + 1) + "-" +
- (result.offset + result.rows.length) + " of " + result.total_rows +
- " document" + (result.total_rows != 1 ? "s" : ""));
}
window.onbeforeunload = function() {
@@ -375,103 +450,125 @@ function CouchDatabasePage() {
*/
function CouchDocumentPage() {
var urlParts = location.search.substr(1).split("/");
- var dbName = urlParts.shift();
+ var dbName = decodeURIComponent(urlParts.shift());
var idParts = urlParts.join("/").split("@", 2);
var docId = decodeURIComponent(idParts[0]);
var docRev = (idParts.length > 1) ? idParts[1] : null;
- var db = new CouchDB(dbName);
- var doc = db.open(docId, {revs_info: true});
- var revs = doc._revs_info;
- delete doc._revs_info;
- if (docRev != null) {
- try {
- doc = db.open(docId, {rev: docRev});
- } catch (e) {
- alert("The requested revision was not found. " +
- "You will be redirected back to the latest revision.");
- location.href = "?" + dbName + "/" + docId;
- return;
- }
- }
+ var db = $.couch.db(dbName);
this.dbName = dbName;
this.db = db;
- this.doc = doc;
+ this.docId = docId;
+ this.doc = null;
this.isDirty = false;
page = this;
this.addField = function() {
var fieldName = "unnamed";
var fieldIdx = 1;
- while (doc.hasOwnProperty(fieldName)) {
+ while (page.doc.hasOwnProperty(fieldName)) {
fieldName = "unnamed " + fieldIdx++;
}
- doc[fieldName] = null;
- var row = _addRowForField(fieldName);
+ page.doc[fieldName] = null;
+ var row = _addRowForField(page.doc, fieldName);
page.isDirty = true;
- _editKey(row.find("th"), fieldName);
+ _editKey(page.doc, row.find("th"), fieldName);
}
this.updateFieldListing = function() {
+ $(document.body).addClass("loading");
$("#fields tbody.content").empty();
- var propNames = [];
- for (var prop in doc) {
- if (!doc.hasOwnProperty(prop)) continue;
- propNames.push(prop);
- }
- // Order properties alphabetically, but put internal fields first
- propNames.sort(function(a, b) {
- var a0 = a.charAt(0), b0 = b.charAt(0);
- if (a0 == "_" && b0 != "_") {
- return -1;
- } else if (a0 != "_" && b0 == "_") {
- return 1;
- } else {
- return a < b ? -1 : a != b ? 1 : 0;
+
+ function handleResult(doc, revs) {
+ page.doc = doc;
+ var propNames = [];
+ for (var prop in doc) {
+ if (!doc.hasOwnProperty(prop)) continue;
+ propNames.push(prop);
}
- });
- for (var pi = 0; pi < propNames.length; pi++) {
- _addRowForField(propNames[pi]);
- }
- if (revs.length > 1) {
- var currentIndex = 0;
- for (var i = 0; i < revs.length; i++) {
- if (revs[i].rev == doc._rev) {
- currentIndex = i;
- break;
+ // Order properties alphabetically, but put internal fields first
+ propNames.sort(function(a, b) {
+ var a0 = a.charAt(0), b0 = b.charAt(0);
+ if (a0 == "_" && b0 != "_") {
+ return -1;
+ } else if (a0 != "_" && b0 == "_") {
+ return 1;
+ } else {
+ return a < b ? -1 : a != b ? 1 : 0;
}
+ });
+ for (var pi = 0; pi < propNames.length; pi++) {
+ _addRowForField(doc, propNames[pi]);
}
- if (currentIndex < revs.length - 1) {
- var prevRev = revs[currentIndex + 1].rev;
- $("#paging a.prev").attr("href", "?" + dbName + "/" + docId + "@" + prevRev);
- }
- if (currentIndex > 0) {
- var nextRev = revs[currentIndex - 1].rev;
- $("#paging a.next").attr("href", "?" + dbName + "/" + docId + "@" + nextRev);
+ if (revs.length > 1) {
+ var currentIndex = 0;
+ for (var i = 0; i < revs.length; i++) {
+ if (revs[i].rev == doc._rev) {
+ currentIndex = i;
+ break;
+ }
+ }
+ if (currentIndex < revs.length - 1) {
+ var prevRev = revs[currentIndex + 1].rev;
+ $("#paging a.prev").attr("href", "?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(docId) + "@" + prevRev);
+ }
+ if (currentIndex > 0) {
+ var nextRev = revs[currentIndex - 1].rev;
+ $("#paging a.next").attr("href", "?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(docId) + "@" + nextRev);
+ }
+ $("#fields tbody.footer td span").text("Showing revision " +
+ (revs.length - currentIndex) + " of " + revs.length);
}
- $("#fields tbody.footer td span").text("Showing revision " +
- (revs.length - currentIndex) + " of " + revs.length);
+ $(document.body).removeClass("loading");
}
+
+ db.openDoc(docId, {revs_info: true,
+ success: function(doc) {
+ var revs = doc._revs_info;
+ delete doc._revs_info;
+ if (docRev != null) {
+ db.openDoc(docId, {rev: docRev,
+ error: function(status, error, reason) {
+ alert("The requested revision was not found. " +
+ "You will be redirected back to the latest revision.");
+ location.href = "?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(docId);
+ },
+ success: function(doc) {
+ handleResult(doc, revs);
+ }
+ });
+ } else {
+ handleResult(doc, revs);
+ }
+ }
+ });
}
this.deleteDocument = function() {
$.showDialog("_delete_document.html", {
- submit: function() {
- db.deleteDoc(doc);
- location.href = "database.html?" + dbName;
+ submit: function(data, callback) {
+ db.removeDoc(page.doc, {
+ success: function(resp) {
+ callback();
+ location.href = "database.html?" + encodeURIComponent(dbName);
+ }
+ });
}
});
}
this.saveDocument = function() {
- try {
- db.save(doc);
- } catch (e) {
- alert(e.reason);
- return;
- }
- page.isDirty = false;
- location.href = "?" + dbName + "/" + docId;
+ $(document.body).addClass("loading");
+ db.saveDoc(page.doc, {
+ success: function(resp) {
+ page.isDirty = false;
+ location.href = "?" + encodeURIComponent(dbName) +
+ "/" + encodeURIComponent(docId);
+ }
+ });
}
window.onbeforeunload = function() {
@@ -481,26 +578,26 @@ function CouchDocumentPage() {
}
}
- function _addRowForField(fieldName) {
+ function _addRowForField(doc, fieldName) {
var value = _renderValue(doc[fieldName]);
var row = $("<tr><th></th><td></td></tr>")
.find("th").append($("<b></b>").text(fieldName)).dblclick(function() {
- _editKey(this, $(this).text());
+ _editKey(doc, this, $(this).text());
}).end()
.find("td").append(value).dblclick(function() {
- _editValue(this, $(this).prev("th").text());
+ _editValue(doc, this, $(this).prev("th").text());
}).end()
.appendTo("#fields tbody.content");
if (fieldName != "_id" && fieldName != "_rev") {
row.find("th, td").attr("title", "Double click to edit");
- _initKey(row, fieldName);
+ _initKey(doc, row, fieldName);
_initValue(value);
}
$("#fields tbody tr").removeClass("odd").filter(":odd").addClass("odd");
return row;
}
- function _editKey(cell, fieldName) {
+ function _editKey(doc, cell, fieldName) {
if (fieldName == "_id" || fieldName == "_rev") return;
var th = $(cell);
th.empty();
@@ -523,13 +620,13 @@ function CouchDocumentPage() {
delete doc[fieldName];
th.children().remove();
th.append($("<b></b>").text(newName));
- _initKey(th.parent("tr"), fieldName);
+ _initKey(doc, th.parent("tr"), fieldName);
page.isDirty = true;
}
function cancelChange() {
th.children().remove();
th.append($("<b></b>").text(fieldName));
- _initKey(th.parent("tr"), fieldName);
+ _initKey(doc, th.parent("tr"), fieldName);
}
$("<button type='button' class='apply'></button>").click(function() {
@@ -543,8 +640,8 @@ function CouchDocumentPage() {
input.each(function() { this.focus(); this.select(); });
}
- function _editValue(cell, fieldName) {
- if (fieldName == "_id" || fieldName == "_rev") return;
+ function _editValue(doc, cell, fieldName) {
+ if (!fieldName || fieldName == "_id" || fieldName == "_rev") return;
var td = $(cell);
var value = doc[fieldName];
var needsTextarea = $("dl", td).length > 0 || $("code", td).text().length > 60;
@@ -591,10 +688,10 @@ function CouchDocumentPage() {
_initValue(value);
}
- $("<button type='button' class='apply'></button>").click(function() {
+ $("<button type='button' class='apply' title='Apply change'></button>").click(function() {
applyChange();
}).appendTo(tools);
- $("<button type='button' class='cancel'></button>").click(function() {
+ $("<button type='button' class='cancel' title='Revert change'></button>").click(function() {
cancelChange();
}).appendTo(tools);
tools.appendTo(td);
@@ -603,7 +700,7 @@ function CouchDocumentPage() {
if (needsTextarea) input.resizable();
}
- function _initKey(row, fieldName) {
+ function _initKey(doc, row, fieldName) {
if (fieldName != "_id" && fieldName != "_rev") {
$("<button type='button' class='delete' title='Delete field'></button>").click(function() {
delete doc[fieldName];
diff --git a/share/www/script/jquery.couch.js b/share/www/script/jquery.couch.js
new file mode 100644
index 00000000..de1cddc9
--- /dev/null
+++ b/share/www/script/jquery.couch.js
@@ -0,0 +1,271 @@
+// 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.
+
+(function($) {
+ $.couch = $.couch || {}
+ $.fn.extend($.couch, {
+
+ allDbs: function(options) {
+ $.ajax({
+ type: "GET", url: "/_all_dbs",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("An error occurred retrieving the list of all databases: " +
+ resp.reason);
+ }
+ }
+ });
+ },
+
+ db: function(name) {
+ return {
+ name: name,
+ uri: "/" + encodeURIComponent(name) + "/",
+
+ compact: function(options) {
+ $.ajax({
+ type: "POST", url: this.uri + "_compact", dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 202 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The database could not be compacted: " + resp.reason);
+ }
+ }
+ });
+ },
+ create: function(options) {
+ $.ajax({
+ type: "PUT", url: this.uri, dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 201 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The database could not be created: " + resp.reason);
+ }
+ }
+ });
+ },
+ drop: function(options) {
+ $.ajax({
+ type: "DELETE", url: this.uri, dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 202 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The database could not be deleted: " + resp.reason);
+ }
+ }
+ });
+ },
+ info: function(options) {
+ $.ajax({
+ type: "GET", url: this.uri, dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("Database information could not be retrieved: " +
+ resp.reason);
+ }
+ }
+ });
+ },
+ allDocs: function(options) {
+ $.ajax({
+ type: "GET", url: this.uri + "_all_docs" + encodeOptions(options),
+ dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("An error occurred retrieving a list of all documents: " +
+ resp.reason);
+ }
+ },
+ });
+ },
+ openDoc: function(docId, options) {
+ $.ajax({
+ type: "GET",
+ url: this.uri + encodeURIComponent(docId) + encodeOptions(options),
+ dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The document could not be retrieved: " + resp.reason);
+ }
+ }
+ });
+ },
+ saveDoc: function(doc, options) {
+ if (doc._id === undefined) {
+ var method = "POST";
+ var uri = this.uri;
+ } else {
+ var method = "PUT";
+ var uri = this.uri + encodeURIComponent(doc._id);
+ }
+ $.ajax({
+ type: method, url: uri + encodeOptions(options),
+ dataType: "json", data: toJSON(doc),
+ contentType: "application/json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json")
+ doc._id = resp.id;
+ doc._rev = resp.rev;
+ if (req.status == 201 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The document could not be saved: " + resp.reason);
+ }
+ }
+ });
+ },
+ removeDoc: function(doc, options) {
+ $.ajax({
+ type: "DELETE",
+ url: this.uri + encodeURIComponent(doc._id) + encodeOptions({rev: doc._rev}),
+ dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 202 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("The document could not be deleted: " + resp.reason);
+ }
+ }
+ });
+ },
+ query: function(fun, options) {
+ if (typeof(fun) != "string")
+ fun = fun.toSource ? fun.toSource() : "(" + fun.toString() + ")";
+ $.ajax({
+ type: "POST", url: this.uri + "_temp_view" + encodeOptions(options),
+ contentType: "text/javascript", data: fun, dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("An error occurred querying the database: " + resp.reason);
+ }
+ }
+ });
+ },
+ view: function(name, options) {
+ $.ajax({
+ type: "GET", url: this.uri + "_view/" + name + encodeOptions(options),
+ dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("An error occurred accessing the view: " + resp.reason);
+ }
+ }
+ });
+ }
+ };
+ },
+
+ info: function(options) {
+ $.ajax({
+ type: "GET", url: "/", dataType: "json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("Server information could not be retrieved: " + resp.reason);
+ }
+ }
+ });
+ },
+
+ replicate: function(source, target, options) {
+ $.ajax({
+ type: "POST", url: "/_replicate", dataType: "json",
+ data: JSON.stringify({source: source, target: target}),
+ contentType: "application/json",
+ complete: function(req) {
+ var resp = $.httpData(req, "json");
+ if (req.status == 200 && options.success) {
+ options.success(resp);
+ } else if (options.error) {
+ options.error(req.status, resp.error, resp.reason);
+ } else {
+ alert("Replication failed: " + resp.reason);
+ }
+ }
+ });
+ }
+
+ });
+
+ // Convert a options object to an url query string.
+ // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
+ function encodeOptions(options) {
+ var buf = []
+ if (typeof(options) == "object" && options !== null) {
+ for (var name in options) {
+ if (name == "error" || name == "success") continue;
+ var value = options[name];
+ if (name == "key" || name == "startkey" || name == "endkey") {
+ value = toJSON(value);
+ }
+ buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
+ }
+ }
+ return buf.length ? "?" + buf.join("&") : "";
+ }
+
+ function toJSON(obj) {
+ return obj !== null ? JSON.stringify(obj) : null;
+ }
+
+})(jQuery);
diff --git a/share/www/script/jquery.dialog.js b/share/www/script/jquery.dialog.js
index 09902758..1fd3d572 100644
--- a/share/www/script/jquery.dialog.js
+++ b/share/www/script/jquery.dialog.js
@@ -75,14 +75,15 @@
$.each($("form :input", dialog).serializeArray(), function(i, field) {
data[field.name] = field.value;
});
- var errors = options.submit(data);
- if (errors == null || errors == {}) {
- dismiss();
- } else {
- for (var name in errors) {
- showError(name, errors[name]);
+ options.submit(data, function callback(errors) {
+ if (errors == null || errors == {}) {
+ dismiss();
+ } else {
+ for (var name in errors) {
+ showError(name, errors[name]);
+ }
}
- }
+ });
return false;
});
});