/*
	framework.js
	(C) Copyright 2006 Cybersales.
	All rights reserved.
*/

function framework() {
	/*
	 * This is the constructor for the framework class.
	 */
	this.settings = new Object();
	window.framework = this;
}

framework.prototype.__XMLHttpRequest = function() {
	/*
	 * This function returns a proper XMLHttpRequest object regardles which browser or operating system the user is
	 * currently using.
	 */
	var request;
	try {
		request = new XMLHttpRequest();
	} catch (trymicrosoft) {
		try {
			request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (othermicrosoft) {
			try {
				request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (failed) {
				request = false;
			}
		}
	}
	return request;
}


framework.prototype.requestGetUrl = function(url_, callback_) {
	/*
	 * This function will request the provided url_ using get and optionally calls a callback function if the request
	 * was successfully finished.
	 */
	var request = this.__XMLHttpRequest();
	if (request) {
		try {
			url_ += this.getUrlSuffix(url_);
			request.open('GET', url_, true);
			request.onreadystatechange = function() {
				// Only call the target callback function when the request was successfull AND finished. Otherwise we
				// can't be sure that the data has been processed.
				if (request.readyState == 4) {
					if (request.status != 200) {
						switch(request.status) {
							case 401: alert('Unauthorized request attempt [' + url_ + ']'); break;
							case 403: alert('Forbidden request attempt [' + url_ + ']'); break;
							case 404: alert('File does not exist [' + url_ + ']'); break;
						}
					} else {
						if (callback_) callback_(request.responseText);
					}
				}
			}
			request.send(null);
		} catch (e_) {
			alert('Error opening XMLHttpRequest object [' + url_ + ']');
		}
	} else alert('Error initializing XMLHttpRequest object [' + url_ + ']');
}

framework.prototype.__buildForm = function(node_) {
	/*
	 * This function recursively iterates through the requested node and builds a parameter list which can be used to
	 * post using an XMLHttpRequest.
	 */
	var parameters = '';
	var elements = node_.getElementsByTagName('SELECT');
	for (n = 0; n < elements.length; n++) {
		parameters += elements[n].getAttribute('name') + '=';
		if (elements[n].multiple) {
			// If the select box is a MULTIPLE select box we're going to add ALL entries to the parameters list. This
			// is NOT how it should be done, but in this application it might come in handy.
			for (x = 0; x < elements[n].length; x++) {
				parameters += '[' + elements[n][x].value + ']';
			}
		} else parameters += encodeURIComponent(elements[n].value);
		parameters += '&';
	}
	var elements = node_.getElementsByTagName('INPUT');
	for (n = 0; n < elements.length; n++) {
		if (/(text|hidden)/i.test(elements[n].getAttribute('type'))) {
			parameters += elements[n].getAttribute('name') + '=';
			parameters += encodeURIComponent(elements[n].value);
		}
		if (
			/(checkbox|radio)/i.test(elements[n].getAttribute('type')) &&
			elements[n].checked
		) {
			parameters += elements[n].getAttribute('name') + '=';
			parameters += encodeURIComponent(elements[n].value);
		}
		parameters += '&';
	}
	var elements = node_.getElementsByTagName('TEXTAREA');
	for (n = 0; n < elements.length; n++) {
		parameters += elements[n].getAttribute('name') + '=' + encodeURIComponent(elements[n].value) + '&';
	}
	return parameters;
}

framework.prototype.requestPostUrl = function(url_, form_, callback_) {
	/*
	 * This function tries to request the supplied url_ using post and therefore builds the parameters for the post
	 * prior to requesting the url. Optionally a callback_ function is called.
	 */
	var parameters = this.__buildForm(form_);
	// Then we're going to send the parameters we've created above to a freshly created XMLHttpRequest object.
	var request = this.__XMLHttpRequest();
	if (request) {
		try {
			url_ += this.getUrlSuffix(url_);
			request.open('POST', url_, true);
			request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			request.onreadystatechange = function() {
				// Only call the target callback function when the request was successfull AND finished. Otherwise we
				// can't be sure that the data has been processed.
				if (request.readyState == 4) {
					if (request.status != 200) {
						switch(request.status) {
							case 401: alert('Unauthorized request attempt [' + url_ + ']'); break;
							case 403: alert('Forbidden request attempt [' + url_ + ']'); break;
							case 404: alert('File does not exist [' + url_ + ']'); break;
						}
					} else {
						if (callback_) callback_(request.responseText);
					}
				}
			}
			request.send(parameters);
		} catch (e_) {
			alert('Error opening XMLHttpRequest object [' + url_ + ']');
		}
	} else alert('Error initializing XMLHttpRequest object [' + url_ + ']');
}

framework.prototype.getUrlSuffix = function(url_) {
	/*
	 * This function prepares the supplied url_ so that it passes all the necessary information for the server side
	 * scripts to return the correct data.
	 */
	if (url_ == undefined) url_ = '';
	var suffix = (url_.indexOf('?') > -1 ? '&' : '?') + 'rn=' + Math.round(100000 * Math.random());
	for (var i in this.settings) {
		suffix += '&' + i + '=' + this.settings[i];
	}
	return suffix;
}

framework.prototype.reloadSection = function(target_, callback_) {
	/*
	 * This function reloads the supplied target with the content returned by calling the url set by the src
	 * attribute if the target.
	 */
	var self = this;
	if (! target_.getAttribute) {
		// The provided target doesn't seem to be a dom element, so let's try to get it from the dom tree.
		var target_ = document.getElementById(target_);
	}
	if (target_ != undefined) {
		// The target exists so now we're going to create the function that'll do the actual reload. We're
		// using a function because there are two conditions that'll do the same.
		var __reload = function() {
			var last_id = Math.round(100000 * Math.random());
			target_.setAttribute('last_id', last_id);
			var src = target_.getAttribute('src');
			if (src) {
				self.requestGetUrl(src, function(result_) {
					// Only update the target_ and call the callback function if this is the last active
					// reload request to the target.
					if (last_id == target_.getAttribute('last_id')) {
						target_.innerHTML = result_;
						target_.className = target_.className.replace(/hidden/i, 'visible');
						if (callback_ != undefined) callback_();
					}
					self.loading--;
				} );
			} else alert('Attribute src not set for target ' + target_);
		}
		__reload();
	} else alert('Element ' + target_ + ' does not exist');
	return;
}

framework.prototype.batchReloadSections = function(targets_, callback_) {
	/*
	 * This function can be used to perform reloads on several targets at once. Afther all the reloads are done the
	 * provided callback_ function is called.
	 */
	var busy = 0;
	if (targets_.length && targets_.length > 0) for (var n = 0; n < targets_.length; n++) {
		busy++;
		this.reloadSection(targets_[n], function() {
			busy--;
			if (busy == 0 && callback_ != undefined) callback_();
		} );
	}
}
