var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{	// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 	// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]
};
BrowserDetect.init();


function OSP_Debug(string)
{
	console.log(string);
}


function byId(id, doc)
{
	if ( id && (typeof id == 'string' || id instanceof String) )
	{
		if ( !doc )
		{
			doc = document;
		}

		return doc.getElementById(id);
	}

	return id;
}


function OSP_GetQueryStrings(url)
{
	var query = "";

	if ( url )
	{
		var pos = url.indexOf('?');
		if ( pos != -1 )
		{
			query = url.substring(pos + 1);
		}
	}
	else
	{
		query = window.location.search.substring(1);
	}

	var args = new Object();

	var pairs = query.split('&');
	for ( var i = 0; i < pairs.length; i++ )
	{
		var pos = pairs[i].indexOf('=');
		if ( pos == -1 ) continue;
		var argname = pairs[i].substring(0, pos);
		var value = pairs[i].substring(pos + 1);
		args[argname] = unescape(value);
	}

	return args;
}



function OSP_GetURL(options)
{
	if ( !options )
	{
		options = new Array();
	}
	if ( !options['url'] )
	{
		options['url'] = window.location.toString();
	}
	if ( !options['query_strings'] )
	{
		options['query_strings'] = new Array();
	}
	if ( !isset(options['format_html']) )
	{
		options['format_html'] = true;
	}

	var separator = options['format_html'] ? '&amp;' : '&';

	var query_strings = array_merge(OSP_GetQueryStrings(options['url']), options['query_strings']);

	var url = options['url'];
	var pos = url.indexOf('?');
	if ( pos != -1 )
	{
		url = url.substr(0, url.indexOf('?'));
	}
	
	// Parse query string
	var query_string = "";
	for ( key in query_strings )
	{
		if ( query_strings[key].length )
		{
			query_string += key + '=' + query_strings[key] + separator;
		}
	}
	var my_regexp = new RegExp(separator + '$', '');
	query_string = query_string.replace(my_regexp, '');

	if ( query_string )
	{
		url += '?' + query_string;
	}

	return url;
}


function SetStyle(elem, style)
{
	var matches;

	if ( elem )
	{
		if ( BrowserDetect.browser == 'Explorer' )
		{
			// IE6 bug : Search for display style
			if ( BrowserDetect.version == 6 && (matches = /display\s*:\s*([a-z]+)/i.exec(style)) )
			{
				elem.style.display = matches[1];
			}

			elem.style.setAttribute('cssText', style, null);
		}
		else
		{
			elem.setAttribute('style', style, null);
		}
	}
}


function SetStyleById(elem_id, style)
{
	SetStyle(byId(elem_id), style);
}


function AppendElement(parent, type, attributes)
{
	var elem = document.createElement(type);

	for ( i in attributes )
	{
		if ( i == 'style' )
		{
			SetStyle(elem, attributes[i]);
		}
		else if ( i == 'class' )
		{
			if ( BrowserDetect.browser == 'Explorer' )
				elem.setAttribute('className', attributes[i]);
			else
				elem.setAttribute(i, attributes[i]);
		}
		else
		{
			elem.setAttribute(i, attributes[i]);
		}
	}

	parent.appendChild(elem);

	return elem;
}


function RemoveChildren(elem)
{
	for ( var i = 0; i < elem.childNodes.length; i++ )
	{
		elem.removeChild(elem.childNodes[i]);
	}
}


function isDefined(variable)
{
	return (!(!(variable || false)))
}


function getElementsByClass(searchClass, node, tag)
{
	var classElements = new Array();
	if ( node == null )
	{
		node = document;
	}
	if ( tag == null )
	{
		tag = '*';
	}
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp('(^|\\s)' + searchClass + '(\\s|$)');

	for ( i = 0, j = 0; i < elsLen; i++ )
	{
		if ( pattern.test(els[i].className) )
		{
			classElements[j] = els[i];
			j++;
		}
	}

	return classElements;
}


function OSP_AppendLoader(container)
{
	var message_box = document.createElement('div');
	message_box.className = 'message_box_loading_container';
	// todo: translate
	message_box.innerHTML = '<div class="message_box_loading">Chargement en cours, veuillez patienter...</div>';

	CenterElem(container, message_box);

	container.appendChild(message_box);

	return message_box;
}


function OSP_RemoveLoader(container)
{
	for ( var i = 0; i < container.childNodes.length; i++ )
	{
		if ( container.childNodes[i].className == 'message_box_loading_container' )
		{
			container.removeChild(container.childNodes[i]);
			break;
		}
	}
}


function OSP_SubmitForm()
{
	if ( typeof CKEDITOR != 'undefined' )
	{
		// Parse CKEditor instances
		for( var name in CKEDITOR.instances )
		{
			// Update the container textarea with WYSIWYG content
			CKEDITOR.instances[name].updateElement();
		}
	}
}


function OSP_InitForm(my_form_id)
{
	var init_code = window[my_form_id + '_init_code'];

	if ( init_code )
	{
		eval(unescape(init_code));
	}

	$('#' + my_form_id).dirtyFields({
		denoteDirtyForm : true,
		dirtyFieldClass : 'osp_dirty',
		dirtyFormClass : 'osp_dirty'
	});
}


function OSP_SetFormDisabled(my_form, disabled_state)
{
	if ( my_form && my_form.elements.length )
	{
		for ( var i = 0; i < my_form.elements.length; i++ )
		{
			if (
				( my_form.elements[i].tagName == 'INPUT' && my_form.elements[i].type != 'hidden' )
				|| my_form.elements[i].tagName == 'SELECT'
				|| my_form.elements[i].tagName == 'BUTTON'
			)
			{
				my_form.elements[i].disabled = disabled_state;
			}
		}
	}
}


function OSP_ReloadForm(my_form)
{
	if ( typeof my_form == "string" )
	{
		my_form = byId(my_form);
	}

	// Create __init fields for all form fields
	var content_arr = Array();
	var my_regexp = new RegExp('^field_' + my_form.id + '_(.+)$', '');
	var matches;
	for ( var key in my_form.elements )
	{
		if ( my_form.elements[key] && my_form.elements[key].name )
		{
			if ( matches = my_form.elements[key].name.match(my_regexp) )
			{
				// This is a checkbox
				if ( my_form.elements[key].tagName == 'INPUT' && my_form.elements[key].type == 'checkbox' )
				{
					if ( my_form.elements[key].checked )
					{
						content_arr['__init_' + my_form.elements[key].name] = $(my_form.elements[key]).val();
					}
					else
					{
						content_arr['__init_' + my_form.elements[key].name] = '';
					}
				}
				// This is NOT a checkbox
				else
				{
					content_arr['__init_' + my_form.elements[key].name] = $(my_form.elements[key]).val();
				}
			}
		}
	}

	// Construct URL
	var url = '?method=ajax';
	url += my_form.elements['object'] ? '&object=' + encodeURIComponent(my_form.elements['object'].value) : '';
	url += my_form.elements['action'] ? '&action=' + encodeURIComponent(my_form.elements['action'].value) : '';
	url += my_form.elements['__step'] ? '&step=' + encodeURIComponent(my_form.elements['__step'].value) : '';
	url += my_form.elements['fid'] ? '&fid=' + encodeURIComponent(my_form.elements['fid'].value) : '';
	url += my_form.elements['referer'] ? '&referer=' + encodeURIComponent(my_form.elements['referer'].value) : '';

	OSP_SetFormDisabled(my_form, true);

	var message_box = OSP_AppendLoader(my_form);

	// Get reloaded form
	dojo.xhrPost({
		url : url,
		content : content_arr,
		load : function(response) { OSP_ReloadForm_OK(my_form, response) },
		error : function(response) { OSP_ReloadForm_Error(my_form, response) }
	});
}


function OSP_ReloadForm_OK(my_form, response)
{
	var my_regexp = new RegExp('^field_' + my_form.id + '_(.+)$', '');
	var matches;

	if ( typeof CKEDITOR != 'undefined' )
	{
		// Parse CKEditor instances
		for( var name in CKEDITOR.instances )
		{
			// This instance concerns reloaded form
			if ( matches = CKEDITOR.instances[name].name.match(my_regexp) )
			{
				CKEDITOR.instances[name].destroy();
			}
		}
	}

	$('#' + my_form.id).replaceWith(response);
}


function OSP_ReloadForm_Error(my_form, response)
{
//	alert('OSP_ReloadForm_Error ' + response.message);
}


function OSP_GetFormField(my_form, field_html_id)
{
	if ( typeof my_form == "string" )
	{
		my_form = byId(my_form);
	}

	return byId('field_' + my_form.id + '_' + field_html_id);
}


function OSP_GetFormFields(my_form, field_html_id)
{
	if ( typeof my_form == "string" )
	{
		my_form = byId(my_form);
	}

	var fields = new Array();

	// Try to get the language selector for this field
	var language_selector = byId('field_' + my_form.id + '_' + field_html_id + '_language');

	// This field is a translation
	if ( language_selector )
	{
		// Parse fields by language
		for ( var i = 0; i < language_selector.options.length; i++ )
		{
			fields.push($('#' + 'field_' + my_form.id + '_' + field_html_id + '_' + language_selector.options[i].value));
		}
	}
	// This field is NOT a translation
	else
	{
		fields.push($('#' + 'field_' + my_form.id + '_' + field_html_id));
	}

	return fields;
}


function OSP_EnableFormField(my_form, field_html_id)
{
	if ( typeof my_form == "string" )
	{
		my_form = byId(my_form);
	}

	var fields = OSP_GetFormFields(my_form, field_html_id);

	for ( var i = 0; i < fields.length; i++ )
	{
		$(fields[i]).attr('disabled', '');
	}
}


function OSP_DisableFormField(my_form, field_html_id)
{
	if ( typeof my_form == "string" )
	{
		my_form = byId(my_form);
	}

	var fields = OSP_GetFormFields(my_form, field_html_id);

	for ( var i = 0; i < fields.length; i++ )
	{
		$(fields[i]).attr('disabled', 'disabled');
	}
}


function OSP_CheckFormDirty(my_form_id, warning_msg)
{
	if ( $.fn.dirtyFields.isDirty($('#' + my_form_id)) )
	{
		return warning_msg;
	}
}


function GetAbsoluteLeftPosition(elem)
{
	var elemLeft = elem.offsetLeft;

	while( elem.offsetParent != null )
	{
		var elemParent = elem.offsetParent;
		elemLeft += elemParent.offsetLeft;
		elem = elemParent;
	}

	return elemLeft;
}


function GetAbsoluteTopPosition(elem)
{
	var elemTop = elem.offsetTop;

	while( elem.offsetParent != null )
	{
		var elemParent = elem.offsetParent;
		elemTop += elemParent.offsetTop;
		elem = elemParent;
	}

	return elemTop;
}


function OSP_ToggleHelpTopic(field_html_id, align_to_elem)
{
	// Remove language ID
	var base_field_html_id = field_html_id.replace(/_sid_(\d+)$/, '_sid');

	if ( !base_field_html_id.match(/^field_/) )
	{
		return;
	}

	if ( !align_to_elem )
	{
		align_to_elem = byId(field_html_id);
	}

	OSP_ToggleHint(base_field_html_id.replace(/^field_/, 'help_topic_'), align_to_elem);
}


function OSP_ToggleHint(hint_id, align_to_elem)
{
	var hint = byId(hint_id);

	if ( hint )
	{
		if ( hint.style.display == 'none' )
		{
			var left = GetAbsoluteLeftPosition(align_to_elem) + align_to_elem.offsetWidth + hint.offsetWidth;
			var top = GetAbsoluteTopPosition(align_to_elem);
			SetStyle(hint, 'display:normal; left:' + left + 'px; top:' + top + 'px;');
		}
		else
		{
			SetStyle(hint, 'display:none;');
		}
	}
}


function OSP_Popup(url, width, height)
{
	if ( !width )
	{
		width = GetClientWidth();
	}
	if ( !height )
	{
		height = GetClientHeight();
	}

	var my_popup = window.open(url, 'osp_popup', 'toolbar=0,menubar=0,location=0,scrollbars=1,resizable=1,directories=0,width=' + width + ',height=' + height);
	my_popup.focus();
}


/*
function SetSelectedOpacity(elem, opacity)
{
	if ( !opacity )
	{
		opacity = '50';
	}

	elem.style.opacity = '.' + opacity;
	elem.style.filter = 'alpha(opacity=' + opacity + ')';
}
function SetFullOpacity(elem)
{
	elem.style.opacity = '';
	elem.style.filter = '';
}
*/


function HasClass(elem, class_name)
{
	if ( elem )
	{
		var class_arr = elem.className.split(' ');

		for ( var i=0; i<class_arr.length; i++ )
		{
			if ( class_arr[i] == class_name )
			{
				return true;
			}
		}
	}

	return false;
}


function AddClass(elem, class_name)
{
	if ( elem )
	{
		var new_class = elem.className + ' ';

		if ( !HasClass(elem, class_name) )
		{
			new_class += class_name + ' ';
		}

		new_class = new_class.substr(0, new_class.length-1);
		elem.className = new_class;
	}
}


function RemoveClass(elem, class_name)
{
	if ( elem )
	{
		var new_class = '';
		var class_arr = elem.className.split(' ');

		for ( var i=0; i<class_arr.length; i++ )
		{
			if ( class_arr[i] != class_name )
			{
				new_class += class_arr[i] + ' ';
			}
		}

		new_class = new_class.substr(0, new_class.length-1);
		elem.className = new_class;
	}
}


function SetOverClass(elem)
{
	AddClass(elem, 'over');
}
function SetOutClass(elem)
{
	RemoveClass(elem, 'over');
}


function SetSelectedClass(elem)
{
	RemoveClass(elem, 'over');
	AddClass(elem, 'selected');
}
function SetNormalClass(elem)
{
	RemoveClass(elem, 'selected');
	RemoveClass(elem, 'over');
}


function SetEnabledClass(elem)
{
	RemoveClass(elem, 'disabled');
	AddClass(elem, 'enabled');
}
function SetDisabledClass(elem)
{
	RemoveClass(elem, 'enabled');
	AddClass(elem, 'disabled');
}


/*
**  sprintf.js -- POSIX sprintf(3) style formatting function for JavaScript
**  Copyright (c) 2006-2007 Ralf S. Engelschall <rse@engelschall.com>
**  Partly based on Public Domain code by Jan Moesen <http://jan.moesen.nu/>
**  Licensed under GPL <http://www.gnu.org/licenses/gpl.txt>
**
**  $LastChangedDate$
**  $LastChangedRevision$
*/

/*  make sure the ECMAScript 3.0 Number.toFixed() method is available  */
if (typeof Number.prototype.toFixed != 'undefined') {
    (function(){
        /*  see http://www.jibbering.com/faq/#FAQ4_6 for details  */
        function Stretch(Q, L, c) {
            var S = Q
            if (c.length > 0)
                while (S.length < L)
                    S = c+S;
            return S;
        }
        function StrU(X, M, N) { /* X >= 0.0 */
            var T, S;
            S = new String(Math.round(X * Number("1e"+N)));
            if (S.search && S.search(/\D/) != -1)
                return ''+X;
            with (new String(Stretch(S, M+N, '0')))
                return substring(0, T=(length-N)) + '.' + substring(T);
        }
        function Sign(X) {
            return X < 0 ? '-' : '';
        }
        function StrS(X, M, N) {
            return Sign(X)+StrU(Math.abs(X), M, N);
        }
        Number.prototype.toFixed = function (n) { return StrS(this, 1, n) };
    })();
}


/*  the sprintf() function  */
sprintf = function () {
    /*  argument sanity checking  */
    if (!arguments || arguments.length < 1)
        alert("sprintf:ERROR: not enough arguments");

    /*  initialize processing queue  */
    var argumentnum = 0;
    var done = "", todo = arguments[argumentnum++];

    /*  parse still to be done format string  */
    var m;
    while (m = /^([^%]*)%(\d+$)?([#0 +'-]+)?(\*|\d+)?(\.\*|\.\d+)?([%diouxXfFcs])(.*)$/.exec(todo)) {
        var pProlog    = m[1],
            pAccess    = m[2],
            pFlags     = m[3],
            pMinLength = m[4],
            pPrecision = m[5],
            pType      = m[6],
            pEpilog    = m[7];

        /*  determine substitution  */
        var subst;
        if (pType == '%')
            /*  special case: escaped percent character  */
            subst = '%';
        else {
            /*  parse padding and justify aspects of flags  */
            var padWith = ' ';
            var justifyRight = true;
            if (pFlags) {
                if (pFlags.indexOf('0') >= 0)
                    padWith = '0';
                if (pFlags.indexOf('-') >= 0) {
                    padWith = ' ';
                    justifyRight = false;
                }
            }
            else
                pFlags = "";

            /*  determine minimum length  */
            var minLength = -1;
            if (pMinLength) {
                if (pMinLength == "*") {
                    var access = argumentnum++;
                    if (access >= arguments.length)
                        alert("sprintf:ERROR: not enough arguments");
                    minLength = arguments[access];
                }
                else
                    minLength = parseInt(pMinLength, 10);
            }

            /*  determine precision  */
            var precision = -1;
            if (pPrecision) {
                if (pPrecision == ".*") {
                    var access = argumentnum++;
                    if (access >= arguments.length)
                        alert("sprintf:ERROR: not enough arguments");
                    precision = arguments[access];
                }
                else
                    precision = parseInt(pPrecision.substring(1), 10);
            }

            /*  determine how to fetch argument  */
            var access = argumentnum++;
            if (pAccess)
                access = parseInt(pAccess.substring(0, pAccess.length - 1), 10);
            if (access >= arguments.length)
                alert("sprintf:ERROR: not enough arguments");

            /*  dispatch into expansions according to type  */
            var prefix = "";
            switch (pType) {
                case 'd':
                case 'i':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = subst.toString(10);
                    if (pFlags.indexOf('#') >= 0 && subst >= 0)
                        subst = "+" + subst;
                    if (pFlags.indexOf(' ') >= 0 && subst >= 0)
                        subst = " " + subst;
                    break;
                case 'o':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = subst.toString(8);
                    break;
                case 'u':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = Math.abs(subst);
                    subst = subst.toString(10);
                    break;
                case 'x':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = subst.toString(16).toLowerCase();
                    if (pFlags.indexOf('#') >= 0)
                        prefix = "0x";
                    break;
                case 'X':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = subst.toString(16).toUpperCase();
                    if (pFlags.indexOf('#') >= 0)
                        prefix = "0X";
                    break;
                case 'f':
                case 'F':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0.0;
                    subst = 0.0 + subst;
                    if (precision > -1) {
                        if (subst.toFixed)
                            subst = subst.toFixed(precision);
                        else {
                            subst = (Math.round(subst * Math.pow(10, precision)) / Math.pow(10, precision));
                            subst += "0000000000";
                            subst = subst.substr(0, subst.indexOf(".")+precision+1);
                        }
                    }
                    subst = '' + subst;
                    if (pFlags.indexOf("'") >= 0) {
                        var k = 0;
                        for (var i = (subst.length - 1) - 3; i >= 0; i -= 3) {
                            subst = subst.substring(0, i) + (k == 0 ? "." : ",") + subst.substring(i);
                            k = (k + 1) % 2;
                        }
                    }
                    break;
                case 'c':
                    subst = arguments[access];
                    if (typeof subst != "number")
                        subst = 0;
                    subst = String.fromCharCode(subst);
                    break;
                case 's':
                    subst = arguments[access];
                    if (precision > -1)
                        subst = subst.substr(0, precision);
                    if (typeof subst != "string")
                        subst = "";
                    break;
            }

            /*  apply optional padding  */
            var padding = minLength - subst.toString().length - prefix.toString().length;
            if (padding > 0) {
                var arrTmp = new Array(padding + 1);
                if (justifyRight)
                    subst = arrTmp.join(padWith) + subst;
                else
                    subst = subst + arrTmp.join(padWith);
            }

            /*  add optional prefix  */
            subst = prefix + subst;
        }

        /*  update the processing queue  */
        done = done + pProlog + subst;
        todo = pEpilog;
    }
    return (done + todo);
}


function CenterElem(container, elem)
{
	SetStyle(elem, 'display:normal;');

	var left = container.offsetLeft + container.offsetWidth / 2 - elem.offsetWidth / 2;
	var top = container.offsetTop + container.offsetHeight / 2 - elem.offsetHeight / 2;

	SetStyle(elem, 'display:normal; left:' + left + 'px; top:' + top + 'px;');
}


function CenterElemOnWindow(elem)
{
	SetStyle(elem, 'display:normal;');

	var left = GetClientWidth() / 2 - elem.offsetWidth / 2;
	var top = GetClientHeight() / 2 - elem.offsetHeight / 2;

	SetStyle(elem, 'display:normal; left:' + left + 'px; top:' + top + 'px;');
}


function GetClientWidth()
{
	var D = document;
	return Math.max(Math.max(D.body.scrollWidth, D.documentElement.scrollWidth), Math.max(D.body.offsetWidth, D.documentElement.offsetWidth), Math.max(D.body.clientWidth, D.documentElement.clientWidth));
}


function GetClientHeight()
{
	var D = document;
	return Math.max(Math.max(D.body.scrollHeight, D.documentElement.scrollHeight), Math.max(D.body.offsetHeight, D.documentElement.offsetHeight), Math.max(D.body.clientHeight, D.documentElement.clientHeight));
}


function SetSelectionRange(input, start, end)
{
	if ( start && end )
	{
		if ( BrowserDetect.browser == 'Explorer' )
		{
			var range = input.createTextRange();
			range.collapse(true);
			range.moveStart('character', start);
			range.moveEnd('character', end - start);
			range.select();
		}
		else
		{
			input.setSelectionRange(start, end);
		}
	}
};


function GetSelectionStart(input)
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		var range = document.selection.createRange();
		var isCollapsed = range.compareEndPoints('StartToEnd', range) == 0;
		if ( !isCollapsed )
		{
			range.collapse(true);
		}
		var b = range.getBookmark();
		return b.charCodeAt(2) - 2;
	}
	else
	{
		return input.selectionStart;
	}
};


function GetSelectionEnd(input)
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		var range = document.selection.createRange();
		var isCollapsed = range.compareEndPoints('StartToEnd', range) == 0;
		if ( !isCollapsed )
		{
			range.collapse(false);
		}
		var b = range.getBookmark();
		return b.charCodeAt(2) - 2;
	}
	else
	{
		return input.selectionEnd;
	}
};


function AddLoadEvent(func)
{
	var previous_onload = window.onload;

	if ( typeof window.onload != 'function' )
	{
		window.onload = function()
		{
			if ( typeof func == 'function' )
				func();
			else
				eval(func);
		};
	}
	else
	{
		window.onload = function()
		{
			previous_onload();
			if ( typeof func == 'function' )
				func();
			else
				eval(func);
		};
	}
}


function GetContentWidth(elem)
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		var size = elem.offsetWidth;
		var computed_style = elem.currentStyle;
		size -= ( computed_style.borderLeft ) ? parseInt(computed_style.borderLeft) : 0;
		size -= ( computed_style.paddingLeft ) ? parseInt(computed_style.paddingLeft) : 0;
		size -= ( computed_style.paddingRight ) ? parseInt(computed_style.paddingRight) : 0;
		size -= ( computed_style.borderRight ) ? parseInt(computed_style.borderRight) : 0;
	}
	else
	{
		var size = elem.offsetWidth;
		var computed_style = document.defaultView.getComputedStyle(elem, null);
		size -= ( computed_style.getPropertyValue('border-left') ) ? parseInt(computed_style.getPropertyValue('border-left')) : 0;
		size -= ( computed_style.getPropertyValue('padding-left') ) ? parseInt(computed_style.getPropertyValue('padding-left')) : 0;
		size -= ( computed_style.getPropertyValue('padding-right') ) ? parseInt(computed_style.getPropertyValue('padding-right')) : 0;
		size -= ( computed_style.getPropertyValue('border-right') ) ? parseInt(computed_style.getPropertyValue('border-right')) : 0;
	}

	return size;
}


function GetContentHeight(elem)
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		var size = elem.offsetHeight;
		var computed_style = elem.currentStyle;
		size -= ( computed_style.borderTop ) ? parseInt(computed_style.borderTop) : 0;
		size -= ( computed_style.paddingTop ) ? parseInt(computed_style.paddingTop) : 0;
		size -= ( computed_style.paddingBottom ) ? parseInt(computed_style.paddingBottom) : 0;
		size -= ( computed_style.borderBottom ) ? parseInt(computed_style.borderBottom) : 0;
	}
	else
	{
		var size = elem.offsetHeight;
		var computed_style = document.defaultView.getComputedStyle(elem, null);
		size -= ( computed_style.getPropertyValue('border-top') ) ? parseInt(computed_style.getPropertyValue('border-top')) : 0;
		size -= ( computed_style.getPropertyValue('padding-top') ) ? parseInt(computed_style.getPropertyValue('padding-top')) : 0;
		size -= ( computed_style.getPropertyValue('padding-bottom') ) ? parseInt(computed_style.getPropertyValue('padding-bottom')) : 0;
		size -= ( computed_style.getPropertyValue('border-bottom') ) ? parseInt(computed_style.getPropertyValue('border-bottom')) : 0;
	}

	return size;
}


function SetCookie(name, value, expires, path, domain, secure)
{
	var szCookie = name + '=' + encodeURIComponent(value) +
		((expires) ? '; expires=' + expires.toGMTString() : '') +
		((path) ? '; path=' + path : '') +
		((domain) ? '; domain=' + domain : '') +
		((secure) ? '; secure' : '');

	document.cookie = szCookie;
}


function GetCookie(name)
{
	if ( document.cookie )
	{
		index = document.cookie.indexOf(name);
		if ( index != -1 )
		{
			nDeb = (document.cookie.indexOf( '=', index) + 1);
			nFin = document.cookie.indexOf( ';', index);
			if ( nFin == -1 )
			{
				nFin = document.cookie.length;
			}
			return unescape(document.cookie.substring(nDeb, nFin));
		}
	}

	return null;
}


function SetSessionVar(name, value)
{
	dojo.xhrGet({
		url : '?method=ajax&object=user&action=set_session_var&session_var_name=' + encodeURIComponent(name) + '&session_var_value=' + encodeURIComponent(value)
	});
}


function DisableOnBeforeUnload()
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		window.document.body.onbeforeunload = null;
	}
	else
	{
		window.onbeforeunload = null;
	}
}


function DisableOnUnload()
{
	if ( BrowserDetect.browser == 'Explorer' )
	{
		window.document.body.onunload = null;
	}
	else
	{
		window.onunload = null;
	}
}


function array_merge () {
    // Merges elements from passed arrays into one array  
    // 
    // version: 1102.614
    // discuss at: http://phpjs.org/functions/array_merge    // +   original by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Nate
    // +   input by: josh
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: arr1 = {"color": "red", 0: 2, 1: 4}    // *     example 1: arr2 = {0: "a", 1: "b", "color": "green", "shape": "trapezoid", 2: 4}
    // *     example 1: array_merge(arr1, arr2)
    // *     returns 1: {"color": "green", 0: 2, 1: 4, 2: "a", 3: "b", "shape": "trapezoid", 4: 4}
    // *     example 2: arr1 = []
    // *     example 2: arr2 = {1: "data"}    // *     example 2: array_merge(arr1, arr2)
    // *     returns 2: {0: "data"}
    var args = Array.prototype.slice.call(arguments),
        retObj = {},
        k, j = 0,        i = 0,
        retArr = true;
 
    for (i = 0; i < args.length; i++) {
        if (!(args[i] instanceof Array)) {            retArr = false;
            break;
        }
    }
     if (retArr) {
        retArr = [];
        for (i = 0; i < args.length; i++) {
            retArr = retArr.concat(args[i]);
        }        return retArr;
    }
    var ct = 0;
 
    for (i = 0, ct = 0; i < args.length; i++) {        if (args[i] instanceof Array) {
            for (j = 0; j < args[i].length; j++) {
                retObj[ct++] = args[i][j];
            }
        } else {            for (k in args[i]) {
                if (args[i].hasOwnProperty(k)) {
                    if (parseInt(k, 10) + '' === k) {
                        retObj[ct++] = args[i][k];
                    } else {                        retObj[k] = args[i][k];
                    }
                }
            }
        }    }
    return retObj;
}


function isset () {
    // !No description available for isset. @php.js developers: Please update the function summary text file.
    // 
    // version: 1102.614
    // discuss at: http://phpjs.org/functions/isset    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: FremyCompany
    // +   improved by: Onno Marsman
    // +   improved by: Rafał Kukawski
    // *     example 1: isset( undefined, true);    // *     returns 1: false
    // *     example 2: isset( 'Kevin van Zonneveld' );
    // *     returns 2: true
    var a = arguments,
        l = a.length,        i = 0,
        undef;
 
    if (l === 0) {
        throw new Error('Empty isset');    }
 
    while (i !== l) {
        if (a[i] === undef || a[i] === null) {
            return false;        }
        i++;
    }
    return true;
}

