You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by cm...@apache.org on 2008/04/15 02:07:10 UTC

svn commit: r648074 - in /incubator/couchdb/trunk: ./ share/ share/www/ share/www/browse/ share/www/image/ share/www/script/ share/www/style/

Author: cmlenz
Date: Mon Apr 14 17:07:08 2008
New Revision: 648074

URL: http://svn.apache.org/viewvc?rev=648074&view=rev
Log:
Merged futon-async branch back into trunk.

Added:
    incubator/couchdb/trunk/share/www/image/progress.gif
      - copied unchanged from r648071, incubator/couchdb/branches/futon-async/share/www/image/progress.gif
    incubator/couchdb/trunk/share/www/image/spinner.gif
      - copied unchanged from r648071, incubator/couchdb/branches/futon-async/share/www/image/spinner.gif
    incubator/couchdb/trunk/share/www/script/jquery.couch.js
      - copied unchanged from r648071, incubator/couchdb/branches/futon-async/share/www/script/jquery.couch.js
Modified:
    incubator/couchdb/trunk/   (props changed)
    incubator/couchdb/trunk/share/Makefile.am
    incubator/couchdb/trunk/share/www/browse/database.html
    incubator/couchdb/trunk/share/www/browse/document.html
    incubator/couchdb/trunk/share/www/browse/index.html
    incubator/couchdb/trunk/share/www/couch_tests.html
    incubator/couchdb/trunk/share/www/index.html
    incubator/couchdb/trunk/share/www/replicator.html
    incubator/couchdb/trunk/share/www/script/browse.js
    incubator/couchdb/trunk/share/www/script/jquery.dialog.js
    incubator/couchdb/trunk/share/www/style/layout.css

Propchange: incubator/couchdb/trunk/
------------------------------------------------------------------------------
    svnmerge-integrated = /incubator/couchdb/trunk:1-648070

Modified: incubator/couchdb/trunk/share/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/Makefile.am?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/Makefile.am (original)
+++ incubator/couchdb/trunk/share/Makefile.am Mon Apr 14 17:07:08 2008
@@ -39,6 +39,7 @@
     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 @@
     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 \

Modified: incubator/couchdb/trunk/share/www/browse/database.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/browse/database.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/browse/database.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/browse/database.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -21,20 +21,21 @@
     <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 @@
         $("#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 @@
 
         $("#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 @@
         });
         $("#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 @@
     </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>

Modified: incubator/couchdb/trunk/share/www/browse/document.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/browse/document.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/browse/document.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/browse/document.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -21,9 +21,9 @@
     <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 @@
         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);

Modified: incubator/couchdb/trunk/share/www/browse/index.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/browse/index.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/browse/index.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/browse/index.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -21,8 +21,8 @@
     <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>

Modified: incubator/couchdb/trunk/share/www/couch_tests.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/couch_tests.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/couch_tests.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/couch_tests.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -48,6 +48,12 @@
         <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>

Modified: incubator/couchdb/trunk/share/www/index.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/index.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/index.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/index.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -28,16 +28,20 @@
     </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 @@
         });
       }
       $(function() {
-        $("#version").text(CouchDB.getVersion());
+        $.couch.info({
+          success: function(info, status) {
+            $("#version").text(info.version);
+          }
+        });
         updateDatabaseList();
       });
     </script>

Modified: incubator/couchdb/trunk/share/www/replicator.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/replicator.html?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/replicator.html [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/replicator.html [utf-8] Mon Apr 14 17:07:08 2008
@@ -20,7 +20,7 @@
     <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 @@
           });
         });
 
-        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 @@
           $("#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>

Modified: incubator/couchdb/trunk/share/www/script/browse.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/script/browse.js?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/script/browse.js [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/script/browse.js [utf-8] Mon Apr 14 17:07:08 2008
@@ -18,35 +18,50 @@
 
   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 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 @@
   } 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 @@
 
   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 @@
     $.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 @@
     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 @@
     $("#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 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;
-      }
-    });
-    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;
+
+    function handleResult(doc, revs) {
+      page.doc = doc;
+      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;
         }
+      });
+      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);
+      }
+      $(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);
+        }
       }
-      $("#fields tbody.footer td span").text("Showing revision " +
-        (revs.length - currentIndex) + " of " + revs.length);
-    }
+    });
   }
 
   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 _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 @@
       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 @@
     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 @@
       _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 @@
     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];

Modified: incubator/couchdb/trunk/share/www/script/jquery.dialog.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/script/jquery.dialog.js?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/script/jquery.dialog.js [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/script/jquery.dialog.js [utf-8] Mon Apr 14 17:07:08 2008
@@ -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;
         });
       });

Modified: incubator/couchdb/trunk/share/www/style/layout.css
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/style/layout.css?rev=648074&r1=648073&r2=648074&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/style/layout.css (original)
+++ incubator/couchdb/trunk/share/www/style/layout.css Mon Apr 14 17:07:08 2008
@@ -33,7 +33,10 @@
 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 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 @@
   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 @@
   -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;