summaryrefslogtreecommitdiff
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
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
-rw-r--r--share/Makefile.am2
-rw-r--r--share/www/browse/database.html22
-rw-r--r--share/www/browse/document.html9
-rw-r--r--share/www/browse/index.html2
-rw-r--r--share/www/couch_tests.html6
-rw-r--r--share/www/image/progress.gifbin0 -> 10819 bytes
-rw-r--r--share/www/image/spinner.gifbin10819 -> 1849 bytes
-rw-r--r--share/www/index.html26
-rw-r--r--share/www/replicator.html52
-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
-rw-r--r--share/www/style/layout.css11
13 files changed, 730 insertions, 333 deletions
diff --git a/share/Makefile.am b/share/Makefile.am
index fd4eff0e..f1f44b05 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -39,6 +39,7 @@ nobase_dist_pkgdata_DATA = \
www/image/order-asc.gif \
www/image/order-desc.gif \
www/image/path.gif \
+ www/image/progress.gif \
www/image/run-mini.gif \
www/image/run.gif \
www/image/running.gif \
@@ -58,6 +59,7 @@ nobase_dist_pkgdata_DATA = \
www/script/couch_tests.js \
www/script/jquery.js \
www/script/jquery.cookies.js \
+ www/script/jquery.couch.js \
www/script/jquery.dialog.js \
www/script/jquery.resizer.js \
www/script/jquery.suggest.js \
diff --git a/share/www/browse/database.html b/share/www/browse/database.html
index e52c3b8a..c685baad 100644
--- a/share/www/browse/database.html
+++ b/share/www/browse/database.html
@@ -21,20 +21,21 @@ specific language governing permissions and limitations under the License.
<script src="../script/json2.js"></script>
<script src="../script/jquery.js"></script>
<script src="../script/jquery.cookies.js"></script>
+ <script src="../script/jquery.couch.js"></script>
<script src="../script/jquery.dialog.js"></script>
<script src="../script/jquery.resizer.js"></script>
<script src="../script/jquery.suggest.js"></script>
- <script src="../script/couch.js"></script>
<script src="../script/browse.js"></script>
<script src="../script/pprint.js"></script>
<script>
var page = new CouchDatabasePage();
if (window != parent) {
- parent.updateNavigation(location.pathname, location.search.split("/", 2)[0]);
+ parent.updateNavigation(location.pathname,
+ encodeURIComponent(location.search.split("/", 2)[0]));
}
$(document).ready(function() {
- $("h1 strong").text(page.dbName);
+ $("h1 strong").text(page.db.name);
$("#viewcode label").click(function() {
$("#viewcode").toggleClass("expanded");
});
@@ -53,11 +54,11 @@ specific language governing permissions and limitations under the License.
$("#viewcode textarea").resizable({grippie: $("#viewcode .bottom")});
// Restore preferences/state from cookies
- var query = $.cookies.get(page.dbName + ".query");
+ var query = $.cookies.get(page.db.name + ".query");
if (query) $("#viewcode textarea").val(query);
- var desc = $.cookies.get(page.dbName + ".desc");
+ var desc = $.cookies.get(page.db.name + ".desc");
if (desc) $("#documents thead th.key").addClass("desc");
- var rowsPerPage = $.cookies.get(page.dbName + ".perpage");
+ var rowsPerPage = $.cookies.get(page.db.name + ".perpage");
if (rowsPerPage) $("#perpage").val(rowsPerPage);
page.populateViewsMenu();
@@ -66,8 +67,9 @@ specific language governing permissions and limitations under the License.
$("#switch select").change(function() {
var viewName = $(this).val();
- if (!viewName) $.cookies.remove(page.dbName + ".view");
- location.href = "?" + page.dbName + (viewName ? "/" + viewName : "");
+ if (!viewName) $.cookies.remove(page.db.name + ".view");
+ location.href = "?" + encodeURIComponent(page.db.name) +
+ (viewName ? "/" + encodeURIComponent(viewName) : "");
});
$("#documents thead th.key").click(function() {
$(this).toggleClass("desc");
@@ -75,7 +77,7 @@ specific language governing permissions and limitations under the License.
});
$("#perpage").change(function() {
page.updateDocumentListing();
- $.cookies.set(page.dbName + ".perpage", this.value);
+ $.cookies.set(page.db.name + ".perpage", this.value);
});
$("#toolbar button.add").click(page.addDocument);
$("#toolbar button.compact").click(page.compactDatabase);
@@ -91,7 +93,7 @@ specific language governing permissions and limitations under the License.
</h1>
<div id="wrap">
<div id="switch">
- <label>Select view: <select>
+ <label>Select view: <select autocomplete="false">
<option value="">All documents</option>
<option value="_design_docs">Design documents</option>
<option value="_temp_view">Custom query…</option>
diff --git a/share/www/browse/document.html b/share/www/browse/document.html
index f7876539..db3de935 100644
--- a/share/www/browse/document.html
+++ b/share/www/browse/document.html
@@ -21,9 +21,9 @@ specific language governing permissions and limitations under the License.
<script src="../script/json2.js"></script>
<script src="../script/jquery.js"></script>
<script src="../script/jquery.cookies.js"></script>
+ <script src="../script/jquery.couch.js"></script>
<script src="../script/jquery.dialog.js"></script>
<script src="../script/jquery.resizer.js"></script>
- <script src="../script/couch.js"></script>
<script src="../script/browse.js"></script>
<script src="../script/pprint.js"></script>
<script>
@@ -32,13 +32,14 @@ specific language governing permissions and limitations under the License.
var dbLink = $("h1 a.dbname").get(0);
parent.updateNavigation(
location.pathname.replace(/document\.html/, "database.html"),
- location.search.split("/")[0]
+ encodeURIComponent(location.search.split("/")[0])
);
}
$(function() {
- $("h1 a.dbname").text(page.dbName).attr("href", "database.html?" + page.dbName);
- $("h1 strong").text(page.doc._id);
+ $("h1 a.dbname").text(page.dbName)
+ .attr("href", "database.html?" + encodeURIComponent(page.db.name));
+ $("h1 strong").text(page.docId);
page.updateFieldListing();
$("#toolbar button.save").click(page.saveDocument);
$("#toolbar button.add").click(page.addField);
diff --git a/share/www/browse/index.html b/share/www/browse/index.html
index 63ef62e6..1d583825 100644
--- a/share/www/browse/index.html
+++ b/share/www/browse/index.html
@@ -21,8 +21,8 @@ specific language governing permissions and limitations under the License.
<script src="../script/json2.js"></script>
<script src="../script/jquery.js"></script>
<script src="../script/jquery.cookies.js"></script>
+ <script src="../script/jquery.couch.js"></script>
<script src="../script/jquery.dialog.js"></script>
- <script src="../script/couch.js"></script>
<script src="../script/browse.js"></script>
<script src="../script/pprint.js"></script>
<script>
diff --git a/share/www/couch_tests.html b/share/www/couch_tests.html
index a1e4ee6e..83a47771 100644
--- a/share/www/couch_tests.html
+++ b/share/www/couch_tests.html
@@ -48,6 +48,12 @@ specific language governing permissions and limitations under the License.
<li><button class="run">Run All</button></li>
<li><button class="load">Reload</button></li>
</ul>
+ <p class="help">
+ <strong>Note:</strong> Each of the tests will block the browser. If the
+ connection to your CouchDB server is slow, running the tests will take
+ some time, and you'll not be able to do much with your browser while
+ a test is being executed.
+ </p>
<table class="listing" id="tests" cellspacing="0">
<caption>Tests</caption>
<thead>
diff --git a/share/www/image/progress.gif b/share/www/image/progress.gif
new file mode 100644
index 00000000..d84f6537
--- /dev/null
+++ b/share/www/image/progress.gif
Binary files differ
diff --git a/share/www/image/spinner.gif b/share/www/image/spinner.gif
index d84f6537..37f782dd 100644
--- a/share/www/image/spinner.gif
+++ b/share/www/image/spinner.gif
Binary files differ
diff --git a/share/www/index.html b/share/www/index.html
index 8616989a..f74e672d 100644
--- a/share/www/index.html
+++ b/share/www/index.html
@@ -28,16 +28,20 @@ specific language governing permissions and limitations under the License.
</style>
<script src="script/json2.js"></script>
<script src="script/jquery.js"></script>
- <script src="script/couch.js"></script>
+ <script src="script/jquery.couch.js"></script>
<script>
function updateDatabaseList() {
- var dbs = CouchDB.allDbs();
- $("#dbs").empty();
- for (var i = 0; i < dbs.length; i++) {
- var dbname = dbs[i];
- $("#dbs").append("<li><a href='browse/database.html?" + dbname +
- "' target='content'>" + dbname + "</a></li>");
- }
+ var list = $("#dbs").empty();
+ var dbs = $.couch.allDbs({
+ success: function(dbs, status) {
+ for (var i = 0; i < dbs.length; i++) {
+ var dbName = dbs[i];
+ list.append("<li><a href='browse/database.html?" +
+ encodeURIComponent(dbName) + "' target='content'>" + dbName +
+ "</a></li>");
+ }
+ }
+ });
}
function updateNavigation(path, queryString) {
function fixupPath(path) { // hack for IE/Win
@@ -67,7 +71,11 @@ specific language governing permissions and limitations under the License.
});
}
$(function() {
- $("#version").text(CouchDB.getVersion());
+ $.couch.info({
+ success: function(info, status) {
+ $("#version").text(info.version);
+ }
+ });
updateDatabaseList();
});
</script>
diff --git a/share/www/replicator.html b/share/www/replicator.html
index 36dc3d17..684826ce 100644
--- a/share/www/replicator.html
+++ b/share/www/replicator.html
@@ -20,7 +20,7 @@ specific language governing permissions and limitations under the License.
<link rel="stylesheet" href="style/layout.css" type="text/css">
<script src="script/json2.js"></script>
<script src="script/jquery.js"></script>
- <script src="script/couch.js"></script>
+ <script src="script/jquery.couch.js"></script>
<script src="script/pprint.js"></script>
<script>
$(document).ready(function() {
@@ -39,12 +39,17 @@ specific language governing permissions and limitations under the License.
});
});
- var allDbs = CouchDB.allDbs();
- $("fieldset select").each(function() {
- for (var i = 0; i < allDbs.length; i++) {
- $("<option></option>").text(allDbs[i]).appendTo(this);
+
+ $.couch.allDbs({
+ success: function(dbs) {
+ $("fieldset select").each(function() {
+ var select = this;
+ $.each(dbs, function(idx, dbName) {
+ $("<option></option>").text(dbName).appendTo(select);
+ });
+ select.selectedIndex = 0;
+ });
}
- this.selectedIndex = 0;
});
$("button#swap").click(function() {
@@ -73,24 +78,23 @@ specific language governing permissions and limitations under the License.
$("#records tbody.content").empty();
var source = $("#from_local")[0].checked ? $("#from_name").val() : $("#from_url").val();
var target = $("#to_local")[0].checked ? $("#to_name").val() : $("#to_url").val();
- try {
- var results = CouchDB.replicate(source, target);
- } catch (e) {
- alert(e.reason);
- return;
- }
- for (var i = 0; i < results.history.length; i++) {
- var record = results.history[i];
- $("<tr><th></th><td class='seq'></td>" +
- "<td class='read'></td><td class='copied'></td></tr>")
- .find("th").text(record.start_time).end()
- .find("td.seq").text(record.start_last_seq + "–" + record.end_last_seq).end()
- .find("td.read").text(record.docs_read + " (" + record.read_errors + " errors)").end()
- .find("td.copied").text(record.docs_copied + " (" + record.copy_errors + " errors)").end()
- .appendTo("#records tbody.content");
- }
- $("#records tbody tr").removeClass("odd").filter(":odd").addClass("odd");
- $("#records tbody.footer td").text("Replication session " + results.session_id);
+ $(document.body).addClass("loading");
+ $.couch.replicate(source, target, {
+ success: function(resp) {
+ $.each(resp.history, function(idx, record) {
+ $("<tr><th></th><td class='seq'></td>" +
+ "<td class='read'></td><td class='copied'></td></tr>")
+ .find("th").text(record.start_time).end()
+ .find("td.seq").text(record.start_last_seq + "–" + record.end_last_seq).end()
+ .find("td.read").text(record.docs_read + " (" + record.read_errors + " errors)").end()
+ .find("td.copied").text(record.docs_copied + " (" + record.copy_errors + " errors)").end()
+ .appendTo("#records tbody.content");
+ });
+ $("#records tbody tr").removeClass("odd").filter(":odd").addClass("odd");
+ $("#records tbody.footer td").text("Replication session " + resp.session_id);
+ $(document.body).removeClass("loading");
+ }
+ });
});
});
</script>
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;
});
});
diff --git a/share/www/style/layout.css b/share/www/style/layout.css
index 32bbb7e8..62f64587 100644
--- a/share/www/style/layout.css
+++ b/share/www/style/layout.css
@@ -33,7 +33,10 @@ h1 :link, h1 :visited {
h1 :link, h1 :visited { color: #bbb; cursor: pointer;
text-shadow: #333 2px 2px 1px;
}
-h1 strong { color: #fff; text-shadow: #000 2px 2px 4px; }
+h1 strong { color: #fff; padding-right: 25px; text-shadow: #000 2px 2px 4px; }
+body.loading h1 strong {
+ background: url(../image/spinner.gif) right center no-repeat;
+}
hr { border: 1px solid #999; border-width: 1px 0 0; }
dl dt { font-weight: bold; }
@@ -49,6 +52,8 @@ fieldset legend { color: #666; font-weight: bold; padding: 0; }
fieldset input, fieldset select { font-size: 95%; }
fieldset p { margin: .4em; }
+p.help { color: #999; font-size: 90%; margin: 0 2em 1em; }
+
/* Tabular listings */
table.listing { border-collapse: separate; border-spacing: 0;
@@ -195,7 +200,7 @@ ul.suggest-dropdown li.selected { cursor: pointer; background: Highlight;
width: expression(document.body.clientWidth + 'px');
height: expression(document.body.clientHeight + 'px');
}
-#dialog { background: #333 url(../image/spinner.gif) 50% 50% no-repeat;
+#dialog { background: #333 url(../image/progress.gif) 50% 50% no-repeat;
color: #f4f4f4; overflow: hidden; opacity: .95; max-width: 33em;
padding: 1em 1em 0; -moz-border-radius: 7px; -webkit-border-radius: 7px;
-webkit-box-shadow: 4px 4px 6px #333;
@@ -213,7 +218,7 @@ ul.suggest-dropdown li.selected { cursor: pointer; background: Highlight;
-webkit-border-bottom-left-radius: 7px;
-webkit-border-bottom-right-radius: 7px;
}
-#dialog p.help { color: #bbb; margin: 0 0 1em; }
+#dialog p.help { color: #bbb; font-size: 95%; margin: 0 0 1em; }
#dialog fieldset table { margin-top: 1em; }
#dialog fieldset th, #dialog fieldset td { padding: .5em;
vertical-align: top;