aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Karneges <justin@affinix.com>2013-01-28 20:06:31 -0800
committerJustin Karneges <justin@affinix.com>2013-01-28 20:06:31 -0800
commitdb0f76bbfa49d3415158b4a0188e95c71783d82e (patch)
tree77225f6358533827139ad476ef2d60a4333cd053
parentf19ddca48d8befe65538be754b7381e10dcb6121 (diff)
downloadpollymer-db0f76bbfa49d3415158b4a0188e95c71783d82e.tar
pollymer-db0f76bbfa49d3415158b4a0188e95c71783d82e.tar.gz
kats' changes
-rw-r--r--polldance.js445
1 files changed, 253 insertions, 192 deletions
diff --git a/polldance.js b/polldance.js
index 906aed6..2991fac 100644
--- a/polldance.js
+++ b/polldance.js
@@ -1,192 +1,253 @@
-// don't break if there's no console
-if(typeof(console) === "undefined")
-{
- console = { log: function() {} };
-}
-
-var FO = FO || {};
-
-var fo_jsonp_callback_id = 0;
-var fo_jsonp_callbacks = {};
-
-function fo_jsonp_get_callback(cb_id)
-{
- if(fo_jsonp_callbacks[cb_id])
- {
- return fo_jsonp_callbacks[cb_id];
- }
- else
- {
- console.log("no callback with id " + cb_id);
- return function(result) {};
- }
-}
-
-// FO.Request has onFinished(int code, object result) and onError(int reason) callback members
-// error reasons: 0=http, 1=timeout
-// note: failed json parse on http body results in empty object {}, not error
-
-FO.Request = function()
-{
- if(!(this instanceof FO.Request))
- throw new Error("Constructor called as a function");
-}
-
-FO.Request.prototype.start = function(method, url, headers, body)
-{
- this._cors = false;
- if("withCredentials" in new XMLHttpRequest())
- this._cors = true;
-
- var self = this;
- this._timer = setTimeout(function() { self._timeout(); }, 60000);
-
- if(this._cors)
- {
- this._xhr = new XMLHttpRequest();
-
- this._xhr.onreadystatechange = function() { self._xhr_readystatechange(); };
- this._xhr.open(method, url, true);
-
- for(var key in headers)
- {
- if(!headers.hasOwnProperty(key))
- continue;
-
- this._xhr.setRequestHeader(key, headers[key]);
- }
-
- this._xhr.send(body);
- }
- else
- {
- var head = document.getElementsByTagName("head")[0];
- var script = document.createElement("script");
-
- script.type = "text/javascript";
-
- this._cb_id = fo_jsonp_callback_id.toString();
- ++fo_jsonp_callback_id;
-
- this._script_id = "fo-jsonp-script-" + this._cb_id;
- script.id = this._script_id;
-
- fo_jsonp_callbacks[this._cb_id] = function(result) { self._jsonp_callback(result); };
-
- var param_list = new Array();
-
- param_list.push("callback=" + encodeURIComponent("fo_jsonp_get_callback(\"" + this._cb_id + "\")"));
- if(method != "GET")
- param_list.push("method=" + encodeURIComponent(method));
- if(headers)
- param_list.push("headers=" + encodeURIComponent(JSON.stringify(headers)));
- if(body)
- param_list.push("body=" + encodeURIComponent(body));
-
- var params = param_list.join("&");
-
- var src;
- if(url.indexOf("?") != -1)
- src = url + "&" + params;
- else
- src = url + "?" + params;
-
- script.src = src;
- console.log("FO.Request json-p " + this._cb_id + " " + src);
- head.appendChild(script);
- }
-}
-
-FO.Request.prototype.abort = function()
-{
- clearTimeout(this._timer);
- this._timer = null;
-
- this._cancelreq();
-}
-
-FO.Request.prototype._cancelreq = function()
-{
- if(this._cors)
- {
- this._xhr.onreadystatechange = function() {}
- this._xhr.abort();
- this._xhr = null;
- }
- else
- {
- console.log("FO.Request json-p " + this._cb_id + " timeout");
-
- delete fo_jsonp_callbacks[this._cb_id];
- var script = document.getElementById(this._script_id);
- script.parentNode.removeChild(script);
- this._cb_id = null;
- this._script_id = null;
- }
-}
-
-FO.Request.prototype._xhr_readystatechange = function()
-{
- if(this._xhr.readyState === 4)
- {
- clearTimeout(this._timer);
- this._timer = null;
-
- var status = this._xhr.status;
- var responseText = this._xhr.responseText;
- this._xhr = null;
-
- if(status)
- {
- var result;
-
- try
- {
- result = JSON.parse(responseText);
- }
- catch(e)
- {
- result = {}
- }
-
- this._finished(status, result);
- }
- else
- this._error(0);
- }
-}
-
-FO.Request.prototype._jsonp_callback = function(result)
-{
- console.log("FO.Request json-p " + this._cb_id + " finished");
-
- clearTimeout(this._timer);
- this._timer = null;
-
- delete fo_jsonp_callbacks[this._cb_id];
- var script = document.getElementById(this._script_id);
- script.parentNode.removeChild(script);
- this._cb_id = null;
- this._script_id = null;
-
- this._finished(result.status, result.value);
-}
-
-FO.Request.prototype._timeout = function()
-{
- this._timer = null;
- this._cancelreq();
- this._error(1);
-}
-
-FO.Request.prototype._finished = function(code, result)
-{
- if(this.onFinished)
- this.onFinished(code, result);
-}
-
-FO.Request.prototype._error = function(reason)
-{
- if(this.onError)
- this.onError(reason);
-}
+(function (window, undefined) {
+
+ var TIMEOUT = 60000;
+
+ // don't break if there's no console
+ if (typeof (window.console) === "undefined") {
+ window.console = { log: function () { }, dir: function () { } };
+ }
+
+ // PollDance.Request has on('finished', int code, object result) and on('error', int reason) callback members
+ // error reasons: 0=http, 1=timeout
+ // note: failed json parse on http body results in empty object {}, not error
+
+ var JsonCallbacks = {
+ id: 0,
+ requests: {},
+ emptyCallback: function() {},
+ getJsonpCallback: function (id) {
+ var cb;
+ var requests = this.requests;
+ if (id in this.requests) {
+ cb = function (result) { requests[id]._jsonp_callback(result); };
+ } else {
+ console.log("no callback with id " + id);
+ cb = this.emptyCallback;
+ }
+ return cb;
+ },
+ addJsonpCallback: function (id, obj) {
+ this.requests[id] = obj;
+ },
+ removeJsonpCallback: function (id) {
+ delete this.requests[id];
+ },
+ newCallbackInfo: function () {
+ var callbackInfo = {
+ id: "cb-" + this.id,
+ scriptId: "fo-jsonp-script-" + this.id
+ };
+ this.id++;
+ return callbackInfo;
+ }
+ };
+
+ var corsAvailable = "withCredentials" in new XMLHttpRequest();
+
+ var Events = function () {
+ this._events = {};
+ };
+ Events.prototype._getEventsForType = function (type) {
+ if (!(type in this._events)) {
+ this._events[type] = [];
+ }
+ return this._events[type];
+ };
+ Events.prototype._setEventsForType = function (type, events) {
+ this._events[type] = events;
+ };
+ Events.prototype.on = function (type, handler) {
+ var events = this._getEventsForType(type);
+ events.push(handler);
+ };
+ Events.prototype.off = function (type) {
+ if (arguments.length > 1) {
+ var events = this._getEventsForType(type);
+ var handlersToKeep = [];
+ var handlers = Array.prototype.slice.call(arguments, 1);
+ for (var i = 0; i < events.length; i++) {
+ var event = events[i];
+ var keep = true;
+ for (var j = 0; j < handlers.length; j++) {
+ var handler = handlers[j];
+ if (event == handler) {
+ keep = false;
+ }
+ }
+ if (keep) {
+ handlersToKeep.push(event);
+ }
+ }
+ this._setEventsForType(type, handlersToKeep);
+ } else {
+ delete this._events[type];
+ }
+
+ };
+ Events.prototype.trigger = function (type, obj) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ var events = this._getEventsForType(type);
+ for (var i = 0; i < events.length; i++) {
+ var handler = events[i];
+ handler.apply(obj, args);
+ }
+ };
+
+ var TransportTypes = {
+ "Auto": 0,
+ "Xhr": 1,
+ "Xdr": 2,
+ "Jsonp": 3
+ };
+
+ var Request = function () {
+ if (!(this instanceof Request)) {
+ throw new Error("Constructor called as a function");
+ }
+ this._events = new Events();
+ };
+ Request.prototype.transport = TransportTypes.Auto;
+ Request.prototype.start = function (method, url, headers, body) {
+ var self = this;
+ self._timer = window.setTimeout(function () { self._timeout(); }, TIMEOUT);
+
+ if (corsAvailable) {
+
+ self._xhr = new XMLHttpRequest();
+ self._xhr.onreadystatechange = function () { self._xhr_readystatechange(); };
+ self._xhr.open(method, url, true);
+
+ for (var key in headers) {
+ if (headers.hasOwnProperty(key)) {
+ self._xhr.setRequestHeader(key, headers[key]);
+ }
+ }
+
+ self._xhr.send(body);
+
+ console.log("PollDance.Request start: " + url + " " + body);
+
+ } else {
+
+ this._callbackInfo = JsonCallbacks.newCallbackInfo();
+
+ var paramList = [];
+
+ paramList.push("callback=" + encodeURIComponent("PollDance._getJsonpCallback(\"" + this._callbackInfo.id + "\")"));
+ if (method != "GET") {
+ paramList.push("method=" + encodeURIComponent(method));
+ }
+ if (headers) {
+ paramList.push("headers=" + encodeURIComponent(JSON.stringify(headers)));
+ }
+ if (body) {
+ paramList.push("body=" + encodeURIComponent(body));
+ }
+ var params = paramList.join("&");
+
+ var src;
+ if (url.indexOf("?") != -1) {
+ src = url + "&" + params;
+ } else {
+ src = url + "?" + params;
+ }
+
+ console.log("PollDance.Request json-p " + this._callbackInfo.id + " " + src);
+ this._addJsonpCallback(this._callbackInfo, src);
+ }
+ };
+ Request.prototype.abort = function () {
+ clearTimeout(this._timer);
+ this._timer = null;
+ this._cancelreq();
+ };
+ Request.prototype.on = function (type, handler) {
+ this._events.on(type, handler);
+ };
+ Request.prototype.off = function (type) {
+ var args = Array.prototype.slice.call(arguments);
+ this._events.off.apply(this._events, args);
+ };
+ Request.prototype._addJsonpCallback = function (callbackInfo, src) {
+ JsonCallbacks.addJsonpCallback(callbackInfo.id, this);
+
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.id = callbackInfo.scriptId;
+ script.src = src;
+ head.appendChild(script);
+ };
+ Request.prototype._removeJsonpCallback = function (callbackInfo) {
+ JsonCallbacks.removeJsonpCallback(callbackInfo.id, this);
+
+ var script = document.getElementById(callbackInfo.scriptId);
+ script.parentNode.removeChild(script);
+ };
+ Request.prototype._cancelreq = function () {
+ if (corsAvailable) {
+ this._xhr.onreadystatechange = function () { }
+ this._xhr.abort();
+ this._xhr = null;
+ } else {
+ console.log("PollDance.Request json-p " + this._callbackInfo.id + " cancel");
+ this._removeJsonpCallback(this._callbackInfo);
+ this._callbackInfo = null;
+ }
+ };
+ Request.prototype._xhr_readystatechange = function () {
+ var xhr = this._xhr;
+ if (xhr != null && xhr.readyState === 4) {
+ this._xhr = null;
+
+ window.clearTimeout(this._timer);
+ this._timer = null;
+
+ var status = xhr.status;
+
+ if (status) {
+ var result;
+ try {
+ result = JSON.parse(xhr.responseText);
+ } catch (e) {
+ result = {};
+ }
+ this._finished(status, result);
+ } else {
+ this._error(0);
+ }
+ }
+ };
+ Request.prototype._jsonp_callback = function (result) {
+ console.log("PollDance.Request json-p " + this._callbackInfo.id + " finished");
+
+ window.clearTimeout(this._timer);
+ this._timer = null;
+
+ this._removeJsonpCallback(this._callbackInfo);
+ this._callbackInfo = null;
+
+ this._finished(result.status, result.value);
+ };
+ Request.prototype._timeout = function () {
+ this._timer = null;
+ this._cancelreq();
+ this._error(1);
+ };
+ Request.prototype._finished = function (code, result) {
+ this._events.trigger('finished', this, code, result);
+ };
+ Request.prototype._error = function (reason) {
+ this._events.trigger('error', this, reason);
+ };
+
+ var pollDance = {
+ Request: Request,
+ _getJsonpCallback: function (id) {
+ return JsonCallbacks.getJsonpCallback(id);
+ }
+ };
+
+ window.PollDance = window.PollDance || pollDance;
+
+})(window);