summaryrefslogtreecommitdiff
path: root/share/www/script/jquery.couch.js
diff options
context:
space:
mode:
Diffstat (limited to 'share/www/script/jquery.couch.js')
-rw-r--r--share/www/script/jquery.couch.js294
1 files changed, 253 insertions, 41 deletions
diff --git a/share/www/script/jquery.couch.js b/share/www/script/jquery.couch.js
index 7e8a0236..114e5801 100644
--- a/share/www/script/jquery.couch.js
+++ b/share/www/script/jquery.couch.js
@@ -28,7 +28,7 @@
return;
}
var user_prefix = "org.couchdb.user:";
- user_doc._id = user_doc._id || user_prefix + user_doc.username;
+ user_doc._id = user_doc._id || user_prefix + user_doc.name;
if (new_password) {
// handle the password crypto
user_doc.salt = $.couch.newUUID();
@@ -36,17 +36,18 @@
}
user_doc.type = "user";
if (!user_doc.roles) {
- user_doc.roles = []
+ user_doc.roles = [];
}
return user_doc;
};
- uuidCache = [];
+ var uuidCache = [];
$.extend($.couch, {
+ urlPrefix: '',
activeTasks: function(options) {
ajax(
- {url: "/_active_tasks"},
+ {url: this.urlPrefix + "/_active_tasks"},
options,
"Active task status could not be retrieved"
);
@@ -54,14 +55,14 @@
allDbs: function(options) {
ajax(
- {url: "/_all_dbs"},
+ {url: this.urlPrefix + "/_all_dbs"},
options,
"An error occurred retrieving the list of all databases"
);
},
config: function(options, section, option, value) {
- var req = {url: "/_config/"};
+ var req = {url: this.urlPrefix + "/_config/"};
if (section) {
req.url += encodeURIComponent(section) + "/";
if (option) {
@@ -74,7 +75,7 @@
req.type = "PUT";
req.data = toJSON(value);
req.contentType = "application/json";
- req.processData = false
+ req.processData = false;
}
ajax(req, options,
@@ -85,7 +86,7 @@
session: function(options) {
options = options || {};
$.ajax({
- type: "GET", url: "/_session",
+ type: "GET", url: this.urlPrefix + "/_session",
complete: function(req) {
var resp = $.httpData(req, "json");
if (req.status == 200) {
@@ -102,7 +103,7 @@
userDb : function(callback) {
$.couch.session({
success : function(resp) {
- var userDb = $.couch.db(resp.info.user_db);
+ var userDb = $.couch.db(resp.info.authentication_db);
callback(userDb);
}
});
@@ -114,14 +115,14 @@
user_doc = prepareUserDoc(user_doc, password);
$.couch.userDb(function(db) {
db.saveDoc(user_doc, options);
- })
+ });
},
login: function(options) {
options = options || {};
$.ajax({
- type: "POST", url: "/_session", dataType: "json",
- data: {username: options.username, password: options.password},
+ type: "POST", url: this.urlPrefix + "/_session", dataType: "json",
+ data: {name: options.name, password: options.password},
complete: function(req) {
var resp = $.httpData(req, "json");
if (req.status == 200) {
@@ -137,7 +138,7 @@
logout: function(options) {
options = options || {};
$.ajax({
- type: "DELETE", url: "/_session", dataType: "json",
+ type: "DELETE", url: this.urlPrefix + "/_session", dataType: "json",
username : "_", password : "_",
complete: function(req) {
var resp = $.httpData(req, "json");
@@ -152,10 +153,28 @@
});
},
- db: function(name) {
+ db: function(name, db_opts) {
+ db_opts = db_opts || {};
+ var rawDocs = {};
+ function maybeApplyVersion(doc) {
+ if (doc._id && doc._rev && rawDocs[doc._id] && rawDocs[doc._id].rev == doc._rev) {
+ // todo: can we use commonjs require here?
+ if (typeof Base64 == "undefined") {
+ alert("please include /_utils/script/base64.js in the page for base64 support");
+ return false;
+ } else {
+ doc._attachments = doc._attachments || {};
+ doc._attachments["rev-"+doc._rev.split("-")[0]] = {
+ content_type :"application/json",
+ data : Base64.encode(rawDocs[doc._id].raw)
+ };
+ return true;
+ }
+ }
+ };
return {
name: name,
- uri: "/" + encodeURIComponent(name) + "/",
+ uri: this.urlPrefix + "/" + encodeURIComponent(name) + "/",
compact: function(options) {
$.extend(options, {successStatus: 202});
@@ -211,9 +230,79 @@
"Database information could not be retrieved"
);
},
+ changes: function(since, options) {
+ options = options || {};
+ // set up the promise object within a closure for this handler
+ var timeout = 100, db = this, active = true,
+ listeners = [],
+ promise = {
+ onChange : function(fun) {
+ listeners.push(fun);
+ },
+ stop : function() {
+ active = false;
+ }
+ };
+ // call each listener when there is a change
+ function triggerListeners(resp) {
+ $.each(listeners, function() {
+ this(resp);
+ });
+ };
+ // when there is a change, call any listeners, then check for another change
+ options.success = function(resp) {
+ timeout = 100;
+ if (active) {
+ since = resp.last_seq;
+ triggerListeners(resp);
+ getChangesSince();
+ };
+ };
+ options.error = function() {
+ if (active) {
+ setTimeout(getChangesSince, timeout);
+ timeout = timeout * 2;
+ }
+ };
+ // actually make the changes request
+ function getChangesSince() {
+ var opts = $.extend({heartbeat : 10 * 1000}, options, {
+ feed : "longpoll",
+ since : since
+ });
+ ajax(
+ {url: db.uri + "_changes"+encodeOptions(opts)},
+ options,
+ "Error connecting to "+db.uri+"/_changes."
+ );
+ }
+ // start the first request
+ if (since) {
+ getChangesSince();
+ } else {
+ db.info({
+ success : function(info) {
+ since = info.update_seq;
+ getChangesSince();
+ }
+ });
+ }
+ return promise;
+ },
allDocs: function(options) {
- ajax(
- {url: this.uri + "_all_docs" + encodeOptions(options)},
+ var type = "GET";
+ var data = null;
+ if (options["keys"]) {
+ type = "POST";
+ var keys = options["keys"];
+ delete options["keys"];
+ data = toJSON({ "keys": keys });
+ }
+ ajax({
+ type: type,
+ data: data,
+ url: this.uri + "_all_docs" + encodeOptions(options)
+ },
options,
"An error occurred retrieving a list of all documents"
);
@@ -246,10 +335,32 @@
}
});
} else {
- alert("please provide an eachApp function for allApps()");
+ alert("Please provide an eachApp function for allApps()");
}
},
openDoc: function(docId, options, ajaxOptions) {
+ options = options || {};
+ if (db_opts.attachPrevRev || options.attachPrevRev) {
+ $.extend(options, {
+ beforeSuccess : function(req, doc) {
+ rawDocs[doc._id] = {
+ rev : doc._rev,
+ raw : req.responseText
+ };
+ }
+ });
+ } else {
+ $.extend(options, {
+ beforeSuccess : function(req, doc) {
+ if (doc["jquery.couch.attachPrevRev"]) {
+ rawDocs[doc._id] = {
+ rev : doc._rev,
+ raw : req.responseText
+ };
+ }
+ }
+ });
+ }
ajax({url: this.uri + encodeDocId(docId) + encodeOptions(options)},
options,
"The document could not be retrieved",
@@ -258,6 +369,8 @@
},
saveDoc: function(doc, options) {
options = options || {};
+ var db = this;
+ var beforeSend = fullCommit(options);
if (doc._id === undefined) {
var method = "POST";
var uri = this.uri;
@@ -265,16 +378,28 @@
var method = "PUT";
var uri = this.uri + encodeDocId(doc._id);
}
+ var versioned = maybeApplyVersion(doc);
$.ajax({
type: method, url: uri + encodeOptions(options),
contentType: "application/json",
dataType: "json", data: toJSON(doc),
+ beforeSend : beforeSend,
complete: function(req) {
var resp = $.httpData(req, "json");
- if (req.status == 201) {
+ if (req.status == 200 || req.status == 201 || req.status == 202) {
doc._id = resp.id;
doc._rev = resp.rev;
- if (options.success) options.success(resp);
+ if (versioned) {
+ db.openDoc(doc._id, {
+ attachPrevRev : true,
+ success : function(d) {
+ doc._attachments = d._attachments;
+ if (options.success) options.success(resp);
+ }
+ });
+ } else {
+ if (options.success) options.success(resp);
+ }
} else if (options.error) {
options.error(req.status, resp.error, resp.reason);
} else {
@@ -284,10 +409,12 @@
});
},
bulkSave: function(docs, options) {
- $.extend(options, {successStatus: 201});
+ var beforeSend = fullCommit(options);
+ $.extend(options, {successStatus: 201, beforeSend : beforeSend});
ajax({
type: "POST",
- url: this.uri + "_bulk_docs" + encodeOptions(options)
+ url: this.uri + "_bulk_docs" + encodeOptions(options),
+ contentType: "application/json", data: toJSON(docs)
},
options,
"The documents could not be saved"
@@ -304,13 +431,27 @@
"The document could not be deleted"
);
},
- copyDoc: function(doc, options, ajaxOptions) {
+ bulkRemove: function(docs, options){
+ docs.docs = $.each(
+ docs.docs, function(i, doc){
+ doc._deleted = true;
+ }
+ );
+ $.extend(options, {successStatus: 201});
+ ajax({
+ type: "POST",
+ url: this.uri + "_bulk_docs" + encodeOptions(options),
+ data: toJSON(docs)
+ },
+ options,
+ "The documents could not be deleted"
+ );
+ },
+ copyDoc: function(docId, options, ajaxOptions) {
ajaxOptions = $.extend(ajaxOptions, {
complete: function(req) {
var resp = $.httpData(req, "json");
if (req.status == 201) {
- doc._id = resp.id;
- doc._rev = resp.rev;
if (options.success) options.success(resp);
} else if (options.error) {
options.error(req.status, resp.error, resp.reason);
@@ -321,9 +462,7 @@
});
ajax({
type: "COPY",
- url: this.uri +
- encodeDocId(doc._id) +
- encodeOptions({rev: doc._rev})
+ url: this.uri + encodeDocId(docId)
},
options,
"The document could not be copied",
@@ -350,6 +489,26 @@
"An error occurred querying the database"
);
},
+ list: function(list, view, options) {
+ var list = list.split('/');
+ var options = options || {};
+ var type = 'GET';
+ var data = null;
+ if (options['keys']) {
+ type = 'POST';
+ var keys = options['keys'];
+ delete options['keys'];
+ data = toJSON({'keys': keys });
+ }
+ ajax({
+ type: type,
+ data: data,
+ url: this.uri + '_design/' + list[0] +
+ '/_list/' + list[1] + '/' + view + encodeOptions(options)
+ },
+ options, 'An error occured accessing the list'
+ );
+ },
view: function(name, options) {
var name = name.split('/');
var options = options || {};
@@ -369,6 +528,25 @@
},
options, "An error occurred accessing the view"
);
+ },
+ getDbProperty: function(propName, options, ajaxOptions) {
+ ajax({url: this.uri + propName + encodeOptions(options)},
+ options,
+ "The property could not be retrieved",
+ ajaxOptions
+ );
+ },
+
+ setDbProperty: function(propName, propValue, options, ajaxOptions) {
+ ajax({
+ type: "PUT",
+ url: this.uri + propName + encodeOptions(options),
+ data : JSON.stringify(propValue)
+ },
+ options,
+ "The property could not be updated",
+ ajaxOptions
+ );
}
};
},
@@ -377,19 +555,23 @@
info: function(options) {
ajax(
- {url: "/"},
+ {url: this.urlPrefix + "/"},
options,
"Server information could not be retrieved"
);
},
- replicate: function(source, target, options) {
+ replicate: function(source, target, ajaxOptions, repOpts) {
+ repOpts = $.extend({source: source, target: target}, repOpts);
+ if (repOpts.continuous) {
+ ajaxOptions.successStatus = 202;
+ }
ajax({
- type: "POST", url: "/_replicate",
- data: JSON.stringify({source: source, target: target}),
+ type: "POST", url: this.urlPrefix + "/_replicate",
+ data: JSON.stringify(repOpts),
contentType: "application/json"
},
- options,
+ ajaxOptions,
"Replication failed"
);
},
@@ -399,9 +581,9 @@
cacheNum = 1;
}
if (!uuidCache.length) {
- ajax({url: "/_uuids", data: {count: cacheNum}, async: false}, {
+ ajax({url: this.urlPrefix + "/_uuids", data: {count: cacheNum}, async: false}, {
success: function(resp) {
- uuidCache = resp.uuids
+ uuidCache = resp.uuids;
}
},
"Failed to retrieve UUID batch."
@@ -409,21 +591,40 @@
}
return uuidCache.shift();
}
-
});
function ajax(obj, options, errorMessage, ajaxOptions) {
options = $.extend({successStatus: 200}, options);
+ ajaxOptions = $.extend({contentType: "application/json"}, ajaxOptions);
errorMessage = errorMessage || "Unknown error";
-
$.ajax($.extend($.extend({
- type: "GET", dataType: "json",
+ type: "GET", dataType: "json", cache : !$.browser.msie,
+ beforeSend: function(xhr){
+ if(ajaxOptions && ajaxOptions.headers){
+ for (var header in ajaxOptions.headers){
+ xhr.setRequestHeader(header, ajaxOptions.headers[header]);
+ }
+ }
+ },
complete: function(req) {
- var resp = $.httpData(req, "json");
+ try {
+ var resp = $.httpData(req, "json");
+ } catch(e) {
+ if (options.error) {
+ options.error(req.status, req, e);
+ } else {
+ alert(errorMessage + ": " + e);
+ }
+ return;
+ }
+ if (options.ajaxStart) {
+ options.ajaxStart(resp);
+ }
if (req.status == options.successStatus) {
+ if (options.beforeSuccess) options.beforeSuccess(req, resp);
if (options.success) options.success(resp);
} else if (options.error) {
- options.error(req.status, resp.error, resp.reason);
+ options.error(req.status, resp && resp.error || errorMessage, resp && resp.reason || "no response");
} else {
alert(errorMessage + ": " + resp.reason);
}
@@ -431,13 +632,24 @@
}, obj), ajaxOptions));
}
+ function fullCommit(options) {
+ var options = options || {};
+ if (typeof options.ensure_full_commit !== "undefined") {
+ var commit = options.ensure_full_commit;
+ delete options.ensure_full_commit;
+ return function(xhr) {
+ xhr.setRequestHeader("X-Couch-Full-Commit", commit.toString());
+ };
+ }
+ };
+
// Convert a options object to an url query string.
// ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
function encodeOptions(options) {
var buf = [];
if (typeof(options) === "object" && options !== null) {
for (var name in options) {
- if ($.inArray(name, ["error", "success"]) >= 0)
+ if ($.inArray(name, ["error", "success", "beforeSuccess", "ajaxStart"]) >= 0)
continue;
var value = options[name];
if ($.inArray(name, ["key", "startkey", "endkey"]) >= 0) {