diff options
author | Robert Newson <rnewson@apache.org> | 2011-05-17 11:15:14 +0000 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2011-05-17 11:15:14 +0000 |
commit | e8e4b0d293021fe90326a85828f3cfb087bf18b7 (patch) | |
tree | 986f544eac623ec23b769b36828894f93a173aa3 /1.1.x/share/www/script/futon.js | |
parent | da6a5322b0b8084f434752060caa8be214c6f4fa (diff) |
tagging 1.1.0
git-svn-id: https://svn.apache.org/repos/asf/couchdb/tags/1.1.0@1104149 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '1.1.x/share/www/script/futon.js')
-rw-r--r-- | 1.1.x/share/www/script/futon.js | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/1.1.x/share/www/script/futon.js b/1.1.x/share/www/script/futon.js new file mode 100644 index 00000000..fb73e3c9 --- /dev/null +++ b/1.1.x/share/www/script/futon.js @@ -0,0 +1,535 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// $$ inspired by @wycats: http://yehudakatz.com/2009/04/20/evented-programming-with-jquery/ +function $$(node) { + var data = $(node).data("$$"); + if (data) { + return data; + } else { + data = {}; + $(node).data("$$", data); + return data; + } +}; + +(function($) { + + function Session() { + + function doLogin(name, password, callback) { + $.couch.login({ + name : name, + password : password, + success : function() { + $.futon.session.sidebar(); + callback(); + }, + error : function(code, error, reason) { + $.futon.session.sidebar(); + callback({name : "Error logging in: "+reason}); + } + }); + }; + + function doSignup(name, password, callback, runLogin) { + $.couch.signup({ + name : name + }, password, { + success : function() { + if (runLogin) { + doLogin(name, password, callback); + } else { + callback(); + } + }, + error : function(status, error, reason) { + $.futon.session.sidebar(); + if (error == "conflict") { + callback({name : "Name '"+name+"' is taken"}); + } else { + callback({name : "Signup error: "+reason}); + } + } + }); + }; + + function validateUsernameAndPassword(data, callback) { + if (!data.name || data.name.length == 0) { + callback({name: "Please enter a name."}); + return false; + }; + return validatePassword(data, callback); + }; + + function validatePassword(data, callback) { + if (!data.password || data.password.length == 0) { + callback({password: "Please enter a password."}); + return false; + }; + return true; + }; + + function createAdmin() { + $.showDialog("dialog/_create_admin.html", { + submit: function(data, callback) { + if (!validateUsernameAndPassword(data, callback)) return; + $.couch.config({ + success : function() { + doLogin(data.name, data.password, function(errors) { + if(!$.isEmptyObject(errors)) { + callback(errors); + return; + } + doSignup(data.name, null, function(errors) { + if (errors && errors.name && errors.name.indexOf && errors.name.indexOf("taken") == -1) { + callback(errors); + } else { + callback(); + } + }, false); + }); + } + }, "admins", data.name, data.password); + } + }); + return false; + }; + + function login() { + $.showDialog("dialog/_login.html", { + submit: function(data, callback) { + if (!validateUsernameAndPassword(data, callback)) return; + doLogin(data.name, data.password, callback); + } + }); + return false; + }; + + function logout() { + $.couch.logout({ + success : function(resp) { + $.futon.session.sidebar(); + } + }) + }; + + function signup() { + $.showDialog("dialog/_signup.html", { + submit: function(data, callback) { + if (!validateUsernameAndPassword(data, callback)) return; + doSignup(data.name, data.password, callback, true); + } + }); + return false; + }; + + function changePassword () { + $.showDialog("dialog/_change_password.html", { + submit: function(data, callback) { + if (validatePassword(data, callback)) { + if (data.password != data.verify_password) { + callback({verify_password: "Passwords don't match."}); + return false; + } + } else { + return false; + } + $.couch.session({success: function (resp) { + if (resp.userCtx.roles.indexOf("_admin") > -1) { + $.couch.config({ + success : function () { + doLogin(resp.userCtx.name, data.password, function(errors) { + if(!$.isEmptyObject(errors)) { + callback(errors); + return; + } else { + location.reload(); + } + }); + } + }, "admins", resp.userCtx.name, data.password); + } else { + $.couch.db(resp.info.authentication_db).openDoc("org.couchdb.user:"+resp.userCtx.name, { + success: function (user) { + $.couch.db(resp.info.authentication_db).saveDoc($.couch.prepareUserDoc(user, data.password), { + success: function() { + doLogin(user.name, data.password, function(errors) { + if(!$.isEmptyObject(errors)) { + callback(errors); + return; + } else { + location.reload(); + } + }); + } + }); + } + }); + } + }}); + } + }); + return false; + }; + + this.setupSidebar = function() { + $("#userCtx .login").click(login); + $("#userCtx .logout").click(logout); + $("#userCtx .signup").click(signup); + $("#userCtx .createadmin").click(createAdmin); + $("#userCtx .changepass").click(changePassword); + }; + + this.sidebar = function() { + // get users db info? + $("#userCtx span").hide(); + $.couch.session({ + success : function(r) { + var userCtx = r.userCtx; + $$("#userCtx").userCtx = userCtx; + if (userCtx.name) { + $("#userCtx .name").text(userCtx.name).attr({href : $.couch.urlPrefix + "/_utils/document.html?"+encodeURIComponent(r.info.authentication_db)+"/org.couchdb.user%3A"+encodeURIComponent(userCtx.name)}); + if (userCtx.roles.indexOf("_admin") != -1) { + $("#userCtx .loggedin").show(); + $("#userCtx .loggedinadmin").show(); + } else { + $("#userCtx .loggedin").show(); + } + } else if (userCtx.roles.indexOf("_admin") != -1) { + $("#userCtx .adminparty").show(); + } else { + $("#userCtx .loggedout").show(); + }; + } + }) + }; + }; + + function Navigation() { + var nav = this; + this.loaded = false; + this.eventHandlers = { + load: [] + }; + + this.ready = function(callback) { + if (callback) { + if (this.loaded) { + callback.apply(this); + } + this.eventHandlers["load"].push(callback); + } else { + this.loaded = true; + callbacks = this.eventHandlers["load"]; + for (var i = 0; i < callbacks.length; i++) { + callbacks[i].apply(this); + } + } + } + + this.addDatabase = function(name) { + var current = $.futon.storage.get("recent", ""); + var recentDbs = current ? current.split(",") : []; + if ($.inArray(name, recentDbs) == -1) { + recentDbs.unshift(name); + if (recentDbs.length > 10) recentDbs.length = 10; + $.futon.storage.set("recent", recentDbs.join(",")); + this.updateDatabases(); + } + } + + this.removeDatabase = function(name) { + // remove database from recent databases list + var current = $.futon.storage.get("recent", ""); + var recentDbs = current ? current.split(",") : []; + var recentIdx = $.inArray(name, recentDbs); + if (recentIdx >= 0) { + recentDbs.splice(recentIdx, 1); + $.futon.storage.set("recent", recentDbs.join(",")); + this.updateDatabases(); + } + } + + this.updateDatabases = function() { + var selection = null; + $("#dbs .selected a").each(function() { + selection = [this.pathname, this.search]; + }); + $("#dbs").empty(); + var recentDbs = $.futon.storage.get("recent").split(","); + recentDbs.sort(); + $.each(recentDbs, function(idx, name) { + if (name) { + name = encodeURIComponent(name); + $("#dbs").append("<li>" + + "<button class='remove' title='Remove from list' value='" + name + "'></button>" + + "<a href='database.html?" + name + "' title='" + name + "'>" + name + + "</a></li>"); + } + }); + if (selection) { + this.updateSelection(selection[0], selection[1]); + } + $("#dbs button.remove").click(function() { + nav.removeDatabase(this.value); + return false; + }); + } + + this.updateSelection = function(path, queryString) { + function fixupPath(path) { // hack for IE/Win + return (path.charAt(0) != "/") ? ("/" + path) : path; + } + if (!path) { + path = location.pathname; + if (!queryString) { + queryString = location.search; + } + } else if (!queryString) { + queryString = ""; + } + var href = fixupPath(path + queryString); + $("#nav li").removeClass("selected"); + $("#nav li a").each(function() { + if (fixupPath(this.pathname) + this.search != href) return; + $(this).parent("li").addClass("selected").parents("li").addClass("selected"); + }); + } + + this.toggle = function(speed) { + if (speed === undefined) { + speed = 500; + } + var sidebar = $("#sidebar").stop(true, true); + var hidden = !$(sidebar).is(".hidden"); + + $("#wrap").animate({ + marginRight: hidden ? 0 : 210 + }, speed, function() { + $(document.body).toggleClass("fullwidth", hidden); + }); + sidebar.toggleClass("hidden").animate({ + width: hidden ? 26 : 210, + height: hidden ? $("h1").outerHeight() - 1 : "100%", + right: hidden ? 0 : -210 + }, speed).children(":not(#sidebar-toggle)").animate({ + opacity: "toggle" + }, speed); + $("h1").animate({marginRight: hidden ? 26 : 0}, speed); + + $("#sidebar-toggle") + .attr("title", hidden ? "Show Sidebar" : "Hide Sidebar"); + $.futon.storage.set("sidebar", hidden ? "hidden" : "show"); + }; + } + + function Storage() { + var storage = this; + this.decls = {}; + + this.declare = function(name, options) { + this.decls[name] = $.extend({}, { + scope: "window", + defaultValue: null, + prefix: "" + }, options || {}); + } + + this.declareWithPrefix = function(prefix, decls) { + for (var name in decls) { + var options = decls[name]; + options.prefix = prefix; + storage.declare(name, options); + } + } + + this.del = function(name) { + lookup(name, function(decl) { + handlers[decl.scope].del(decl.prefix + name); + }); + } + + this.get = function(name, defaultValue) { + return lookup(name, function(decl) { + var value = handlers[decl.scope].get(decl.prefix + name); + if (value !== undefined) { + return value; + } + if (defaultValue !== undefined) { + return defaultValue; + } + return decl.defaultValue; + }); + } + + this.set = function(name, value) { + lookup(name, function(decl) { + if (value == decl.defaultValue) { + handlers[decl.scope].del(decl.prefix + name); + } else { + handlers[decl.scope].set(decl.prefix + name, value); + } + }); + } + + function lookup(name, callback) { + var decl = storage.decls[name]; + if (decl === undefined) { + return decl; + } + return callback(decl); + } + + function windowName() { + try { + return JSON.parse(window.name || "{}"); + } catch (e) { + return {}; + } + } + + // add suffix to cookie names to be able to separate between ports + var cookiePrefix = location.port + "_"; + + var handlers = { + + "cookie": { + get: function(name) { + var nameEq = cookiePrefix + name + "="; + var parts = document.cookie.split(';'); + for (var i = 0; i < parts.length; i++) { + var part = parts[i].replace(/^\s+/, ""); + if (part.indexOf(nameEq) == 0) { + return unescape(part.substring(nameEq.length, part.length)); + } + } + }, + set: function(name, value) { + var date = new Date(); + date.setTime(date.getTime() + 14*24*60*60*1000); // two weeks + document.cookie = cookiePrefix + name + "=" + escape(value) + + "; expires=" + date.toGMTString(); + }, + del: function(name) { + var date = new Date(); + date.setTime(date.getTime() - 24*60*60*1000); // yesterday + document.cookie = cookiePrefix + name + "=" + + "; expires=" + date.toGMTString(); + } + }, + + "window": { + get: function(name) { + return windowName()[name]; + }, + set: function(name, value) { + var obj = windowName(); + obj[name] = value || null; + window.name = JSON.stringify(obj); + }, + del: function(name) { + var obj = windowName(); + delete obj[name]; + window.name = JSON.stringify(obj); + } + } + + }; + + } + + $.couch.urlPrefix = ".."; + $.futon = $.futon || {}; + $.extend($.futon, { + navigation: new Navigation(), + session : new Session(), + storage: new Storage() + }); + + $.fn.addPlaceholder = function() { + if (this[0] && "placeholder" in document.createElement("input")) { + return; // found native placeholder support + } + return this.live('focusin', function() { + var input = $(this); + if (input.val() === input.attr("placeholder")) { + input.removeClass("placeholder").val(""); + } + }).live("focusout", function() { + var input = $(this); + if (input.val() === "") { + input.val(input.attr("placeholder")).addClass("placeholder"); + } + }).trigger("focusout"); + } + + $.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"); }); + + $.futon.storage.declare("sidebar", {scope: "cookie", defaultValue: "show"}); + $.futon.storage.declare("recent", {scope: "cookie", defaultValue: ""}); + + $(function() { + document.title = "Apache CouchDB - Futon: " + document.title; + if ($.futon.storage.get("sidebar") == "hidden") { + // doing this as early as possible prevents flickering + $(document.body).addClass("fullwidth"); + } + $("input[placeholder]").addPlaceholder(); + + $.get("_sidebar.html", function(resp) { + $("#wrap").append(resp) + .find("#sidebar-toggle").click(function(e) { + $.futon.navigation.toggle(e.shiftKey ? 2500 : 500); + return false; + }); + if ($.futon.storage.get("sidebar") == "hidden") { + $.futon.navigation.toggle(0); + } + + $.futon.navigation.updateDatabases(); + $.futon.navigation.updateSelection(); + $.futon.navigation.ready(); + $.futon.session.setupSidebar(); + $.futon.session.sidebar(); + + $.couch.info({ + success: function(info, status) { + $("#version").text(info.version); + } + }); + }); + }); + +})(jQuery); |