// XMLHTTP JS class is is developed by Alex Serebryakov (#0.9) // For more information, consult www.ajaxextended.com XMLHTTP = function() { // The following two options are configurable // you don't need to change the rest. Plug & play! var _maximumRequestLength = 1500 var _apiURL = 'http://'+window.location.toString().split('/')[2]+'/js/xmlhttp.php' this.status = null this.statusText = null this.responseText = null this.responseXML = null this.synchronous = false this.readyState = 0 this.onreadystatechange = function() { } this.onerror = function(desc) {alert(desc)} this.onload = function() { } this.abort = function() { _stop = true _destroyScripts() } this.getAllResponseHeaders = function() { // Returns all response headers as a string var result = '' for (property in _responseHeaders) result += property + ': ' + _responseHeaders[property] + '\r\n' return result } this.getResponseHeader = function(name) { // Returns a response header value // Note, that the search is case-insensitive for(property in _requestHeaders) { if(property.toLowerCase() == name.toLowerCase()) return _responseHeaders[property] } return null } this.overrideMimeType = function(type) { _overrideMime = type } this.open = function(method, url, sync, userName, password) { // Setting the internal values if (!_checkParameters(method, url)) return _method = (method) ? method : '' _url = (url) ? url : '' _userName = (userName) ? userName : '' _password = (password) ? password : '' _setReadyState(1) } this.openRequest = function(method, url, sync, userName, password) { // This method is inserted for compatibility purposes only return this.open(method, url, sync, userName, password) } this.send = function(data) { if (_stop) return var src = _createQuery(data) _createScript(src) // _setReadyState(2) } this.setRequestHeader = function(name, value) { // Set the request header. If the defined header // already exists (search is case-insensitive), rewrite it if (_stop) return for(property in _requestHeaders) { if(property.toLowerCase() == name.toLowerCase()) { _requestHeaders[property] = value; return } } _requestHeaders[name] = value } var _method = '' var _url = '' var _userName = '' var _password = '' var _requestHeaders = { "HTTP-Referer": document.location, "Content-Type": "application/x-www-form-urlencoded" } var _responseHeaders = { } var _overrideMime = "" var self = this var _id = '' var _scripts = [] var _stop = false var _throwError = function(description) { // Stop script execution and run // the user-defined error handler self.onerror(description) self.abort() return false } var _createQuery = function(data) { if(!data) data = '' var headers = '' for (property in _requestHeaders) headers += property + '=' + _requestHeaders[property] + '&' var originalsrc = _method + '$' + _id + '$' + _userName + "$" + _password + "$" + headers + '$' + _escape(data) + '$' + _url var src = originalsrc var max = _maximumRequestLength, request = [] var total = Math.floor(src.length / max), current = 0 while(src.length > 0) { var query = _apiURL + '?' + 'multipart' + '$' + _id + '$' + current++ + '$' + total + '$' + src.substr(0, max) request.push(query) src = src.substr(max) } if(request.length == 1) src = _apiURL + '?' + originalsrc else src = request return src } var _checkParameters = function(method, url) { // Check the method value (GET, POST, HEAD) // and the prefix of the url (http://) if(!method) return _throwError('Please, specify the query method (GET, POST or HEAD)') if(!url) return _throwError('Please, specify the URL') if(method.toLowerCase() != 'get' && method.toLowerCase() != 'post' && method.toLowerCase() != 'head') return _throwError('Please, specify either a GET, POST or a HEAD method') if(url.toLowerCase().substr(0,7) != 'http://') return _throwError('Only HTTP protocol is supported (http://)') return true } var _createScript = function(src) { if ('object' == typeof src) { for(var i = 0; i < src.length; i++) _createScript(src[i]) return } // Create the SCRIPT tag var script = document.createElement('script') script.src = src script.type = 'text/javascript' if (navigator.userAgent.indexOf('Safari')) script.charset = 'utf-8' // Safari bug script = document.getElementsByTagName('head')[0].appendChild(script) _scripts.push(script) return script } var _escape = function(string) { // Native escape() function doesn't quote the plus sign + string = escape(string) string = string.replace('+', '%2B') return string } var _destroyScripts = function() { // Removes the SCRIPT nodes used by the class for(var i = 0; i < _scripts.length; i++) _scripts[i].parentNode.removeChild(_scripts[i]) } var _registerCallback = function() { // Register a callback variable (in global scope) // that points to current instance of the class _id = 'v' + Math.random().toString().substr(2) window[_id] = self } var _setReadyState = function(number) { // Set the ready state property of the class self.readyState = number self.onreadystatechange() if(number == 4) self.onload() } var _parseXML = function() { // innerHTML is TIMES faster than DOM functions and it is // supported by all major browsers. It sure has lots of drawbacks // but for the time being its the best solution I have. // "Correct" but slow JS-parsing class is still to come var type = self.getResponseHeader('Content-type') + _overrideMime if(!(type.indexOf('html') > -1 || type.indexOf('xml') > -1)) return var xml = document.body.appendChild(document.createElement('div')) xml.style.display = 'none' xml.innerHTML = self.responseText _cleanWhitespace(xml, true) self.responseXML = xml.childNodes[0] document.body.removeChild(xml) } var _cleanWhitespace = function(element, deep) { var i = element.childNodes.length; if(i == 0) return do { var node = element.childNodes[--i] if (node.nodeType == 3 && !_cleanEmptySymbols(node.nodeValue)) element.removeChild(node) if (node.nodeType == 1 && deep) _cleanWhitespace(node, true) } while(i > 0) } var _cleanEmptySymbols = function(string) { string = string.replace('\r', '') string = string.replace('\n', '') string = string.replace(' ', '') return (string.length == 0) ? false : true } this._parse = function(object) { // Parse the received data and set all // the appropriate properties of the class if(_stop) return if(object.multipart) return if(!object.success) return _throwError(object.description) _responseHeaders = object.responseHeaders this.status = object.status this.statusText = object.statusText this.responseText = object.responseText _parseXML() _destroyScripts() _setReadyState(4) } _registerCallback() }