summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Lenz <cmlenz@apache.org>2009-12-09 23:06:13 +0000
committerChristopher Lenz <cmlenz@apache.org>2009-12-09 23:06:13 +0000
commit4cd710ae4d2c813f41f8a8bb75595ec2202e7d6e (patch)
tree2fa85dce119601ae598bebc5bf76542b98de3bec
parent995bef1f24aa746200030edc5a4f9e66b280689a (diff)
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. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@889013 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--share/www/script/futon.browse.js37
-rw-r--r--share/www/script/futon.format.js19
-rw-r--r--share/www/script/futon.js20
-rw-r--r--share/www/style/layout.css45
4 files changed, 93 insertions, 28 deletions
diff --git a/share/www/script/futon.browse.js b/share/www/script/futon.browse.js
index e962ee9c..d5b860e2 100644
--- a/share/www/script/futon.browse.js
+++ b/share/www/script/futon.browse.js
@@ -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);
diff --git a/share/www/script/futon.format.js b/share/www/script/futon.format.js
index 7d70bfc2..674f5f8f 100644
--- a/share/www/script/futon.format.js
+++ b/share/www/script/futon.format.js
@@ -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);
diff --git a/share/www/script/futon.js b/share/www/script/futon.js
index f6b1d9f6..31f04a90 100644
--- a/share/www/script/futon.js
+++ b/share/www/script/futon.js
@@ -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"); });
diff --git a/share/www/style/layout.css b/share/www/style/layout.css
index ae442f1c..0b3b6cf5 100644
--- a/share/www/style/layout.css
+++ b/share/www/style/layout.css
@@ -23,7 +23,7 @@ html, body { color: #000; font: normal 90% Arial,Helvetica,sans-serif;
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 @@ body.loading h1 strong {
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 @@ input, select, textarea { background: #fff; border: 1px solid;
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 @@ body.fullwidth #wrap { margin-right: 0; }
#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 @@ body.fullwidth #wrap { margin-right: 0; }
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 @@ body.fullwidth #wrap { margin-right: 0; }
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 @@ body.fullwidth #wrap { margin-right: 0; }
#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 @@ form#replicator p.actions { padding: 1px; clear: left; margin: 0;
#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;
}