kansas-comet-0.2: static/js/kansas-comet.js
// Kansas Comet jQuery plugin
(function($) {
var the_prefix = "";
var kansascomet_session;
var kansascomet_server;
var eventQueues = {}; // TODO: add the use of the queue
var eventCallbacks = {};
var please_debug = false;
var debug = function () { };
var failure_callback = function(ig,ty,msg,re) {
console.error("redraw failed (retrying) : " + ig + "," + ty + "," + msg);
}
$.kc = {
// If we want to debug, then add a true
connect: function(prefix) {
the_prefix = prefix;
// if there is a ?debug=0, then send debug messages to it
if (window.location.search == '?debug=1') {
console.log("using logging to console for " + prefix);
debug = function(arg) {
console.log(arg);
};
}
$.ajax({ url: the_prefix,
type: "POST",
data: "",
dataType: "script"});
debug('connect(' + prefix + ')');
},
session: function(server_id, session_id) {
kansascomet_server = server_id;
kansascomet_session = session_id;
debug('session(' + session_id + ')');
$.kc.register("session","abort",null);
$.kc.redraw(0);
},
// Set failure behavior
failure: function(f) {
failure_callback = f;
},
redraw: function (count) {
debug('redraw(' + count + ') url = ' + the_prefix + "/act/" + kansascomet_server + "/" + kansascomet_session + "/" + count);
$.ajax({ url: the_prefix + "/act/" + kansascomet_server + "/" + kansascomet_session + "/" + count,
type: "GET",
dataType: "script",
success: function success() { $.kc.redraw(count + 1); },
error: function failure(ig,ty,msg) {
failure_callback(ig,ty,msg,function() { $.kc.redraw(count + 1); });
}
});
// TODO: Add failure; could happen
},
// This says someone is listening on a specific event
// The full event name is "scope/eventname", for example
// "body/click"
register: function (scope, eventname, fn) {
debug('register(' + scope + ',' + eventname + ')');
var fulleventname = scope + "/" + eventname;
eventQueues[fulleventname] = [];
if (fn == null) {
// no special setup required, because no callback to call.
} else {
$(scope).on(eventname, "." + eventname, function (event,aux) {
var e = fn(this,event,aux);
debug('{callback}on(' + eventname + ')');
e.eventname = eventname;
$.kc.send(fulleventname,e);
});
}
},
send: function (fulleventname, event) {
debug('send(' + fulleventname + ')');
if (eventCallbacks[fulleventname] == undefined) {
if (eventQueues[fulleventname] != undefined) {
eventQueues[fulleventname].push(event);
} else {
debug('send(' + fulleventname + ') not sent (no one listening)');
}
} else {
eventCallbacks[fulleventname](event);
}
},
// This waits for (full) named event(s). The second argument is the continuation
waitFor: function (scope, eventnames, fn) {
debug('waitFor(' + scope + ',' + eventnames + ')');
var prefixScope = function(o) { return scope + "/" + o; }
for (eventname in eventnames) {
var e = eventQueues[prefixScope(eventnames[eventname])].shift();
if (e != undefined) {
// call with event from queue
fn(e);
// and we are done
return;
}
if (eventCallbacks[prefixScope(eventnames[eventname])] != undefined) {
alert("ABORT: event queue callback failure for " + eventname);
}
}
// All the callback better be undefined
var f = function (e) {
// delete all the waiting callback(s)
for (eventname in eventnames) {
delete eventCallbacks[prefixScope(eventnames[eventname])];
}
// and do the callback
fn(e);
};
for (eventname in eventnames) {
eventCallbacks[prefixScope(eventnames[eventname])] = f;
}
},
// There is a requirement that obj be an object or array.
// See RFC 4627 for details.
reply: function (uq,obj) {
debug('reply(' + uq + ')');
$.ajax({ url: the_prefix + "/reply/" + kansascomet_server + "/" + kansascomet_session + "/" + uq,
type: "POST",
// This wrapper is needed because the JSON parser
// used on the Haskell side only supports objects
// and arrays. But the returned data might be just
// a number or a boolean. So this wrapper keeps
// the value safe to parse and has to be unwrapped
// on server side. Formatting it as string is also
// important for some reason.
data: "{ \"data\": " + $.toJSON(obj) + " }",
contentType: "application/json; charset=utf-8",
dataType: "json"});
}
};
})(jQuery);