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 2009/12/10 00:06:14 UTC

svn commit: r889013 - in /couchdb/trunk/share/www: script/futon.browse.js script/futon.format.js script/futon.js style/layout.css

Author: cmlenz
Date: Wed Dec  9 23:06:13 2009
New Revision: 889013

URL: http://svn.apache.org/viewvc?rev=889013&view=rev
Log:
A couple of Futon improvements:
 * JSON strings are now displayed as-is in the document view, without the escaping of new-lines and quotes. That dramatically improves readability of multi-line strings.
 * Same goes for editing of JSON string values. When a change to a field value is submitted, and the value is not valid JSON it is assumed to be a string. This improves editing of multi-line strings a lot.
 * Hitting tab in textareas no longer moves focus to the next form field, but simply inserts a tab character at the current caret position.
 * Fixed some font declarations.

Modified:
    couchdb/trunk/share/www/script/futon.browse.js
    couchdb/trunk/share/www/script/futon.format.js
    couchdb/trunk/share/www/script/futon.js
    couchdb/trunk/share/www/style/layout.css

Modified: couchdb/trunk/share/www/script/futon.browse.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/futon.browse.js?rev=889013&r1=889012&r2=889013&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/futon.browse.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/futon.browse.js [utf-8] Wed Dec  9 23:06:13 2009
@@ -189,7 +189,8 @@
                 }
               }, 100);
             }
-            $("#viewcode textarea").bind("input", updateDirtyState);
+            $("#viewcode textarea").enableTabInsertion()
+              .bind("input", updateDirtyState);
             if ($.browser.msie || $.browser.safari) {
               $("#viewcode textarea").bind("paste", updateDirtyState)
                                      .bind("change", updateDirtyState)
@@ -720,7 +721,7 @@
           $(this).html($("<pre></pre>").html($.futon.formatJSON(page.doc, {html: true})))
             .makeEditable({allowEmpty: false,
               createInput: function(value) {
-                return $("<textarea rows='8' cols='80' spellcheck='false'></textarea>");
+                return $("<textarea rows='8' cols='80' spellcheck='false'></textarea>").enableTabInsertion();
               },
               prepareInput: function(input) {
                 $(input).makeResizable({vertical: true});
@@ -985,10 +986,10 @@
           return;
         }
 
-        row.find("td").makeEditable({allowEmpty: true,
+        row.find("td").makeEditable({acceptOnBlur: false, allowEmpty: true,
           createInput: function(value) {
             if ($("dl", this).length > 0 || $("code", this).text().length > 60) {
-              return $("<textarea rows='8' cols='40' spellcheck='false'></textarea>");
+              return $("<textarea rows='1' cols='40' spellcheck='false'></textarea>");
             }
             return $("<input type='text' spellcheck='false'>");
           },
@@ -998,12 +999,17 @@
           },
           prepareInput: function(input) {
             if ($(input).is("textarea")) {
-              $(input).makeResizable({vertical: true});
+              var height = Math.min(input.scrollHeight, document.body.clientHeight - 100);
+              $(input).height(height).makeResizable({vertical: true}).enableTabInsertion();
             }
           },
           accept: function(newValue) {
             var fieldName = row.data("name");
-            doc[fieldName] = JSON.parse(newValue);
+            try {
+              doc[fieldName] = JSON.parse(newValue);
+            } catch (err) {
+              doc[fieldName] = newValue;
+            }
             page.isDirty = true;
             if (fieldName == "_id") {
               page.docId = page.doc._id = doc[fieldName];
@@ -1011,7 +1017,11 @@
             }
           },
           populate: function(value) {
-            return $.futon.formatJSON(doc[row.data("name")]);
+            value = doc[row.data("name")];
+            if (typeof(value) == "string") {
+              return value;
+            }
+            return $.futon.formatJSON(value);
           },
           validate: function(value) {
             $("div.error", this).remove();
@@ -1024,12 +1034,7 @@
               }
               return true;
             } catch (err) {
-              var msg = err.message;
-              if (msg == "parseJSON" || msg == "JSON.parse") {
-                msg = "Please enter a valid JSON value (for example, \"string\").";
-              }
-              $("<div class='error'></div>").text(msg).appendTo(this);
-              return false;
+              return true;
             }
           }
         });
@@ -1046,7 +1051,11 @@
             }
             return list;
           } else {
-            return $($.futon.formatJSON(val, {html: true}));
+            var html = $.futon.formatJSON(val, {
+              html: true,
+              escapeStrings: false
+            });
+            return $(html);
           }
         }
         var elem = render(value);

Modified: couchdb/trunk/share/www/script/futon.format.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/futon.format.js?rev=889013&r1=889012&r2=889013&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/futon.format.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/futon.format.js [utf-8] Wed Dec  9 23:06:13 2009
@@ -17,6 +17,7 @@
     // JSON pretty printing
     formatJSON: function(val, options) {
       options = $.extend({
+        escapeStrings: true,
         indent: 4,
         linesep: "\n",
         quoteKeys: true
@@ -39,9 +40,14 @@
           case "boolean":
           case "number":
           case "string":
-            var retval = JSON.stringify(val);
+            var retval = val;
+            if (type == "string" && !options.escapeStrings) {
+              retval = indentLines(retval, tab);
+            } else {
+              retval = escape(JSON.stringify(val));
+            }
             if (options.html) {
-              retval = "<code class='" + type + "'>" + escape(retval) + "</code>";
+              retval = "<code class='" + type + "'>" + retval + "</code>";
             }
             return retval;
 
@@ -95,6 +101,14 @@
         }
       }
 
+      function indentLines(text, tab) {
+        var lines = text.split("\n");
+        for (var i in lines) {
+          lines[i] = (i > 0 ? tab : "") + escape(lines[i]);
+        }
+        return lines.join("<br>");
+      }
+
       return format(val, 1);
     },
 
@@ -112,4 +126,5 @@
     }
 
   });
+
 })(jQuery);

Modified: couchdb/trunk/share/www/script/futon.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/futon.js?rev=889013&r1=889012&r2=889013&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/futon.js (original)
+++ couchdb/trunk/share/www/script/futon.js Wed Dec  9 23:06:13 2009
@@ -159,6 +159,26 @@
     });
   }
 
+  $.fn.enableTabInsertion = function(chars) {
+    chars = chars || "\t";
+    var width = chars.length;
+    return this.keydown(function(evt) {
+      if (evt.keyCode == 9) {
+        var v = this.value;
+        var start = this.selectionStart;
+        var scrollTop = this.scrollTop;
+        if (start !== undefined) {
+          this.value = v.slice(0, start) + chars + v.slice(start);
+          this.selectionStart = this.selectionEnd = start + width;
+        } else {
+          document.selection.createRange().text = chars;
+          this.caretPos += width;
+        }
+        return false;
+      }
+    });
+  }
+
   $(document)
     .ajaxStart(function() { $(this.body).addClass("loading"); })
     .ajaxStop(function() { $(this.body).removeClass("loading"); });

Modified: couchdb/trunk/share/www/style/layout.css
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/style/layout.css?rev=889013&r1=889012&r2=889013&view=diff
==============================================================================
--- couchdb/trunk/share/www/style/layout.css (original)
+++ couchdb/trunk/share/www/style/layout.css Wed Dec  9 23:06:13 2009
@@ -23,7 +23,7 @@
 
 h1 { background: #333; border-right: 2px solid #111;
   border-bottom: 1px solid #333; color: #999;
-  font: 125% normal Arial,Helvetica,sans-serif; height: 32px;
+  font: normal 125% Arial,Helvetica,sans-serif; height: 32px;
   line-height: 32px; margin: 0; padding: 0 0 0 .5em; position: relative;
 }
 h1 :link, h1 :visited, h1 strong { padding: .4em .5em; }
@@ -44,7 +44,9 @@
 
 hr { border: 1px solid #999; border-width: 1px 0 0; }
 dl dt { font-weight: bold; }
-code, tt, pre { font-family: "DejaVu Sans Mono",Monaco,monospace; }
+code, tt, pre {
+  font-family: "DejaVu Sans Mono",Menlo,Courier,monospace;
+}
 code.key { color: #333; font-weight: bold; }
 code.string { color: #393; }
 code.number, code.boolean { color: #339; }
@@ -56,7 +58,10 @@
   border-color: #999 #ddd #ddd #999; margin: 0; padding: 1px;
 }
 input.placeholder { color: #999; }
-textarea { font-family: "DejaVu Sans Mono",Monaco,monospace; font-size: 100%; }
+textarea {
+  font-family: "DejaVu Sans Mono",Menlo,Courier,monospace;
+  font-size: 100%;
+}
 fieldset { border: none; font-size: 95%; margin: 0; padding: .2em 0 0; }
 fieldset legend { color: #666; font-weight: bold; padding: 0; }
 fieldset input, fieldset select { font-size: 95%; }
@@ -370,7 +375,7 @@
 
 #documents thead th { width: 50%; }
 #documents tbody.content td { color: #999;
-  font: normal 11px "DejaVu Sans Mono",Monaco,monospace;
+  font: normal 11px "DejaVu Sans Mono",Menlo,Courier,monospace;
 }
 #documents tbody.content td.key { color: #333; }
 #documents tbody.content td.key a { display: block; }
@@ -411,8 +416,13 @@
   padding-right: 48px;
 }
 #fields tbody.content td code { display: block; font-size: 11px;
-  padding: 2px 2px 2px 3px;
+  padding: 2px 2px 2px 3px; position: relative;
+}
+#fields tbody.content td code.string:before { color: #ccc; content: "“";
+  position: absolute; left: -4px;
 }
+#fields tbody.content td code.string:after { color: #ccc; content: "”"; }
+
 #fields tbody.content td dl { margin: 0; padding: 0; }
 #fields tbody.content td dt {
   background: transparent url(../image/toggle-collapse.gif) 0 3px no-repeat;
@@ -429,23 +439,33 @@
   float: left; margin-left: 0; padding-left: 2px; padding-right: .5em;
   padding-top: 2px;
 }
-#fields tbody.content input, #fields tbody.content textarea, #fields tbody.source textarea {
+#fields tbody.content td dd code.string { left: 4px; text-indent: -6px;
+  white-space: pre-wrap;
+}
+#fields tbody.content td dd code.string:before { position: static; }
+#fields tbody.content input, #fields tbody.content textarea,
+#fields tbody.source textarea {
   background: #fff; border: 1px solid; border-color: #999 #ddd #ddd #999;
   margin: 0; padding: 1px; width: 100%;
 }
 #fields tbody.content th input { font-family: inherit; font-size: inherit;
   font-weight: bold;
 }
-#fields tbody.content td input, #fields tbody.content td textarea, #fields tbody.source textarea {
-  font: 11px normal "DejaVu Sans Mono",Monaco,monospace;
+#fields tbody.content td input, #fields tbody.content td textarea,
+#fields tbody.source textarea {
+  font: normal 11px "DejaVu Sans Mono",Menlo,Courier,monospace;
 }
 #fields tbody.content input.invalid,
 #fields tbody.content textarea.invalid,
 #fields tbody.source textarea.invalid {
   background: #f9f4f4; border-color: #b66 #ebb #ebb #b66;
 }
-#fields tbody.content div.grippie, #fields tbody.source div.gripple { padding: 0 1px; width: 100%; }
-#fields tbody.content div.error, #fields tbody.source div.error { color: #d33; }
+#fields tbody.content div.grippie, #fields tbody.source div.grippie {
+  padding: 0 1px; width: 100%;
+}
+#fields tbody.content div.error, #fields tbody.source div.error {
+  color: #d33;
+}
 
 #fields tbody.content td ul.attachments { list-style: none; margin: 0;
   padding: 0;
@@ -527,7 +547,7 @@
 #config tbody td.value code.editinline-container { padding: 0; }
 #config tbody td input {
   background: #fff; border: 1px solid; border-color: #999 #ddd #ddd #999;
-  font: 11px normal "DejaVu Sans Mono",Monaco,monospace;
+  font: normal 11px "DejaVu Sans Mono",Menlo,Courier,monospace;
   margin: 0; padding: 1px; width: 100%;
 }
 
@@ -557,5 +577,6 @@
 
 #status tr.none th { color: #666; font-weight: normal; }
 #status td.object, #status td.pid {
-  font-family: "DejaVu Sans Mono",Monaco,monospace; font-size: 11px;
+  font-family: "DejaVu Sans Mono",Menlo,Courier,monospace;
+  font-size: 11px;
 }