if (typeof Util == "undefined") {
    var Util = {
        showDumpInfo: function (dumpId){
            var parent = $('#dumpObject_Parent_'+dumpId);
            var off = parent.offset();
            $('#dumpObject_Data_'+dumpId).detach().appendTo("body").css({
                left: off.left + parent.width(),
                top: off.top + parent.height(),
                position: 'absolute'
            });
            $('#dumpObject_Data_'+dumpId).toggle();
            return false;
        },

        rememberUsernameCookie: "REMEMBER_USERNAME",
        /*
         * Sets cookie with specified attributes
         */
        setCookie: function (sName, sValue, nHours) {
            var date = new Date();
            date.setTime(date.getTime() + (nHours*60*60*1000));
            var expires = "";
            if (typeof nHours != "undefined") {
                expires = "; expires=" + date.toGMTString();
            }
            document.cookie = sName + "=" + sValue + expires + "; path=/";
        },

        getCookie: function (sCookieName) {
            var sName = sCookieName + "=";
            var aCookies = document.cookie.split(';');
            for(var i=0;i < aCookies.length; i++) {
                var c = aCookies[i];
                while (c.charAt(0)==' ') {
                    c = c.substring(1, c.length);
                }
                if (c.indexOf(sName) == 0) {
                    return c.substring(sName.length, c.length);
                }
            }
            return null;
        },

        showHideSearchSettings: function (href, settings) {
            var settingsVisible = false;
            if (settings.style.display == 'block') {
                this.hideSearchSettings(href, settings);
            } else {
                this.showSearchSettings(href, settings);
                settingsVisible = true;
            }
            this.setCookie(settings.id, settingsVisible);
            return false;
	    },

        showSearchSettings: function (href, settings) {
            settings.style.display = 'block';
            href.innerHTML = "Less";
        },

        hideSearchSettings: function (href, settings) {
            settings.style.display = 'none';
            href.innerHTML = "More";
        },

        setRememberUsernameCookie: function (sUsername, sPortalName) {
            this.setCookie(this.rememberUsernameCookie + "_" + sPortalName, sUsername, 10000);
        },

        deleteRememberUsernameCookie: function (sPortalName) {
            this.setCookie(this.rememberUsernameCookie + "_" + sPortalName, "", -1);
        },

        getRememberUsernameCookie: function (sPortalName) {
            return this.getCookie(this.rememberUsernameCookie + "_" + sPortalName);
        },
        /**
         * 1 => {1:1}
         * Useful for filling select elements.
         */
        toMap: function (array) {
            return $.map(array, function(val) {
                return {key: val, value: val};
            });
        },

        /**
         * Create array with years for given range relative to current year.
         *
         * Return array with years.
         */
        getYearsRange: function(pastOffset, futureOffset) {
            var years = [];
            var startFromYear = new Date().getFullYear() - pastOffset;
            for (var i = 0; i <= pastOffset + futureOffset; i++) {
                years[i] = startFromYear + i;
            }
            return years;
        },

        /**
         * Fill in select element by given data;
         * @selectedValue the value which should be set as selected.
         * @param values Array of values.
         * @selectId selectId of select element.
         * @needEmptyValue set to true if you want that an option with empty value will be added.
         */
 		fillSelect: function (selectId, values, selectedValue, needEmptyValue, keyValue, keyLabel) {
			var $select = $("#" + selectId);
			if ($select.length > 0) {
				$select.empty();
                if(typeof keyLabel == 'undefined'){keyLabel = 'label';}
                if(typeof keyValue == 'undefined'){keyValue = 'value';}

                if (needEmptyValue) {
                    values.unshift({keyLabel: '', keyValue: ''});
				}
                var selectedIndex = 0;
                for (var i = 0; i < values.length; i++) {
                    var value = '' + values[i][keyValue];
                    var option = "<option value='" + value + "'";
                    if (selectedValue == value) {
                        option = option+" selected ";
                    }
                    option = option+">" + values[i][keyLabel] + "</option>";
                    $(option).appendTo($select);
                }
                //setTimeout(function() {$select.get(0).selectedIndex = selectedIndex;}, 1);
            }
		},

        setObjectPropertyValue: function(object, propName, propValue) {
            if (propName) {
                propName = propName.replace(/\[([^\]]+?)\]/g, ".$1");
                var props = propName.split('.');
                var obj = object;
                for (var i = 0; i < props.length - 1; i++) {
                    var prop = obj[props[i]];
                    if (!prop) {
                        prop = {};
                        obj[props[i]] = prop;
                    }
                    obj = prop;
                }
                obj[props[props.length - 1]] = propValue;
            }
            return object;
        },

        addObjectPropertyValue: function(object, propName, propValue) {
			// adds property value as array - if already exists
            if (propName) {
                propName = propName.replace(/\[([^\]]+?)\]/g, ".$1");
                var props = propName.split('.');
                var obj = object;
                for (var i = 0; i < props.length - 1; i++) {
                    var prop = obj[props[i]];
                    if (!prop) {
                        prop = {};
                        obj[props[i]] = prop;
                    }
                    obj = prop;
                }
				if(!obj[props[props.length - 1]]){
				    obj[props[props.length - 1]] = propValue;
				}else{
					if(Util.isArray(obj[props[props.length - 1]])){
						obj[props[props.length - 1]][ obj[props[props.length - 1]].length ] = propValue;
					}else{
						var tmp = obj[props[props.length - 1]];
						obj[props[props.length - 1]] = [tmp, propValue];
					}
				}
            }
            return object;
        },

        getObjectPropertyValue: function(object, propName) {
            var props = propName.split(".");
            var obj = object;
            for (var i = 0; i < props.length - 1; i++) {
                obj = obj[props[i]];
                if (!obj) {
                    return null;
                }
            }
            return obj[props[props.length - 1]];
        },
        serializeFormWithValidate: function(formId, validateRequired, validationErrors) {
            var obj = {};
            var parentForm = "#" + formId + " ";
            var formElements = ["input:text", "input:hidden", "input:password",
                    "input:radio:checked", "select", "textarea"];

            var query = $.map(formElements, function(elem) {
                return parentForm + elem;
            }).join(",");

            // process inputs
            var list = $(query);
            list.each(function() {
                var element = $(this);
                if(validateRequired && element.attr("required") == 'true' && element.val() == ''){
                	if(!validationErrors["missing"]){
                		validationErrors["missing"]={};
                	}
                	validationErrors["missing"][element.attr("name")] = "required";
                }
                Util.setObjectPropertyValue(obj, element.attr("name"), $.trim(element.val()));
            });

            // process checkboxes
            //@todo<lumii> add support of multiple values
            var listCheck = $("#" + formId + " input:checkbox:checked");
            listCheck.each(function() {
                var element = $(this);
                Util.addObjectPropertyValue(obj, element.attr("name"), $.trim(element.val()));
            });

            return obj;
		},
		serializeForm: function(formId) {
        	return Util.serializeFormWithValidate(formId, false, {});
        },
        sortByName: function(array) {
            array.sort(function(a, b) {
                var aName = a.name.toLowerCase();
                var bName = b.name.toLowerCase();
                return aName > bName ? 1 :
                       aName == bName ? 0 : -1;
            });

            return array;
        },

        escapeHTML: function(text) {
            return text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
        },

        filterAmountInputs: function(supportNegative) {
            $(".itemamount").keypress(function(event) {
            	Util.isAmountValueEvent(event, supportNegative);
            });
        },

        filterAmountInput: function($input, supportNegative) {
            $input.keypress(function(event) {
            	Util.isAmountValueEvent(event, supportNegative);
            });
        },
        
        isAmountValueEvent: function(event, supportNegative){
	        var keyCode = event.charCode == undefined ? event.keyCode : event.charCode;
	        if (!Util.isKeyCodeFunctional(keyCode)) {
	            if (supportNegative && keyCode == 45) {
	                return $(this).val().length == 0;
	            }
	            return keyCode >= 48 && keyCode < 58;
	        }
	        return true;
        },

        isKeyCodeFunctional: function(code) {
        	if($.browser.safari){
        		return code == 8 		//backspace button
        			|| code == 63234	//left button
        			|| code == 63235	//right button
        			|| code == 63272;	//del button
        	}
        	return code == 0;
        },

        filterDecimalInputs: function() {
            $(".decimal").keypress(function(event) {
                var keyCode = event.charCode == undefined ? event.keyCode : event.charCode;
                if (keyCode) {
                    return (keyCode >= 48 && keyCode < 58) || (keyCode == 46 && $(this).val().indexOf('.') == -1);
                }
                return true;
            });
        },

        filterDecimalInput: function($input) {
            $input.keypress(function(event) {
                var keyCode = event.charCode == undefined ? event.keyCode : event.charCode;
                if (keyCode) {
                    return (keyCode >= 48 && keyCode < 58) || (keyCode == 46 && $(this).val().indexOf('.') == -1);
                }
                return true;
            });
        },

        validateAmount: function(value){
            return /^[0-9]+$/.test(value) && parseInt(value) != 0;
        },

        showErrors : function(errors, container, errorClass) {
            var $existingErrors = $("." + errorClass, container);
            var $errors;
            if ($existingErrors.length > 0) {
                $errors = $existingErrors.parent();
                $existingErrors.remove();
            } else {
                $errors = $("<div></div>").appendTo(container);
            }

            for (var i = 0; i < errors.length; i++) {
                $("<div></div>").addClass(errorClass).appendTo($errors).text(errors[i]);
            }
        },

        removeErrors : function(container, errorClass) {
            $("." + errorClass, container).remove();
        },

        reportImpression : function(imgPath) {
            if (typeof(imgPath) != 'undefined') {
				var emptyImage = new Image();
				emptyImage.src = imgPath;
				$("body").append(emptyImage);
            }

        },

       	/**
		 *  Make case sensitive string comparision.
		 *  The result order is: A -> a -> B -> b ...
		 *
		 *  @return 0 if strings are equals, -1 if str1 less than str2 and 1 otherwise.
		 **/
	    compareStr: function(str1, str2){
			var l = str1.length > str2.length ? str2.length : str1.length;
			for (var i = 0; i < l; i++) {
				var ch1 = str1.charCodeAt(i);
				var ch2 = str2.charCodeAt(i);
				if (ch1 >= 97 && ch1 <= 122) {
					ch1 -= 31.5;
				}
				if (ch2 >= 97 && ch2 <= 122) {
					ch2 -= 31.5;
				}
				if(ch1 != ch2) {
					return ch1 - ch2;
				}
			}
			return str1.length - str2.length;
        },

        isFunction : function(obj) {
            return Object().toString.call(obj) === "[object Function]";
        },

        isArray : function(obj) {
            return Object().toString.call(obj) === "[object Array]";
        },

        isRegExp : function(obj) {
            return Object().toString.call(obj) === "[object RegExp]";
        },

        openExportWindow: function(url, formId, params) {
            if (typeof formId != "undefined" && !!formId) {
                var $form = $("#" + formId);
                if (typeof url != "undefined" && !!url) {
                    if ($form.length == 0) {
                        $form = $('<form method="POST" target="_blank"></form>');
                        if (typeof params != "undefined" && !!params) {
                            for (var i in params) {
                                $form.append('<input type="hidden" name="' + i + '"/>');
                            }
                        }
                        $form.appendTo('body');
                    }

                    // refresh or set form properties
                    $form.attr("id", formId);
                    $form.attr("action", url);

                    // refresh or set inputs values
                    if (typeof params != "undefined" && !!params) {
                        for (i in params) {
                            var $item = $form.children("[name='" + i + "']");
                            if ($item.length > 0) {
                                $item.val(params[i]);
                            }
                        }
                    }
                }
                $form.submit();
            }
        },

        getPortalRelativeUrl: function() {
            var portalRelativeUrl = document.getElementById('Portal-Relative-URL');
            return portalRelativeUrl && portalRelativeUrl.content || "/";
        },

        getGenericPath: function() {
            var genericPath = document.getElementById('Generic-Path');
            return genericPath && genericPath.content || "";
        },

        Integer: {
            valueOf: function(val) {
                if (typeof val === "undefined") {
                    return 0;
                }
                var intVal = parseInt(val);
                return isNaN(intVal) ? 0 : intVal;
            }
        },

        Float: {
            valueOf: function(val) {
                if (typeof val === "undefined") {
                    return 0;
                }
                var floatVal = parseFloat(val);
                return isNaN(floatVal) ? 0 : floatVal;
            }
        },

        Currency: {
            format: function(value) {
                var num = parseFloat(value);
                if (num == 0) {
                    return "$0.00";
                }
                if (isNaN(num)) {
                    return "N/A";
                }
                var strNum = "$" + Math.round(num * 100);
                var strLength = strNum.length;
                var firstPart = strLength == 2 ? "$" : strNum.substring(0, strLength - 2);
                var lastPart = strLength == 2 ? "0" + strNum.substring(strLength - 1) : strNum.substring(strLength - 2);
                return (firstPart == "$" ? "$0" : firstPart) + "." + lastPart;
            }
        },
		
		// Serialize an array of form elements or a set of
		// key/values into a query string
		serializeObjects: function ( a) {
			var r20 = /%20/g;

			var traditional = false;
			var s = [], add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction(value) ? value() : value;
				s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
			};
			
			// Set traditional to true for jQuery <= 1.3.2 behavior.
			if ( traditional === undefined ) {
				traditional = jQuery.ajaxSettings.traditional;
			}
			
			// If an array was passed in, assume that it is an array of form elements.
			if ( jQuery.isArray(a) || a.jquery ) {
				// Serialize the form elements
				jQuery.each( a, function() {
					add( this.name, this.value );
				});
				
			} else {
				// If traditional, encode the "old" way (the way 1.3.2 or older
				// did it), otherwise encode params recursively.
				for ( var prefix in a ) {
					Util.serializeParamsInner( prefix, a[prefix], traditional, add );
				}
			}

			// Return the resulting serialization
			return s.join("&").replace(r20, "+");
		},

		serializeParamsInner: function ( prefix, obj, traditional, add ) {
			var	rbracket = /\[\]$/;
			if ( jQuery.isArray(obj) && obj.length ) {
				// Serialize array item.
				jQuery.each( obj, function( i, v ) {
					if ( traditional || rbracket.test( prefix ) ) {
						// Treat each array item as a scalar.
						add( prefix, v );

					} else {
						// If array item is non-scalar (array or object), encode its
						// numeric index to resolve deserialization ambiguity issues.
						// Note that rack (as of 1.0.0) can't currently deserialize
						// nested arrays properly, and attempting to do so may cause
						// a server error. Possible fixes are to modify rack's
						// deserialization algorithm or to provide an option or flag
						// to force array serialization to be shallow.
						Util.serializeParamsInner( prefix + ( typeof v === "object" || jQuery.isArray(v) ? ("." + i) : "" ), v, traditional, add );
					}
				});
					
			} else if ( !traditional && obj != null && typeof obj === "object" ) {
				if ( jQuery.isEmptyObject( obj ) ) {
					add( prefix, "" );

				// Serialize object item.
				} else {
					jQuery.each( obj, function( k, v ) {
						if(isNaN(k)){
							Util.serializeParamsInner( prefix + "." + k, v, traditional, add );
						}else{
							Util.serializeParamsInner( prefix + "[" + k + "]", v, traditional, add );
						}
					});
				}
							
			} else {
				// Serialize scalar item.
				add( prefix, obj );
			}
		},
		// Serialize an array of form elements or a set of
		// key/values into a query string
		serializeObjectsToArray: function ( a) {
			var traditional = false;
			var s = [], add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction(value) ? value() : value;
				s[ s.length ] = { 'key': key , 'value': value};
			};
			
			// Set traditional to true for jQuery <= 1.3.2 behavior.
			if ( traditional === undefined ) {
				traditional = jQuery.ajaxSettings.traditional;
			}
			
			// If an array was passed in, assume that it is an array of form elements.
			if ( jQuery.isArray(a) || a.jquery ) {
				// Serialize the form elements
				jQuery.each( a, function() {
					add( this.name, this.value );
				});
				
			} else {
				// If traditional, encode the "old" way (the way 1.3.2 or older
				// did it), otherwise encode params recursively.
				for ( var prefix in a ) {
					Util.serializeParamsInnerToArray( prefix, a[prefix], traditional, add );
				}
			}

			// Return the resulting serialization
			return s;
		},
		serializeParamsInnerToArray: function ( prefix, obj, traditional, add ) {
			var	rbracket = /\[\]$/;
			if ( jQuery.isArray(obj) && obj.length ) {
				// Serialize array item.
				jQuery.each( obj, function( i, v ) {
					if ( traditional || rbracket.test( prefix ) ) {
						// Treat each array item as a scalar.
						add( prefix, v );

					} else {
						// If array item is non-scalar (array or object), encode its
						// numeric index to resolve deserialization ambiguity issues.
						// Note that rack (as of 1.0.0) can't currently deserialize
						// nested arrays properly, and attempting to do so may cause
						// a server error. Possible fixes are to modify rack's
						// deserialization algorithm or to provide an option or flag
						// to force array serialization to be shallow.
						Util.serializeParamsInnerToArray( prefix + ( typeof v === "object" || jQuery.isArray(v) ? ("." + i) : "" ), v, traditional, add );
					}
				});
					
			} else if ( !traditional && obj != null && typeof obj === "object" ) {
				if ( jQuery.isEmptyObject( obj ) ) {
					add( prefix, "" );

				// Serialize object item.
				} else {
					jQuery.each( obj, function( k, v ) {
						Util.serializeParamsInnerToArray( prefix + "." + k, v, traditional, add );
					});
				}
							
			} else {
				// Serialize scalar item.
				add( prefix, obj );
			}
		},
		cleanForm: function (formName){
			var formFields = "#" + formName + " select,input:not(:checkbox,:radio)";
			var list = $(formFields);
			list.val("");
			formFields = "#" + formName + " input[type='checkbox',type='radio']";
			list = $(formFields);
			list.removeAttr("checked");
		},
		fillForm: function (formId, values){
			for ( var param in values ) {
				var val = values[param].value;
				var key = values[param].key;
				var editor = $(formId+' [name="'+key+'"]');
				if(editor.length > 0){
					editor = editor[0];
					if(!val){
						val = '';
					}
					if($(editor).is("select,input:not(:checkbox,:radio)")) {
						$(editor).val(val);
						continue;
					}
					if($(editor).is("div,span")){
						$(editor).html(val);
					}
					if($(editor).is("input")){
						if(editor.type.toLowerCase() == 'password'){ 
							$(editor).val('');
						}
						if($(editor).is("[type='checkbox']")){
							if(val == "checked"){
								$(editor).attr('checked', 'checked');
							}else{
								$(editor).removeAttr('checked');
							}
						}
					}
				}
			}
		},
		serializeFormToWithValidate: function(formId, obj, validateRequired, validationErrors) {
			if(!obj){
				obj = {};
			}
            var parentForm = "#" + formId + " ";
            var formElements = ["input:text", "input:hidden", "input:password",
                    "input:radio:checked", "select", "textarea"];

            var query = $.map(formElements, function(elem) {
                return parentForm + elem;
            }).join(",");

            // process inputs
            var list = $(query);
            list.each(function() {
                var element = $(this);
                if(validateRequired && element.attr("required") == 'true' && element.val() == ''){
                	if(!validationErrors["missing"]){
                		validationErrors["missing"]={};
                	}
                	validationErrors["missing"][element.attr("name")] = "required";
                }
				Util.setObjectPropertyValueAdv(obj, element.attr("name"), $.trim(element.val()), element.attr("convert"));
            });

            // process checkboxes
            //@todo<lumii> add support of multiple values
            var listCheck = $("#" + formId + " input:checkbox:checked");
            listCheck.each(function() {
                var element = $(this);
                Util.addObjectPropertyValueAdv(obj, element.attr("name"), $.trim(element.val()), element.attr("convert"));
            });

            return obj;
		},
        serializeFormTo: function(formId, obj) {
			return Util.serializeFormToWithValidate(formId, obj, false, {});
		},
		setObjectPropertyValueAdv: function(object, propName, propValue, propType) {
            if (propName) {
                propName = propName.replace(/\[([^\]]+?)\]/g, ".$1");
                var props = propName.split('.');
                var obj = object;
                for (var i = 0; i < props.length - 1; i++) {
                    var prop = obj[props[i]];
                    if (!prop) {
                        prop = {};
                        obj[props[i]] = prop;
                    }
                    obj = prop;
                }
				var original = obj[props[props.length - 1]];
				if(propType){
					if(propType=='int'){
						if(isFinite(propValue) && propValue != ""){
							propValue = parseInt(propValue);
						}else{
							return;
}
					}
					if(propType=='float' ){
						if(isFinite(propValue) && propValue != ""){
							propValue = parseFloat(propValue);
						}else{
							return;
						}
					}
					if(propType=='nullstring'){
						if(propValue.length == 0){
							propValue = '';
						}
					}
					if(propType=='string'){
						if(!propValue || propValue.length == 0){
							propValue = '';
						}
					}
				}
				
                obj[props[props.length - 1]] = propValue;
            }
            return object;
        },

        addObjectPropertyValueAdv: function(object, propName, propValue, propType) {
			// adds property value as array - if already exists
            if (propName) {
                propName = propName.replace(/\[([^\]]+?)\]/g, ".$1");
                var props = propName.split('.');
                var obj = object;
                for (var i = 0; i < props.length - 1; i++) {
                    var prop = obj[props[i]];
                    if (!prop) {
                        prop = {};
                        obj[props[i]] = prop;
                    }
                    obj = prop;
                }
				//var original = obj[props[props.length - 1]];
				if(propType){
					if(propType=='int'){
						if(isFinite(propValue) && propValue != ""){
							propValue = parseInt(propValue);
						}else{
							return;
						}
					}
					if(propType=='float'){
						if(isFinite(propValue) && propValue != ""){
							propValue = parseFloat(propValue);
						}else{
							return;
						}
					}
					if(propType=='nullstring'){
						if(propValue.length == 0){
							propValue = null;
						}
					}
					if(propType=='string'){
						if(!propValue || propValue.length == 0){
							propValue = '';
						}
					}
				}
				
				if(!obj[props[props.length - 1]]){
				    obj[props[props.length - 1]] = propValue;
				}else{
					if(Util.isArray(obj[props[props.length - 1]])){
						obj[props[props.length - 1]][ obj[props[props.length - 1]].length ] = propValue;
					}else{
						var tmp = obj[props[props.length - 1]];
						obj[props[props.length - 1]] = [tmp, propValue];
					}
				}
            }
            return object;
        },

        setButtonValue: function($button, value) {
           var oldValue = $.trim($button.text());
           var newValue = $button.html().replace(oldValue, value);
           $button.html(newValue);
        },

        getCorrectId: function(id) {
            return id.replace(/[\.\[\]]/ig, "_");
        }
    };
}

if (typeof Validator == "undefined") {
    var Validator = {
        errElementName : "span",
        listeners: [],

        validateRequiredFields : function(container, error, hideOldErrors) {
            var ok = true;
           	var firstFieldError = null;

            $(".required", container).each(function(index) {
                var element = $(this);
                var name = element.attr("name");
                var value;

	            if (index == 0) {
	            	firstFieldError = this.name;
	            }

				if (element.is(":radio")) {
                    value = $(":radio:checked[name='" + name + "']").length > 0 ? "checked" : "";
				} else if (element.is("input") || element.is("select")) {
                    value = element.val();
                } else {
                    value = element.text();
                }

                if ($.trim(value).length == 0) {
                    Validator.addFieldError(name, error, container, null, hideOldErrors);
                    ok = false;
                } else {
                    if (hideOldErrors) {
                        Validator.removeFieldError(name, container);
                    }
                }
            });

			if (!ok) {
		        Validator.focusOnElement(firstFieldError, container);
		    }

            return ok;
        },
        setFieldErrors : function(errors, globalErrorsFieldId, container, doNotFocus) {
           	var firstFieldError = null;
            $.each(errors, function(index) {
                if (this.fieldName) {
                    Validator.addFieldError(this.fieldName, this.error, container, globalErrorsFieldId);
                } else {
                    if (globalErrorsFieldId) {
                        Validator.addFieldError(globalErrorsFieldId, this.error, container, globalErrorsFieldId);
                    }
                }
	            if (index == 0) {
	            	firstFieldError = this.fieldName;
	            }
            });
            if(!doNotFocus){
				Validator.focusOnElement(firstFieldError, container);
            	Validator.runListeners();
            }
        },

        addFieldError : function(fieldName, error, parent, globalErrorsFieldId, hidePrevErrors) {
	        var errorFieldId = "";
            if (fieldName && fieldName != globalErrorsFieldId) {
            	errorFieldId = Validator.getErrorFieldId(fieldName);
            } else {
            	errorFieldId = globalErrorsFieldId;
            }
            var errorFields = $("#" + Validator.escapeFieldName(errorFieldId), parent);
            var errorField;
            var escapedFieldId = Validator.escapeFieldName(errorFieldId);
            if (errorFields.length == 0) {
                var elem = $("[name='" + fieldName + "'], #" + Util.getCorrectId(fieldName), parent);
	            if (elem.length > 0){
	                errorField = $("<" + Validator.errElementName + " class='error' id='" + errorFieldId + "'></" +
                                   Validator.errElementName + ">")
	                        .insertAfter(elem.get(elem.length - 1));
	            } else if (globalErrorsFieldId && fieldName != globalErrorsFieldId) {
	            	Validator.addFieldError(globalErrorsFieldId, error, parent, globalErrorsFieldId, hidePrevErrors);
	            } else {
                    if ($.isFunction(popupAlert)) {
                        popupAlert("Error: " + error);
                    } else {
                        alert("Error: " + error);
                    }
					return;
	            }
            } else if (errorFields.length == 1) {
                errorField = errorFields.eq(0);
	            errorField.addClass("error");
            } else {
                alert("More than 1 error fields for field with name " + fieldName);
				return;
            }

			if (errorField) {
				var prevMessage = errorField.text();
	            errorField.text(!hidePrevErrors && jQuery.trim(prevMessage).length > 0 ? prevMessage + "; " + error: error).show();
	        }
        },

        removeAllErrors: function (formName){
			var form = $("#" + formName);
			var list = $(":input", form);
			list.each(function(ind, el){
				var fieldId = $(el).attr("id");
				Validator.removeFieldError(fieldId, form[0]);	
			});
			list = $(".error:visible", form).html("").hide();
		},

        removeErrors : function(fieldNames, parent) {
        	for(var i = 0; i < fieldNames.length; i++){
        		Validator.removeFieldError(fieldNames[i], parent);
        	}
		},
		
        removeFieldError : function(fieldName, parent) {
            var errorFieldId = Validator.getErrorFieldId(fieldName);
            $("#" + Validator.escapeFieldName(errorFieldId), parent).text("").hide();
        },

        getErrorFieldId : function(fieldName) {
            return fieldName + "_err";
        },

        escapeFieldName : function(fieldName) {
            return fieldName.replace(/\./g, "\\.").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
        },

        focusOnElement: function(elementName, container) {
        	if ($.trim(elementName).length > 0 && $("[name='" + elementName + "']", container).length > 0) {
            	$("[name='" + elementName + "']", container).eq(0).focus();
            }
        },

        registerListener: function(func, isOnce) {
            if ($.isFunction(func)) {
                Validator.listeners.push({func: func, once: isOnce});
            }
        },

        runListeners: function() {
            for (var i = 0; i < Validator.listeners.length; i++) {
                var action = Validator.listeners[i];
                if (action.once && !action.done) {
                    action.func();
                    action.done = true;
                    Validator.listeners[i] = action;
                }
            }
        }
    };
}

if (typeof ItemsNavigator == "undefined") {
    var ItemsNavigator = {
        $currentItems : {},
		rotateInfo: {},		
		$impressionUrls: "",
		

        showCurrentItem : function(itemType, itemsListId, index) {
            if (ItemsNavigator.$currentItems[itemType] != null) {
                ItemsNavigator.$currentItems[itemType].hide();
            }
            ItemsNavigator.$currentItems[itemType] = $("#" + itemsListId + " div.item:eq(" + index + ")").show();
            if (typeof $impressionUrls != 'undefined') {
                Util.reportImpression(eval($impressionUrls+"[index]"));
            }

        },

        createNavigation : function(itemsListId, navigatioPanelId, itemType, rotatePeriodInSeconds, impressionUrls) {
            var $navigationPanel = $("#" + navigatioPanelId);            
            $impressionUrls = impressionUrls;
            ItemsNavigator.rotateInfo[itemType] = new ItemsNavigator.rotateData(null, []);
            $("#" + itemsListId + " div.item").hide().each(function(index) {
                var $link = $("<a href='#'></a>").text(index + 1).attr("index", index + 1)
                    .click(function() {
                        var $this = $(this);
                        ItemsNavigator.showItem($this, itemType, itemsListId, $navigationPanel);
                        if (ItemsNavigator.rotateInfo[itemType] && ItemsNavigator.rotateInfo[itemType].rotateFunction) {
                        	 window.clearTimeout(ItemsNavigator.rotateInfo[itemType].rotateFunction);
                        }
                        return false;
                    }).appendTo($navigationPanel);
                if (index == 0) {
                    $link.addClass("activeElement");
                }
                ItemsNavigator.rotateInfo[itemType].links[index] = $link;
            });
            if ($("#" + itemsListId).is(":hidden")) {
            	$("#" + itemsListId).show();
            }

            if (rotatePeriodInSeconds && rotatePeriodInSeconds > 0 && ItemsNavigator.rotateInfo[itemType].links.length > 1) {
            	ItemsNavigator.rotate(itemType, itemsListId, $navigationPanel, rotatePeriodInSeconds * 1000, 0);
            } else {
	            ItemsNavigator.showCurrentItem(itemType, itemsListId, 0);
	        }
        },

        showItem: function (link, itemType, itemsListId, navigationPanel) {
	        ItemsNavigator.showCurrentItem(itemType, itemsListId, link.attr("index") - 1);
	        $("a.activeElement", navigationPanel).removeClass("activeElement");
	        link.addClass("activeElement");
        },

        rotate: function (itemType, itemsListId, navigationPanel, period, index) {
        	ItemsNavigator.showItem(ItemsNavigator.rotateInfo[itemType].links[index], itemType, itemsListId, navigationPanel);
        	var nextIndex = index + 1 < ItemsNavigator.rotateInfo[itemType].links.length ? index + 1 : 0;
        	ItemsNavigator.rotateInfo[itemType].rotateFunction = setTimeout(function(){ItemsNavigator.rotate(itemType, itemsListId, navigationPanel, period, nextIndex);}, period);
        },

        rotateData: function(rotateFunctionP, linksP){
        	this.rotateFunction = rotateFunctionP;
        	this.links = linksP;
        }
    };
}
(function(){
    if (!window.LongWordsProcessor) {
        window.LongWordsProcessor = function(){
            var WORD_SPLITTER = ' ';
            var MAX_LENGTH = 20;

            function wordBreak(str, length, holdMarkup) {
                var maxLength = 20;
                if (str == null) {
                    return str;
                }
                maxLength = length || MAX_LENGTH;
                if (str.length > maxLength) {
                    var words = str.split(WORD_SPLITTER);
                    var newString = '';
                    var fixesMade = false;
                    words.forEach(function(el) {
                        if (el.length > maxLength) {
                            var subWords = '';
                            for (var i = 0; i < el.length / maxLength; i++) {
                                subWords += el.substring(i * maxLength, (i + 1) * maxLength) + WORD_SPLITTER;
                            }
                            el = subWords;
                            fixesMade = true;
                        }
                        newString += el + WORD_SPLITTER;
                    });
                    if(fixesMade){
                        return newString;
                    }
                }
                if(holdMarkup){
                    return holdMarkup;
                }
                return str;
            }

            function cutToNChars(str, n) {
                if (!str || str.length < n) {
                    return str;
                }
                return str.substring(0, n) + "...";
            }

            return {
                wordBreak: wordBreak,
                cutToNChars: cutToNChars
            };
        }();
    }
})();

function getMaxZIndex(selector) {
    var zindex = 0;
    $(selector).each(function(){
        var cssZIndex = $(this).css("z-index");
        var currZIndex = isNaN(cssZIndex) ? 0 : Number(cssZIndex);
        zindex = Math.max(currZIndex, zindex);
    });
    return zindex;
}

window.popupZ = 1;
/**
 * shows top window popup with message
 * @param message text message to show
 * @param params params map (defaults in []):
 * <ul>
 * <li>bgcolor - color of background [#ffff66]</li>
 * <li>color - color of text [#ff0000]</li>
 * <li>autohide - should message autohide or not [true]</li>
 * <li>timeout - time to show message in ms, if "auto" it will calculate automatically: MessageLength * 100 ms ["auto"]</li>
 * <li>parent - parent jquery element ["body"]</li>
 * <li>position - selector of parent element ["absolute"] for ie or ["fixed"] for other browsers</li>
 * <li>width - width of container of message window ["100%"]</li>
 * <li>inwidth - width of internal message window ["100%"]</li>
 * <li>close - callback on close [null]</li>
 * <li>messagepadding - padding in message text container ["10px"]</li>
 * </ul>
 */
function popupAlert(message, params) {
    var p, $alert, time, t;

    function dismissMessage() {
        $alert.fadeOut("fast", function() {
            $alert.remove();
            setBorderRadiusAndTop();
            if ($.isFunction(p.close)) {
                p.close();
            }
        });
    }

    function setBorderRadiusAndTop() {
        $alerts = $(".popup-alert");
        var top = 0;
        $alerts.each(function(i) {
            var $currAlert = $(this);
            $currAlert.css({
                top: top + "px"
            });
            top += $currAlert.height();
            var holder = $currAlert.find(".message-holder");
            if (i == ($alerts.length - 1)) {
                holder.addClass("message-border-radius-bottom");
            } else {
                holder.removeClass("message-border-radius-bottom");
            }
        });
    }

    if (typeof params == "undefined") {
        params = {};
    }
    p = {
        bgcolor: "#ffff66",
        color: "#ff0000",
        autohide: true,
        timeout: "auto",
        parent: $("body"),
        position: $.browser.msie && parseInt($.browser.version) < 7 ? "absolute" : "fixed",
        width: "100%",
        inwidth: "40%",
        close: null,
        messagepadding: "5px",
        opacity: "1",
        additionalClass: ""
    };
    p = $.extend(p, params);
    $alert = $('<div class="popup-alert" style="display:none;position:' + p.position + ';width:' + p.width + ';z-index:' + (getMaxZIndex("*") + popupZ++) + ';text-align:center;">' +
               '<div class="message-holder ' + p.additionalClass + '" style="background:' + p.bgcolor + ';color:' + p.color + ';font:bold;margin:auto;font-size: 11pt;width:' + p.inwidth + '">' +
               '<div class="border-holder" style="padding:' + p.messagepadding + ';">' + message + '</div>' +
               '</div>' +
               '</div>').css({
        opacity: p.opacity
    });
    if ($.isFunction(p.close)) {
        var $popupActionRow = $('<div class="popup-action-row" style="width:100%;text-align:right;">' +
                                    '<div style="padding: 0 10px 5px;">' +
                                        '<a class="close" onclick="return false;" href=".">close x<a>' +
                                    '</div>' +
                                '<div>');
        $alert.click(function() {
            clearTimeout(t);
            dismissMessage();
        }).find(".message-holder")
                .append($popupActionRow)
                .find(".close").click(function() {
            clearTimeout(t);
            dismissMessage();
        });
    }
    time = (p.timeout == "auto") ? message.length * 100 : p.timeout; //one second for every 10 characters
    var $alerts = $(".popup-alert");
    if ($alerts.length > 0) {
        $alert.insertAfter($(".popup-alert:last"));
    } else {
        $alert.prependTo(p.parent);
    }
    setBorderRadiusAndTop();
    $alert.fadeIn(1000, function() {
        if (p.autohide) {
            try {
                t = setTimeout(dismissMessage, time);
            } catch(ex) {
                t = null;
            }
        }
    });

    return {
        hide: dismissMessage,
        rectangle: {
            h: $alert.height(),
            w: $alert.width()
        }
    };
}

function renderImage(id, src) {
    var $image = $("#" + id);
    var img = new Image();
    var $tempImg = $(img);
    $tempImg.load(function() {
        if (!$.support.style) {
            var $imageContainer = $image.parent();
            var containerInnerWidth = $imageContainer.innerWidth();
            var containerInnerHeight = $imageContainer.innerHeight();
            if (containerInnerWidth < this.width || containerInnerHeight < this.height) {
                if (this.width > this.height) {
                    $image.css({
                        width: containerInnerWidth + "px"
                    });
                } else {
                    $image.css({
                        height: containerInnerHeight + "px"
                    });
                }

            }
        }
        $image.attr("src", img.src);
    });
    img.src = src;
}

//Arrays extentions
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(elt /*, from*/) {
        var len = this.length;

        var from = Number(arguments[1]) || 0;
        from = (from < 0)
                ? Math.ceil(from)
                : Math.floor(from);
        if (from < 0)
            from += len;

        for (; from < len; from++) {
            if (from in this &&
                this[from] === elt)
                return from;
        }
        return -1;
    };
}

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function(fun /*, thisp*/) {
        var len = this.length;
        if (!Util.isFunction(fun))
            throw new TypeError();

        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this)
                fun.call(thisp, this[i], i, this);
        }
    };
}

if (!Array.prototype.clone) {
    Array.prototype.clone = function() {
        var clone = new Array();
        for (var i = 0; i < this.length; i++) {
            clone[i] = this[i];
        }
        return clone;
    };
}

if (typeof Object.beget !== 'function') {
    Object.beget = function (o) {
        var F = function() {};
        F.prototype = o;
        return new F();
    };
}

/**
 * From http://stackoverflow.com/questions/1068834/object-comparison-in-javascript
 */
function equals(y, x){
	
	for(p in y)
	{
	    if(typeof(x[p])=='undefined') {return false;}
	}
	
	for(p in y)
	{
	    if (y[p])
	    {
	        switch(typeof(y[p]))
	        {
	                case 'object':
	                        if (!y[p].equals(x[p])) { return false }; break;
	                case 'function':
	                        if (typeof(x[p])=='undefined' || (p != 'equals' && y[p].toString() != x[p].toString())) { return false; }; break;
	                default:
	                        if (y[p] != x[p]) { return false; }
	        }
	    }
	    else
	    {
	        if (x[p])
	        {
	            return false;
	        }
	    }
	}
	
	for(p in x)
	{
	    if(typeof(y[p])=='undefined') {return false;}
	}
	
	return true;
}

var timer = new Date();
function logTimestamp(start) {
    if (start) {
        timer = new Date();
    }
    var updatedTimer = new Date();
    var diff = updatedTimer.getTime() - timer.getTime();
    timer = updatedTimer;
    return diff;
}

function isEmail(s) {
    return /^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$/.test(s);
}

if (!window.UrlUtil && window.URLService) {
    window.UrlUtil = function() {
        var tiniurls = {};

        function tinify(url, callbacks) {
            callbacks.success = callbacks.success || function() {};
            callbacks.error = callbacks.error || function() {};
            callbacks.complete = callbacks.complete || function() {};
            if (tiniurls[url]) {
                callbacks.success(tiniurls[url]);
                callbacks.complete();
                return;
            }
            URLService.tinify(url, {
                callback: function(data) {
                    tiniurls[url] = data;
                    callbacks.success(data);
                    callbacks.complete();
                },
                timeout: 1000,
                errorHandler: function(e) {
                    callbacks.error(e);
                    callbacks.complete();
                }
            });
        }

        return {
            tinify: tinify
        }
    }();
}

if (!window.CSRFUtil) {
    window.CSRFUtil = function() {
        var hashCodeParamName = "formHashCode";

        function replaceHashCode($form) {
            if(typeof window.CSRFService !== "undefined") {
                CSRFService.getAvailableCodes(1, {callback: function(availableCodes) {
                    if(availableCodes.length > 0) {
                        $form.find("input[name='" + hashCodeParamName + "']").val(availableCodes.pop());
                    }
                }});
            }
        }

        function getHashCodes(hashCodeCount) {
            var hashCode = "";
            hashCodeCount = hashCodeCount || null;
            if(typeof window.CSRFService !== "undefined") {
                CSRFService.getAvailableCodes(hashCodeCount, {callback: function(availableCodes) {
                    if(availableCodes.length > 0) {
                        hashCode = availableCodes.pop();
                    }
                }, async: false});
            }
            return hashCode;
        }

        function appendHashCode() {
            return hashCodeParamName + "=" + getHashCodes(1);
        }

        return {
            HashCodeParam: hashCodeParamName,
            replaceHashCode: replaceHashCode,
            getHashCodes: getHashCodes,
            appendHashCode: appendHashCode
        }
    }();
}

