From 0de41589080a9ebbd172e96a3d2130591c671898 Mon Sep 17 00:00:00 2001 From: Christopher Lenz Date: Fri, 23 May 2008 11:09:17 +0000 Subject: Initial set of changes to Futon to support the recent introduction map/reduce. git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@659501 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/browse/database.html | 20 ++++++++++++----- share/www/script/browse.js | 39 ++++++++++++++++++++++----------- share/www/script/couch.js | 4 ++-- share/www/script/jquery.couch.js | 30 +++++++++++++++++++++----- share/www/script/jquery.resizer.js | 6 ++++-- share/www/style/layout.css | 44 ++++++++++++++++++++++---------------- 6 files changed, 98 insertions(+), 45 deletions(-) (limited to 'share') diff --git a/share/www/browse/database.html b/share/www/browse/database.html index 76990608..51cc19f4 100644 --- a/share/www/browse/database.html +++ b/share/www/browse/database.html @@ -36,7 +36,7 @@ specific language governing permissions and limitations under the License. $(document).ready(function() { $("h1 strong").text(page.db.name); - $("#viewcode label").click(function() { + $("#viewcode span").click(function() { $("#viewcode").toggleClass("expanded"); }); $("#viewcode button.run").click(function() { @@ -51,11 +51,14 @@ specific language governing permissions and limitations under the License. $("#viewcode button.saveas").click(function() { page.saveViewAs(); }); - $("#viewcode textarea").resizable({grippie: $("#viewcode .bottom")}); + $("#viewcode textarea").resizable({ + always: true, + grippie: $("#viewcode .bottom") + }); // Restore preferences/state from cookies var query = $.cookies.get(page.db.name + ".query"); - if (query) $("#viewcode textarea").val(query); + if (query) $("#viewcode_map").val(query); var desc = $.cookies.get(page.db.name + ".desc"); if (desc) $("#documents thead th.key").addClass("desc"); var rowsPerPage = $.cookies.get(page.db.name + ".perpage"); @@ -108,11 +111,18 @@ specific language governing permissions and limitations under the License. +
+ + +
diff --git a/share/www/script/browse.js b/share/www/script/browse.js index 9d821d09..29e76d6a 100644 --- a/share/www/script/browse.js +++ b/share/www/script/browse.js @@ -145,7 +145,8 @@ function CouchDatabasePage() { clearTimeout(dirtyTimeout); dirtyTimeout = setTimeout(function() { var buttons = $("#viewcode button.save, #viewcode button.revert"); - page.isDirty = $("#viewcode textarea").val() != page.storedViewCode; + page.isDirty = ($("#viewcode_map").val() != page.storedViewCode.map) + || ($("#viewcode_reduce").val() != page.storedViewCode.reduce); if (page.isDirty) { buttons.removeAttr("disabled"); } else { @@ -153,7 +154,7 @@ function CouchDatabasePage() { } }, 100); } - $("#viewcode textarea").bind("input", updateDirtyState); + $("#viewcode_map").bind("input", updateDirtyState); if ($.browser.msie) { // sorry, browser detection $("#viewcode textarea").get(0).onpropertychange = updateDirtyState } else if ($.browser.safari) { @@ -214,13 +215,15 @@ function CouchDatabasePage() { }, success: function(resp) { page.storedViewCode = resp.views[localViewName]; - $("#viewcode textarea").val(page.storedViewCode); + $("#viewcode_map").val(page.storedViewCode.map); + $("#viewcode_reduce").val(page.storedViewCode.reduce || ""); $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled"); if (callback) callback(); } }); } else { - $("#viewcode textarea").val(page.storedViewCode); + $("#viewcode_map").val(page.storedViewCode.map); + $("#viewcode_reduce").val(page.storedViewCode.reduce || ""); page.isDirty = false; $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled"); if (callback) callback(); @@ -274,7 +277,10 @@ function CouchDatabasePage() { if (!data.name) errors.name = "Please enter a view name"; callback(errors); } else { - var viewCode = $("#viewcode textarea").val(); + var viewCode = { + map: $("#viewcode_map").val(), + reduce: $("#viewcode_map").val() || undefined + }; var docId = ["_design", data.docid].join("/"); function save(doc) { if (!doc) doc = {_id: docId, language: "javascript"}; @@ -311,7 +317,9 @@ function CouchDatabasePage() { $(document.body).addClass("loading"); db.openDoc(["_design", designDocId].join("/"), { success: function(doc) { - doc.views[localViewName] = $("#viewcode textarea").val(); + var viewDef = doc.views[localViewName]; + viewDef.map = $("#viewcode_map").val(); + viewDef.reduce = $("#viewcode_reduce").val() || undefined; db.saveDoc(doc, { success: function(resp) { page.isDirty = false; @@ -410,8 +418,9 @@ function CouchDatabasePage() { $(document.body).removeClass("loading"); } options.success = handleResults; - options.error = function(error, reason) { - alert(reason); + options.error = function(status, error, reason) { + alert("Error: " + error + "\n\n" + reason); + $(document.body).removeClass("loading"); } if (!viewName) { @@ -420,16 +429,22 @@ function CouchDatabasePage() { } else { if (viewName == "_temp_view") { $("#viewcode").show().addClass("expanded"); - var query = $("#viewcode textarea").val(); - $.cookies.set(db.name + ".query", query); - db.query(query, options); + var mapFun = $("#viewcode_map").val(); + $.cookies.set(db.name + ".map", mapFun); + var reduceFun = $("#viewcode_reduce").val() || null; + if (reduceFun != null) { + $.cookies.set(db.name + ".reduce", reduceFun); + } else { + $.cookies.remove(db.name + ".reduce"); + } + db.query(mapFun, reduceFun, null, options); } else if (viewName == "_design_docs") { options.startkey = options.descending ? "_design/ZZZZ" : "_design/"; options.endkey = options.descending ? "_design/" : "_design/ZZZZ"; db.allDocs(options); } else { $("#viewcode").show(); - var currentViewCode = $("#viewcode textarea").val(); + var currentViewCode = $("#viewcode_map").val(); if (page.isDirty) { db.query(currentViewCode, options); } else { diff --git a/share/www/script/couch.js b/share/www/script/couch.js index 0b2f828c..d1cff6c1 100644 --- a/share/www/script/couch.js +++ b/share/www/script/couch.js @@ -113,7 +113,7 @@ function CouchDB(name) { throw result; return result; } - + this.view = function(viewname, options) { var req = request("GET", this.uri + "_view/" + viewname + encodeOptions(options)); if (req.status == 404) @@ -140,7 +140,7 @@ function CouchDB(name) { throw result; return result; } - + this.compact = function() { var req = request("POST", this.uri + "_compact"); var result = JSON.parse(req.responseText); diff --git a/share/www/script/jquery.couch.js b/share/www/script/jquery.couch.js index 695b0f11..71a3c787 100644 --- a/share/www/script/jquery.couch.js +++ b/share/www/script/jquery.couch.js @@ -15,6 +15,7 @@ $.fn.extend($.couch, { allDbs: function(options) { + options = options || {}; $.ajax({ type: "GET", url: "/_all_dbs", complete: function(req) { @@ -37,6 +38,7 @@ uri: "/" + encodeURIComponent(name) + "/", compact: function(options) { + options = options || {}; $.ajax({ type: "POST", url: this.uri + "_compact", dataType: "json", complete: function(req) { @@ -52,6 +54,7 @@ }); }, create: function(options) { + options = options || {}; $.ajax({ type: "PUT", url: this.uri, dataType: "json", complete: function(req) { @@ -67,6 +70,7 @@ }); }, drop: function(options) { + options = options || {}; $.ajax({ type: "DELETE", url: this.uri, dataType: "json", complete: function(req) { @@ -82,6 +86,7 @@ }); }, info: function(options) { + options = options || {}; $.ajax({ type: "GET", url: this.uri, dataType: "json", complete: function(req) { @@ -98,6 +103,7 @@ }); }, allDocs: function(options) { + options = options || {}; $.ajax({ type: "GET", url: this.uri + "_all_docs" + encodeOptions(options), dataType: "json", @@ -115,6 +121,7 @@ }); }, openDoc: function(docId, options) { + options = options || {}; $.ajax({ type: "GET", url: this.uri + encodeURIComponent(docId) + encodeOptions(options), @@ -132,6 +139,7 @@ }); }, saveDoc: function(doc, options) { + options = options || {}; if (doc._id === undefined) { var method = "POST"; var uri = this.uri; @@ -158,6 +166,7 @@ }); }, removeDoc: function(doc, options) { + options = options || {}; $.ajax({ type: "DELETE", url: this.uri + encodeURIComponent(doc._id) + encodeOptions({rev: doc._rev}), @@ -174,14 +183,22 @@ } }); }, - query: function(fun, options) { - if (typeof(fun) != "string") - fun = fun.toSource ? fun.toSource() : "(" + fun.toString() + ")"; + query: function(mapFun, reduceFun, language, options) { + options = options || {}; + language = language || "javascript" + if (typeof(mapFun) != "string") { + mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")"; + } + var body = {language: language, map: mapFun}; + if (reduceFun != null) { + if (typeof(reduceFun) != "string") + reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")"; + body.reduce = reduceFun; + } $.ajax({ type: "POST", url: this.uri + "_temp_view" + encodeOptions(options), contentType: "application/json", - data: toJSON({language:"javascript", map:fun}), - dataType: "json", + data: toJSON(body), dataType: "json", complete: function(req) { var resp = $.httpData(req, "json"); if (req.status == 200 && options.success) { @@ -195,6 +212,7 @@ }); }, view: function(name, options) { + options = options || {}; $.ajax({ type: "GET", url: this.uri + "_view/" + name + encodeOptions(options), dataType: "json", @@ -214,6 +232,7 @@ }, info: function(options) { + options = options || {}; $.ajax({ type: "GET", url: "/", dataType: "json", complete: function(req) { @@ -230,6 +249,7 @@ }, replicate: function(source, target, options) { + options = options || {}; $.ajax({ type: "POST", url: "/_replicate", dataType: "json", data: JSON.stringify({source: source, target: target}), diff --git a/share/www/script/jquery.resizer.js b/share/www/script/jquery.resizer.js index 8ebd0c66..081c7177 100644 --- a/share/www/script/jquery.resizer.js +++ b/share/www/script/jquery.resizer.js @@ -13,13 +13,15 @@ (function($) { $.fn.resizable = function(options) { - if ($.browser.safari && parseInt($.browser.version) >= 522) - return this; // safari3 and later provides textarea resizing natively options = options || {}; + options.always = options.always || false; options.grippie = options.grippie || null; options.minHeight = options.minHeight || 32; options.maxHeight = options.maxHeight || null; + if (!options.always && $.browser.safari && parseInt($.browser.version) >= 522) + return this; // safari3 and later provides textarea resizing natively + return this.each(function() { var grippie = options.grippie; if (!grippie) grippie = $("
").appendTo(this.parentNode); diff --git a/share/www/style/layout.css b/share/www/style/layout.css index 0632d261..c899198d 100644 --- a/share/www/style/layout.css +++ b/share/www/style/layout.css @@ -251,35 +251,41 @@ ul.suggest-dropdown li.selected { cursor: pointer; background: Highlight; #viewcode { background: #fff; border: 1px solid; border-color: #999 #ddd #ddd #999; margin: 0 0 1em; padding: 0 .5em; } -#viewcode div { background-color: #e9e9e9; border: 1px solid; - border-color: #ddd #ddd #e9e9e9 #ddd; color: #333; margin: 0 -.5em; - padding: 0 .5em 2px; +#viewcode .top, #viewcode .bottom { background-color: #e9e9e9; + border: 1px solid; border-color: #ddd #ddd #e9e9e9 #ddd; color: #333; + margin: 0 -.5em; padding: 0 .5em 2px; } #viewcode .top { color: #aaa; font-size: 95%; } +#viewcode .top span { background: url(../image/twisty.gif) 0 3px no-repeat; + border: none; color: #666; cursor: pointer; display: block; font-size: 90%; + margin: 0; padding: 2px 0 0 15px; +} #viewcode .top a { float: right; font-size: 90%; line-height: 1.4em; padding: 2px 2px 0 0; } #viewcode .top a:link, #viewcode .top a:visited { color: #999; } -#viewcode label { background: url(../image/twisty.gif) 0 3px no-repeat; - color: #666; cursor: pointer; display: block; padding: 2px 0 0 15px; -} -#viewcode div.bottom, #viewcode textarea { display: none; } -#viewcode textarea { border: none; color: #333; max-width: 100%; - min-height: 50px; padding: .5em 0; width: 100%; -} -#viewcode div.bottom { border-bottom: none; padding: 1px 3px; } -#viewcode div.bottom button { font-size: 90%; margin: 0 1em 0 0; +#viewcode .code, #viewcode .bottom { display: none; } +#viewcode .code { float: left; padding: .2em 0; width: 49%; } +#viewcode .code label { font-size: 90%; color: #999; } +#viewcode .code textarea { border: none; border-top: 1px solid #ddd; + color: #333; min-height: 50px; max-width: 98%; padding-top: .5em; + resize: none; +} +#viewcode div.map { border-right: 1px dashed #ccc; margin-right: .5em; } +#viewcode .bottom { border-bottom: none; clear: left; padding: 1px 3px; } +#viewcode .bottom button { font-size: 90%; margin: 0 1em 0 0; padding-left: 2em; padding-right: 2em; } -*html #viewcode div.bottom button { padding: 0 .5em; } -*+html #viewcode div.bottom button { padding: 0 .5em; } -#viewcode div.bottom button.revert, #viewcode div.bottom button.save, -#viewcode div.bottom button.saveas { +*html #viewcode .bottom button { padding: 0 .5em; } +*+html #viewcode .bottom button { padding: 0 .5em; } +#viewcode .bottom button.revert, #viewcode .bottom button.save, +#viewcode .bottom button.saveas { float: right; margin: 0 0 0 1em; } -#viewcode div.bottom button.save { font-weight: bold; } -#viewcode.expanded label { background-position: 0 -96px; } -#viewcode.expanded textarea, #viewcode.expanded div.bottom { display: block; } +#viewcode .bottom button.save { font-weight: bold; } +#viewcode .grippie { background-position: 49% 50%; } +#viewcode.expanded .top span { background-position: 0 -96px; } +#viewcode.expanded .code, #viewcode.expanded .bottom { display: block; } /* Database table */ -- cgit v1.2.3