var XOAD_ERROR_USER = 0x400; var XOAD_ERROR_TIMEOUT = 0x401; var xoad = {}; xoad.errorHandler = null; xoad.callbacks = {}; xoad.callbacks.table = {}; xoad.callbacks.count = 0; xoad.events = {}; xoad.events.table = []; xoad.events.postTable = []; xoad.events.timeout = 5000; xoad.events.startInterval = 250; xoad.events.refreshInterval = 2000; xoad.events.status = 0; xoad.observers = []; xoad.asyncCall = function() {}; xoad.callSuspender = function(xmlhttpobj) { return { suspend : function() { this.suspended = true; }, abort : function() { this.suspend(); this.xmlHTTPObject.abort(); }, suspended : false, xmlHTTPObject : xmlhttpobj } }; xoad.getError = function(errorCode, errorMessage) { return { code : errorCode, message : errorMessage } }; xoad.getXmlHttp = function() { var xmlHttp = null; try { xmlHttp = new XMLHttpRequest(); } catch (e) { var progIds = ['MSXML2.XMLHTTP', 'Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0']; var success = false; for (var iterator = 0; (iterator < progIds.length) && ( ! success); iterator ++) { try { xmlHttp = new ActiveXObject(progIds[iterator]); success = true; } catch (e) {} } if ( ! success ) { return null; } } return xmlHttp; }; xoad.clone = function(target, source) { var wipeKeys = []; var key = null; for (key in target.__meta) { if (typeof(source[key]) == 'undefined') { wipeKeys[wipeKeys.length] = key; } } if (wipeKeys.length > 0) { for (var iterator = 0; iterator < wipeKeys.length; iterator ++) { target[wipeKeys[iterator]] = null; } } for (key in source.__meta) { if (source[key] == null) { target[key] = null; } else { target[key] = source[key]; } } target.__meta = source.__meta; target.__size = source.__size; target.__timeout = source.__timeout; }; xoad.serialize = function(data) { if (data == null) { return 'N;'; } var type = typeof(data); var code = ''; var iterator = 0; var length = null; var asciiCode = null; var key = null; if (type == 'boolean') { code += 'b:' + (data ? 1 : 0) + ';'; } else if (type == 'number') { if (Math.round(data) == data) { code += 'i:' + data + ';'; } else { code += 'd:' + data + ';'; } } else if (type == 'string') { length = data.length; for (iterator = 0; iterator < data.length; iterator ++) { asciiCode = data.charCodeAt(iterator); if ((asciiCode >= 0x00000080) && (asciiCode <= 0x000007FF)) { length += 1; } else if ((asciiCode >= 0x00000800) && (asciiCode <= 0x0000FFFF)) { length += 2; } else if ((asciiCode >= 0x00010000) && (asciiCode <= 0x001FFFFF)) { length += 3; } else if ((asciiCode >= 0x00200000) && (asciiCode <= 0x03FFFFFF)) { length += 4; } else if ((asciiCode >= 0x04000000) && (asciiCode <= 0x7FFFFFFF)) { length += 5; } } code += 's:' + length + ':"' + data + '";'; } else if (type == 'object') { if (typeof(data.__class) == 'undefined') { length = 0; if ( (typeof(data.length) == 'number') && (data.length > 0) && (typeof(data[0]) != 'undefined')) { for (iterator = 0; iterator < data.length; iterator ++) { if (typeof(data[iterator]) != 'function') { code += xoad.serialize(iterator); code += xoad.serialize(data[iterator]); length ++; } } } else { for (key in data) { if (typeof(data[key]) != 'function') { if (/^[0-9]+$/.test(key)) { code += xoad.serialize(parseInt(key)); } else { code += xoad.serialize(key); } code += xoad.serialize(data[key]); length ++; } } } code = 'a:' + length + ':{' + code + '}'; } else { code += 'O:' + data.__class.length + ':"' + data.__class + '":' + data.__size + ':{'; if (data.__meta != null) { for (key in data.__meta) { if (typeof(data[key]) != 'function') { code += xoad.serialize(key); code += xoad.serialize(data[key]); } } } code += '}'; } } else { code = 'N;' } return code; }; xoad.setErrorHandler = function(handler) { if ( (handler != null) && (typeof(handler) == 'function')) { xoad.errorHandler = handler; return true; } return false; }; xoad.restoreErrorHandler = function() { xoad.errorHandler = null; return true; }; xoad.throwException = function(error, throwArguments) { if (typeof(throwArguments) != 'undefined') { var sender = throwArguments[0]; var method = throwArguments[1]; method = 'on' + method.charAt(0).toUpperCase() + method.substr(1) + 'Error'; if (xoad.invokeMethod(sender, method, [error])) { return false; } } if ( (xoad.errorHandler != null) && (typeof(xoad.errorHandler) == 'function')) { xoad.errorHandler(error); return false; } throw error; }; xoad.invokeMethod = function(obj, method, invokeArguments) { if ( (obj == null) || (typeof(obj) != 'object')) { return false; } var type = eval('typeof(obj.' + method + ')'); if (type == 'function') { var invokeCode = 'obj.' + method + '('; if (typeof(invokeArguments) != 'undefined') { for (var iterator = 0; iterator < invokeArguments.length; iterator ++) { invokeCode += 'invokeArguments[' + iterator + ']'; if (iterator < invokeArguments.length - 1) { invokeCode += ', '; } } } invokeCode += ')'; return eval(invokeCode); } return false; }; xoad.call = function(obj, method, callArguments) { if ( (obj == null) || (typeof(obj) != 'object') || (typeof(obj.__class) != 'string')) { return false; } var methodCallback = null; var methodArgs = []; for (var iterator = 0; iterator < callArguments.length; iterator ++) { if ( (typeof(callArguments[iterator]) == 'function') && (iterator == callArguments.length - 1)) { methodCallback = callArguments[iterator]; continue; } methodArgs[methodArgs.length] = callArguments[iterator]; } var xmlHttp = xoad.getXmlHttp(); var requestBody = { source : obj, className : obj.__class, method : method, arguments : methodArgs }; xoad.notifyObservers('call', requestBody); requestBody.source = xoad.serialize(requestBody.source); requestBody.arguments = xoad.serialize(requestBody.arguments); requestBody = xoad.serialize(requestBody); var url = obj.__url; if (url.indexOf('?') < 0) { url += '?'; } else { url += '&'; } url += 'xoadCall=true'; if (methodCallback != null) { xmlHttp.open('POST', url, true); } else { xmlHttp.open('POST', url, false); } var callId = null; var callTimeout = obj.getTimeout(); if (callTimeout != null) { callId = xoad.callbacks.count; } xoad.callbacks.count ++; var callResult = true; var requestCompleted = function() { if (typeof(callResult) == 'object') { if (callResult.suspended) { return false; } } if (callId != null) { if (eval('xoad.callbacks.table.call' + callId + '.timeout')) { return false; } eval('window.clearTimeout(xoad.callbacks.table.call' + callId + '.id)'); eval('xoad.callbacks.table.call' + callId + ' = null'); } if (xmlHttp.status != 200) { return xoad.throwException(xoad.getError(xmlHttp.status, xmlHttp.statusText), [obj, method]); } else { if (xmlHttp.responseText == null) { return xoad.throwException(xoad.getError(xmlHttp.status, 'Empty response.'), [obj, method]); } if (xmlHttp.responseText.length < 1) { return xoad.throwException(xoad.getError(xmlHttp.status, 'Empty response.'), [obj, method]); } try { eval('var xoadResponse = ' + xmlHttp.responseText + ';'); } catch(e) { return xoad.throwException(xoad.getError(xmlHttp.status, 'Invalid response.'), [obj, method]); } if (typeof(xoadResponse.exception) != 'undefined') { return xoad.throwException(xoad.getError(XOAD_ERROR_USER, xoadResponse.exception), [obj, method]); } if (xoad.notifyObservers('callCompleted', xoadResponse)) { obj.__clone(xoadResponse.returnObject); if (typeof(xoadResponse.output) != 'undefined') { obj.__output = xoadResponse.output; } else { obj.__output = null; } return { returnValue : xoadResponse.returnValue }; } } return false; }; try { xmlHttp.setRequestHeader('Content-Length', requestBody.length); xmlHttp.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8'); xmlHttp.setRequestHeader('Accept-Charset', 'UTF-8'); } catch (e) {} if (methodCallback != null) { xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { var response = requestCompleted(); if (typeof(response.returnValue) != 'undefined') { methodCallback(response.returnValue); } } } } if (callTimeout != null) { eval('xoad.callbacks.table.call' + callId + ' = {}'); eval('xoad.callbacks.table.call' + callId + '.timeout = false'); eval('xoad.callbacks.table.call' + callId + '.source = obj'); eval('xoad.callbacks.table.call' + callId + '.id = ' + 'window.setTimeout(\'xoad.callbacks.table.call' + callId + '.timeout = true; ' + 'xoad.throwException(xoad.getError(XOAD_ERROR_TIMEOUT, "Timeout."), [xoad.callbacks.table.call' + callId + '.source, "' + method + '"]);\', callTimeout)'); } xmlHttp.send(requestBody); if (methodCallback == null) { var response = requestCompleted(); if (typeof(response.returnValue) != 'undefined') { return response.returnValue; } return null; } else { callResult = new xoad.callSuspender(xmlHttp); return callResult; } }; xoad.catchEvent = function(obj, eventArguments) { if (eventArguments.length < 2) { eventArguments[1] = null; } var eventData = { listener : obj, event : eventArguments[0], filter : eventArguments[1] }; xoad.events.table[xoad.events.table.length] = eventData; xoad.events.tableLength ++; if (xoad.events.status < 1) { xoad.events.status = 1; window.setTimeout('xoad.dispatchEvents()', xoad.events.startInterval); } return true; }; xoad.ignoreEvent = function(obj, eventArguments) { if (xoad.events.tableLength < 1) { return false; } if (eventArguments.length < 2) { eventArguments[1] = null; } for (var iterator = xoad.events.table.length - 1; iterator >= 0; iterator --) { var event = xoad.events.table[iterator]; if ( (event.listener.__uid == obj.__uid) && (event.event == eventArguments[0]) && (event.filter == eventArguments[1])) { xoad.events.table[iterator] = null; xoad.events.tableLength --; break; } } return true; }; xoad.queueDispatchEvents = function(time) { if (typeof(time) == 'undefined') { time = xoad.events.refreshInterval; } window.setTimeout('xoad.dispatchEvents()', time); }; xoad.dispatchEvents = function() { if (xoad.events.tableLength < 1) { xoad.events.status = 0; return false; } if ( (typeof(xoad.events.callbackUrl) != 'string') || (typeof(xoad.events.lastRefresh) != 'number')) { xoad.events.status = 0; return false; } xoad.events.status = 1; var eventsData = []; for (var iterator = 0; iterator < xoad.events.table.length; iterator ++) { var event = xoad.events.table[iterator]; if (event != null) { eventsData[eventsData.length] = { className : event.listener.__class, event : event.event, filter : event.filter }; } } var xmlHttp = xoad.getXmlHttp(); var requestBody = xoad.serialize({ eventsCallback : true, time : xoad.events.lastRefresh, data : eventsData }); var url = xoad.events.callbackUrl; if (url.indexOf('?') < 0) { url += '?'; } else { url += '&'; } url += 'xoadCall=true'; xmlHttp.open('POST', url, true); var callId = xoad.callbacks.count ++; var requestCompleted = function() { if (eval('xoad.callbacks.table.call' + callId + '.timeout')) { return false; } eval('window.clearTimeout(xoad.callbacks.table.call' + callId + '.id)'); eval('xoad.callbacks.table.call' + callId + ' = null'); if (xmlHttp.status != 200) { xoad.queueDispatchEvents(); return false; } else { if (xmlHttp.responseText == null) { xoad.queueDispatchEvents(); return false; } if (xmlHttp.responseText.length < 1) { xoad.queueDispatchEvents(); return false; } try { eval('var xoadResponse = ' + xmlHttp.responseText + ';'); } catch(e) { xoad.queueDispatchEvents(); return false; } if (typeof(xoadResponse) != 'object') { xoad.queueDispatchEvents(); return false; } if (xoad.notifyObservers('dispatchEventsCompleted', xoadResponse)) { for (var serverIterator = 0; serverIterator < xoadResponse.result.length; serverIterator ++) { var serverEvent = xoadResponse.result[serverIterator]; for (var clientIterator = 0; clientIterator < xoad.events.table.length; clientIterator ++) { var clientEvent = xoad.events.table[clientIterator]; if (clientEvent != null) { if ( (serverEvent.event == clientEvent.event) && (serverEvent.className.toLowerCase() == clientEvent.listener.__class.toLowerCase()) && (serverEvent.filter == clientEvent.filter)) { eval('if (typeof(clientEvent.listener.' + clientEvent.event + ') == "function") { ' + 'clientEvent.listener.' + clientEvent.event + '(serverEvent.eventData.sender, serverEvent.eventData.data) }'); } } } if (serverEvent.time > xoad.events.lastRefresh) { xoad.events.lastRefresh = serverEvent.time; } } xoad.queueDispatchEvents(); return true; } } return false; }; try { xmlHttp.setRequestHeader('Content-Length', requestBody.length); xmlHttp.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8'); xmlHttp.setRequestHeader('Accept-Charset', 'UTF-8'); } catch (e) {} xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { xoad.events.status = 3; requestCompleted(); xoad.events.status = 1; } }; eval('xoad.callbacks.table.call' + callId + ' = {}'); eval('xoad.callbacks.table.call' + callId + '.timeout = false'); eval('xoad.callbacks.table.call' + callId + '.id = ' + 'window.setTimeout(\'xoad.callbacks.table.call' + callId + '.timeout = true; ' + 'xoad.queueDispatchEvents();\', xoad.events.timeout)'); xoad.events.status = 2; xmlHttp.send(requestBody); return true; }; xoad.queuePostEvent = function(eventId) { if (typeof(xoad.events.postTable[eventId]) == 'object') { xoad.postEvent(xoad.events.postTable[eventId].sender, [ xoad.events.postTable[eventId].event, xoad.events.postTable[eventId].data, xoad.events.postTable[eventId].filter, eventId]); } }; xoad.postEvent = function(obj, eventArguments) { if (typeof(xoad.events.callbackUrl) != 'string') { return false; } var eventName = eventArguments[0]; var eventData = (eventArguments.length > 1) ? eventArguments[1] : null; var eventFilter = (eventArguments.length > 2) ? eventArguments[2] : null; var eventId = (eventArguments.length > 3) ? eventArguments[3] : xoad.events.postTable.length; xoad.events.postTable[eventId] = { sender : obj, event : eventName, data : eventData, filter : eventFilter }; var xmlHttp = xoad.getXmlHttp(); var requestBody = xoad.serialize({ eventPost : true, className : obj.__class, sender : xoad.serialize(obj), event : eventName, data : eventData, filter : eventFilter }); var url = xoad.events.callbackUrl; if (url.indexOf('?') < 0) { url += '?'; } else { url += '&'; } url += 'xoadCall=true'; xmlHttp.open('POST', url, true); var requestCompleted = function() { if (xmlHttp.status != 200) { xoad.queuePostEvent(eventId); return false; } else { if (xmlHttp.responseText == null) { xoad.queuePostEvent(eventId); return false; } if (xmlHttp.responseText.length < 1) { xoad.queuePostEvent(eventId); return false; } try { eval('var xoadResponse = ' + xmlHttp.responseText + ';'); } catch(e) { xoad.queuePostEvent(eventId); return false; } if (typeof(xoadResponse) != 'object') { xoad.queuePostEvent(eventId); return false; } if (xoadResponse.status != true) { xoad.queuePostEvent(eventId); return false; } if (xoad.notifyObservers('postEventCompleted', xoadResponse)) { xoad.events.postTable[eventId] = null; return true; } } return false; }; try { xmlHttp.setRequestHeader('Content-Length', requestBody.length); xmlHttp.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8'); xmlHttp.setRequestHeader('Accept-Charset', 'UTF-8'); } catch (e) {} xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { requestCompleted(); } }; xmlHttp.send(requestBody); return true; }; xoad.addObserver = function(observer) { xoad.observers[xoad.observers.length] = observer; return true; }; xoad.notifyObservers = function(event) { if (xoad.observers.length < 1) { return true; } var eventMethod = 'on' + event.charAt(0).toUpperCase() + event.substr(1); var notifyArguments = []; var iterator = 0; for (iterator = 1; iterator < arguments.length; iterator ++) { notifyArguments[notifyArguments.length] = arguments[iterator]; } for (iterator = 0; iterator < xoad.observers.length; iterator ++) { xoad.invokeMethod(xoad.observers[iterator], eventMethod, notifyArguments); } return true; };