From 892590e3a20c617b30ec8f89b0a895b753651e57 Mon Sep 17 00:00:00 2001 From: Christopher Lenz Date: Wed, 14 Jan 2009 21:59:48 +0000 Subject: Add view language selection to Futon, based on patch by Brian Palmer. Closes COUCHDB-202. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@734528 13f79535-47bb-0310-9956-ffa450edef68 --- THANKS | 1 + share/www/database.html | 7 +-- share/www/script/futon.browse.js | 95 ++++++++++++++++++++++++++++++++++---- share/www/script/jquery.resizer.js | 2 +- share/www/style/layout.css | 6 ++- 5 files changed, 93 insertions(+), 18 deletions(-) diff --git a/THANKS b/THANKS index c00a60a4..9e6a19aa 100644 --- a/THANKS +++ b/THANKS @@ -20,6 +20,7 @@ Some of these people are: * Roger Leigh * Jim Lindley * Hunter Morris + * Brian Palmer * Sam Ruby * Dirk Schalge * Carlos Valiente diff --git a/share/www/database.html b/share/www/database.html index 3b968487..0d508794 100644 --- a/share/www/database.html +++ b/share/www/database.html @@ -72,8 +72,6 @@ specific language governing permissions and limitations under the License. }); // Restore preferences/state from cookies - var query = $.cookies.get(page.db.name + ".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"); @@ -137,9 +135,7 @@ specific language governing permissions and limitations under the License.
- + @@ -152,6 +148,7 @@ specific language governing permissions and limitations under the License. + diff --git a/share/www/script/futon.browse.js b/share/www/script/futon.browse.js index 832ac1b7..7528ee6e 100644 --- a/share/www/script/futon.browse.js +++ b/share/www/script/futon.browse.js @@ -117,11 +117,18 @@ this.dbName = dbName; this.viewName = viewName; + this.viewLanguage = "javascript"; this.db = db; this.isDirty = false; this.isTempView = viewName == "_slow_view"; page = this; + var templates = { + javascript: "function(doc) {\n emit(null, doc);\n}", + python: "def fun(doc):\n yield None, doc", + ruby: "{|doc|\n emit(nil, doc);\n}", + } + this.addDocument = function() { $.showDialog("dialog/_create_document.html", { submit: function(data, callback) { @@ -178,7 +185,8 @@ dirtyTimeout = setTimeout(function() { var buttons = $("#viewcode button.save, #viewcode button.revert"); page.isDirty = ($("#viewcode_map").val() != page.storedViewCode.map) - || ($("#viewcode_reduce").val() != (page.storedViewCode.reduce || "")); + || ($("#viewcode_reduce").val() != (page.storedViewCode.reduce || "")) + || page.viewLanguage != page.storedViewLanguage; if (page.isDirty) { buttons.removeAttr("disabled"); } else { @@ -195,13 +203,48 @@ .bind("keyup", updateDirtyState) .bind("textInput", updateDirtyState); } + $("#language").change(updateDirtyState); }); } else if (viewName == "_slow_view") { + page.viewLanguage = $.cookies.get(db.name + ".language", page.viewLanguage); page.updateViewEditor( - $.cookies.get(db.name + ".map"), + $.cookies.get(db.name + ".map", templates[page.viewLanguage]), $.cookies.get(db.name + ".reduce", "") ); } + page.populateLanguagesMenu(); + } + + // Populate the languages dropdown, and listen to selection changes + this.populateLanguagesMenu = function() { + $.couch.config({ + success: function(resp) { + var select = $("#language"); + for (var language in resp) { + var option = $(document.createElement("option")) + .attr("value", language).text(language) + .appendTo(select); + } + if (select[0].options.length == 1) { + select[0].disabled = true; + } else { + select.val(page.viewLanguage); + select.change(function() { + var language = $("#language").val(); + if (language != page.viewLanguage) { + var mapFun = $("#viewcode_map").val(); + if (mapFun == "" || mapFun == templates[page.viewLanguage]) { + // no edits made, so change to the new default + $("#viewcode_map").val(templates[language]); + } + page.viewLanguage = language; + $("#viewcode_map")[0].focus(); + } + return false; + }); + } + } + }, "query_servers"); } this.populateViewsMenu = function() { @@ -212,7 +255,6 @@ for (var i = 0; i < resp.rows.length; i++) { db.openDoc(resp.rows[i].id, { success: function(doc) { - var optGroup = $("").attr("label", doc._id.substr(8)); var optGroup = $(document.createElement("optgroup")) .attr("label", doc._id.substr(8)); for (var name in doc.views) { @@ -248,22 +290,27 @@ error: function(status, error, reason) { if (status == 404) { $.cookies.remove(dbName + ".view"); - location.reload(); + location.href = "database.html?" + encodeURIComponent(db.name); } }, success: function(resp) { var viewCode = resp.views[localViewName]; + page.viewLanguage = resp.language || "javascript"; + $("#language").val(page.viewLanguage); page.updateViewEditor(viewCode.map, viewCode.reduce || ""); $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled"); page.storedViewCode = viewCode; + page.storedViewLanguage = page.viewLanguage; if (callback) callback(); } }); } else { - $("#viewcode_map").val(page.storedViewCode.map); - $("#viewcode_reduce").val(page.storedViewCode.reduce || ""); - page.isDirty = false; + page.updateViewEditor(page.storedViewCode.map, + page.storedViewCode.reduce || ""); + page.viewLanguage = page.storedViewLanguage; + $("#language").val(page.viewLanguage); $("#viewcode button.revert, #viewcode button.save").attr("disabled", "disabled"); + page.isDirty = false; if (callback) callback(); } } @@ -332,7 +379,23 @@ }; var docId = ["_design", data.docid].join("/"); function save(doc) { - if (!doc) doc = {_id: docId, language: "javascript"}; + if (!doc) { + doc = {_id: docId, language: page.viewLanguage}; + } else { + var numViews = 0; + for (var viewName in (doc.views || {})) { + if (viewName != data.name) numViews++; + } + if (numViews > 0 && page.viewLanguage != doc.language) { + callback({ + docid: "Cannot save to " + data.docid + + " because its language is \"" + doc.language + + "\", not \"" + page.viewLanguage + "\"." + }); + return; + } + doc.language = page.viewLanguage; + } if (doc.views === undefined) doc.views = {}; doc.views[data.name] = viewCode; db.saveDoc(doc, { @@ -366,6 +429,17 @@ $(document.body).addClass("loading"); db.openDoc(["_design", designDocId].join("/"), { success: function(doc) { + var numViews = 0; + for (var viewName in (doc.views || {})) { + if (viewName != localViewName) numViews++; + } + if (numViews > 0 && page.viewLanguage != doc.language) { + alert("Cannot save view because the design document language " + + "is \"" + doc.language + "\", not \"" + + page.viewLanguage + "\"."); + return; + } + doc.language = page.viewLanguage; var viewDef = doc.views[localViewName]; viewDef.map = $("#viewcode_map").val(); viewDef.reduce = $("#viewcode_reduce").val() || undefined; @@ -524,7 +598,8 @@ } else { $.cookies.remove(db.name + ".reduce"); } - db.query(mapFun, reduceFun, null, options); + $.cookies.set(db.name + ".language", page.viewLanguage); + db.query(mapFun, reduceFun, page.viewLanguage, options); } else if (viewName == "_design_docs") { options.startkey = options.descending ? "_design0" : "_design"; options.endkey = options.descending ? "_design" : "_design0"; @@ -534,7 +609,7 @@ var currentMapCode = $("#viewcode_map").val(); var currentReduceCode = $("#viewcode_reduce").val() || null; if (page.isDirty) { - db.query(currentMapCode, currentReduceCode, null, options); + db.query(currentMapCode, currentReduceCode, page.viewLanguage, options); } else { db.view(viewName.substr(8), options); } diff --git a/share/www/script/jquery.resizer.js b/share/www/script/jquery.resizer.js index 9e0a291b..45c6c39a 100644 --- a/share/www/script/jquery.resizer.js +++ b/share/www/script/jquery.resizer.js @@ -76,7 +76,7 @@ $(document).unbind("mousemove"); document.onselectstart = null; // for IE }); - return false; + return true; }); }); } diff --git a/share/www/style/layout.css b/share/www/style/layout.css index 0691a1ad..2df42734 100644 --- a/share/www/style/layout.css +++ b/share/www/style/layout.css @@ -54,6 +54,7 @@ code.number, code.boolean { color: #339; } code.null { color: #666; } button { font-size: 100%; -webkit-appearance: square-button; } +button[disabled] { color: #999; } input, select, textarea { background: #fff; border: 1px solid; border-color: #999 #ddd #ddd #999; margin: 0; padding: 1px; } @@ -309,8 +310,8 @@ ul.suggest-dropdown li.selected { cursor: pointer; background: Highlight; white-space: nowrap; } #viewcode .code textarea { border: none; border-top: 1px solid #ccc; - color: #333; margin: 0; min-height: 50px; padding: .4em 0 0; resize: none; - width: 100%; overflow: auto; + color: #333; font-size: 11px; margin: 0; min-height: 50px; padding: .4em 0 0; + resize: none; width: 100%; overflow: auto; } #viewcode .code textarea:focus { background: #e9f4ff; } #viewcode .bottom { border-bottom: none; clear: left; padding: 1px 3px; } @@ -324,6 +325,7 @@ ul.suggest-dropdown li.selected { cursor: pointer; background: Highlight; float: right; margin: 0 0 0 1em; } #viewcode .bottom button.save { font-weight: bold; } +#viewcode .bottom label { color: #666; font-size: 90%; } #viewcode .grippie { background-position: 50% 50%; } #viewcode.collapsed { background: #e9e9e9; } #viewcode.collapsed .top { border-bottom: none; } -- cgit v1.2.3