/**
* Copyright Franson Technology AB, Sweden, 2009
* http://franson.com, http://gpsgate.com
* <p>
* low-level methods to interact with GpsGate Server WS
* (The service API proxies depend on this)
* </p>
* author Fredrik Blomqvist
*
* @module GpsGate
*
*/
var GpsGate = GpsGate || {};
/**
* namespace
* @class GpsGate.Server
* @static
*/
GpsGate.Server = GpsGate.Server || {};
/**
* todo: rename getGpsGateServerRelativePath?
* todo: create method to create absolute path from relative?
* todo: deprecate? (only used in BT and webmap)
* @method getServerName
* @return {string} server name url (including protocol and port number)
*/
GpsGate.Server.getServerName = function()
{
var wl = window.location;
var path = wl.href;
// drop two dir levels from the end (our relative installation/setup depth)
// todo: create regexp instead(?)
var idx = path.lastIndexOf('/');
if (idx != -1)
{
path = path.substring(0, idx);
var proto = wl.protocol + '//';
idx = path.lastIndexOf('/');
if (idx != (path.lastIndexOf(proto) + proto.length)) // make sure we don't go as far as the protocol
{
path = path.substring(0, idx);
}
}
return path;
};
/**
* same as Franson.Util.getUniqueId but added here to avoid dependency
* @type integer
* @private
*/
GpsGate.Server._getCallId = MochiKit.Base.counter(); // todo: or make this lazy intialized to reduce script startup race with Mochi?
/**
* standard WS-call method (used by the Service proxies)
* todo: allow choosing between GET/POST calls?
* @method call
* @param {string} url
* @param {string} method
* @param {object} [params]
* @return {Deferred}
*/
GpsGate.Server.call = function(url, method, params)
{
params = params || {};
var d = MochiKit.Async.doXHR(url, {
'method': 'POST',
'headers': {
'Content-Type': 'application/json; charset=utf-8',
'X-JSON-RPC': method
},
'sendContent': MochiKit.Base.serializeJSON({
'id': GpsGate.Server._getCallId(),
'method': method,
'params': params
})
});
/* // same as above but using GET
// (could use loadJSONDoc also but that uses a slightly less efficient pre eval-check)
// (now this is same as doSimpleXMLHttpRequest)
var d = MochiKit.Async.doXHR(url + '/' + method, {
'method': 'GET',
'headers': {
'Content-Type': 'application/json; charset=utf-8',
'X-JSON-RPC': method
},
// ! note that this currently relies on a patched queryString that
// formats DateTimes in same way as our json-spec (ISO-stamp) (isn't that REST "standard"?)
// (todo: create a queryStringJSON that uses the same logic as Mochi.serializeJSON?)
'queryString': params // todo: do we need an id? (or other no-cache stuff?)
});
*/
// eval JSON and forward possible JayRock error
d.addCallback(function(request)
{
var response = eval('(' + request.responseText + ')');
if (typeof(response.error) != 'undefined')
{
var error = response.error;
var e = new Error('GpsGate.Server.call: ' + error.message); // todo: can('t) we set the .name property?
e.nativeError = error;
throw e;
}
return response.result;
});
return d;
};
/**
* container for hooks to the XSS calls
* @private
* @type object
*/
GpsGate.Server._callback = {};
/**
* same as above but using JSONP/XSS calling
* todo: could use Mochi.DOM for some stuff here but better to keep dependencies down(?)
* todo: would actually be possible to make this cancellable by using a
* middle man as callback, but not sure it's worth it.
* todo: see http://trac.mochikit.com/ticket/258
* todo: not fully tested..
* @private // don't expose yet
*/
GpsGate.Server.callJSONP = function(url, method, params)
{
var id = GpsGate.Server._getCallId();
var callId = '_' + id;
var nodeId = 'GpsGateServer_JSONP' + callId;
function cleanup()
{
delete GpsGate.Server._callback[callId];
MochiKit.DOM.removeElement(nodeId); // or would it be better to just keep a ref to the actual node? (should be faster atleast)
}
var d = new MochiKit.Async.Deferred(
function canceller(def)
{
// is it safe to just remove everything?
// shold we need to keep a placeholder? (test in different browsers)
// GpsGate.Server._callback[callId] = MochiKit.Base.noop;
cleanup();
}
);
// add to pool
GpsGate.Server._callback[callId] = function(response)
{
cleanup();
if (typeof(response.error) != 'undefined')
{
d.errback(new Error('GpsGate.Server.callJSONP: ' + response.error.message));
}
else
{
d.callback(response.result);
}
};
document.getElementsByTagName('head')[0].appendChild(
MochiKit.DOM.createDOM('script', {
'type': 'text/javascript',
'id': nodeId,
'src': (
url + '/' + method +
'?jsonp=GpsGate.Server._callback.' + callId +
'&' + MochiKit.Base.queryString(params) +
'&noCache=' + (new Date()).getTime().toString().substr(5) + id
)
})
);
return d;
};
// convenience
GpsGate.Server.callAuth = function(url, method, params)
{
params = params || {};
params.appId = Franson_Session.ApplicationId;
return GpsGate.Server.call(url, method, params);
};