// =========================================================================================================
// ========================    ZMIENNE GLOBALNE    =========================================================
// =========================================================================================================

var $DEBUG_MODE = false,			// tryb debugowania - pokazuje alerty wyjatkow
	$BREAK    	= {},
	$CONTINUE 	= {},
	$TEMP 		= {};


// =========================================================================================================
// ========================    WYKRYWANIE PRZEGLADARKI ITP.    =============================================
// =========================================================================================================

var browser		= navigator.userAgent.toLowerCase(),
	version 	= (browser.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
	isOpera 	= (window.opera || browser.indexOf('opera') > -1),
	isIE 		= (browser.indexOf('msie') > -1 && !isOpera),
	isIE5 		= ((browser.indexOf('msie 5') > -1) && !isOpera),
	isIE55 		= (/msie 5\.[56789]/i.test(navigator.userAgent) && !isOpera),
	isIE7 		= (browser.indexOf('msie 7') > -1),
	isMac 		= (browser.indexOf('mac') > -1),
	isGecko		= (browser.indexOf('gecko') > -1),
	isSafari 	= (browser.indexOf('safari') > -1 || browser.indexOf('webkit') > -1),
	isMozilla	= (browser.indexOf('mozilla') > -1 && !/(compatible|webkit)/.test(browser)),
    isFirefox2  = (browser.indexOf('firefox/2') > -1);

function browserVer (str, prefix) {
	var i = str.indexOf (prefix);
	if (i != -1) {
		var ver = parseFloat(str.substring(i + prefix.length));
		if (!isNaN(ver)) { return ver; }
	}
	return null;
}

function browserSupported () {
	return ((isGecko && (
			((v=browserVer(browser, "firefox/")) >= 1.5)
			|| ((v=browserVer(browser, "camino/")) >= 1)
		))
		|| (isSafari && (v=browserVer(browser, "safari/")) >= 1.3)
		|| (isIE && (v=browserVer(browser, "msie "))>=6)
		|| (isOpera && ((v=browserVer(browser, "opera/"))>=9 || (v=browserVer(browser, "opera "))>=9))
	? true : false);
}


// =========================================================================================================
// ========================    OBSLUGA KLAS    =============================================================
// =========================================================================================================

var Class = {
	create: function () {
		return function () { this.initialize.apply (this, arguments); }
	},

	// Rozszerzanie juz istniejacej definicji klasy
	// Jezeli metoda/wlasnosc jest przeciazana to hest do niej dodawane na poczatku "__" (czyli jest dostepna pod "__staramertoda")
	// @example:
	//		var _Test = Class.extend (_Module, {
	//			test1: function () {
	//				alert ('test 1');
	//			}
	//		});

	extend: function (obj, ext) {
		var o = this.create ();
		o.prototype = ext;
		if (obj && obj.prototype) {
			for (var key in obj.prototype) {
				o.prototype[(typeof o.prototype[key] != 'undefined' ? '__' : '')+key] = obj.prototype[key];
			}
		}
		return o;
	}
};


// =========================================================================================================
// ========================    DEBUG    ====================================================================
// =========================================================================================================

// @function exceptionAlert
// @descr
//		Wyswietla alert'a z pelnym opisem wyjatku
//		Jest inicjowana tylko w przypatku wlaczonego trubu debugowania
// @input
//		* 0: title - tytul wyjatku podawany przez uzytkownika
//		* 1: e - obiekt wyjatku

function exceptionAlert (title, e) {
	if (!$DEBUG_MODE) return;

	var text = title;
	for (var i in e) {
		text += '\r\n' + (i + ' = ' + e[i]);
	}
	alert (text);
}


// @function mydebug
// @descr
//		Wyrzucanie komunikatow do div-a
// @input
//		* msg - komunikat

function mydebug (msg) {
	if (!$DEBUG_MODE) return;

	var debug = $('myhome_debug');
	// tworzenie div-a na debug-i
	if (!debug) {
		debug = document.createElement ('div');
		debug.setAttribute ('id', 'myhome_debug');
		var menu = document.createElement ('div'),
			content = document.createElement ('div');

		// menu (zamykanie)
		menu.innerHTML = 'ZAMKNIJ';
		menu.setAttribute ('id', 'myhome_debugMenu');
		menu.onclick = function () {
			var debug = $('myhome_debug');
			setStyle (debug, {'display':'none'});
		}
		debug.appendChild (menu);

		// content (na wpisy)
		content.setAttribute ('id', 'myhome_debugContent');
		debug.appendChild (content);
		// maksymalna wysokosc
		var viewSize = myViewSize ();
		setStyle (content, {'max-height': (viewSize[1]-60)+'px'});

		if (document.body.childNodes.length) {
			document.body.insertBefore (debug, document.body.childNodes[0]);
		} else {
			document.body.appendChild (debug);
		}
	}

	setStyle (debug, {'display':'block'});
	debug.childNodes[1].innerHTML = msg + '<br>' + debug.childNodes[1].innerHTML;
}


// =========================================================================================================
// ========================    ROZSZERZANIE I POPRAWKI    ==================================================
// =========================================================================================================

// poprawka dla funcji getElementsByTagName w IE 5.5
if (isIE55) {
	document._getElementsByTagName = document.getElementsByTagName;
	document.getElementsByTagName = function ( sTagName ) {
		return (sTagName == "*" ? document.all : document._getElementsByTagName(sTagName));
	};
}

// @function Object.extend
// @input
//		* dst - obiekt docelowy
//		* src - obiekt zrodlowy
// @descr
//		dziedziczenie metod i wlasnosci z obiektu src do obiektu dst
// @output rozszerzony obiekt dst

Object.extend = function (dst, src) {
	for (var p in src)
		dst[p] = src[p];
	return dst;
}

// @function Object.extendClone
// @input
//		* src - obiekt zrodlowy
//		* ext - obiekt rozszerzajacy obiekt zrodlowy
// @descr
//		klonowanie obiektu src i rozszerzanie go o metody i wlasnosci z obiektu ext
// @output rozszerzony obiekt dst

Object.extendClone = function (src, ext) {
	var dst = {}, key;
	for (var key in src)
		dst[key] = src[key];
	for (var key in ext)
		dst[key] = ext[key];
	return dst;
}

var toExtend = {

	// @function toExtend.each
	// @descr Wywołuje iteratora dla każdego elementu, przekazujac mu element i jego indeks.
	// @input
	//		* iterator - iterator zgodny z Function(value, index)
	// @output this

	each: function (iterator) {
		var idx = 0;
		try {
			this._each (function(v) {
				try {
					iterator (v, idx++);
				} catch (e) {
					if (e != $CONTINUE) throw e;
				}
			});
		} catch (e) {
			if (e != $BREAK)
				throw e;
		}
		return this;
	},

	// @function toExtend.include
	// @descr Sprawdza czy dany element wystepuje w innym
	// @input
	//		* obj - do sprawdzenia
	// @output true - istnieje, false - nie

	include: function (obj) {
		var f = false;
	    this.each (function(v) {
	    	if (v == obj) {
	        	f = true;
	        	throw $BREAK;
	      	}
	    });
	    return f;
	}
}

// =========================================================================================================
// ========================    SZABLONY    =================================================================
// =========================================================================================================

// @function Template
// @descr Tworzenie template-ow
// @input
//		* template - szablon
//		* pattern - wzor
// @output rozszerzony obiekt dst
// @example
//		c:	var szablon = new Template ('<a href="#{href}">#{tekst}</a>');
//			alert (szablon.evaluate ({href: 'http://www.home.pl', tekst: 'HOME.pl'}));
//
//		c:	var szablon = new Template ('<a href="#{0}">#{1}</a>');
//			alert (szablon.evaluate (['http://www.home.pl', 'HOME.pl']));

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
	initialize: function (template, pattern) {
		this.template = template.toString();
		this.pattern  = pattern || Template.Pattern;
	},

	getVars: function () {
		var vars = [],
			pattern = /#\{(.*?)\}/g,
			result;
		while ((result = pattern.exec (this.template)) != null) {
			vars.push (result[1]);
		}
		return vars;
	},

	evaluate: function (object) {
		return this.template.gsub (this.pattern, function(match) {
			var before = match[1];
			if (before == '\\')
				return match[2];
			return before + (object[match[3]] || '').toString();
		});
	}
}


// =========================================================================================================
// ========================    ROZSZERZANIE PROTOTYPU ARRAY    =============================================
// =========================================================================================================

Object.extend (Array.prototype, Object.extend (toExtend, {
		_each: function (iterator) {
			for (var i=0, imax=this.length; i<imax; i++)
				iterator (this[i]);
		}
	}));


// =========================================================================================================
// ========================    ROZSZERZANIE PROTOTYPU FUNKCJI    =============================================
// =========================================================================================================

// @function Function.bind
// @descr
//		Podpinanie funkcji/obiektow do wywolywanej innych (wykorzystywane w OOP)
// @example
//	c: obj.fx.bind (obj, 1, 2, 3);

Function.prototype.bind = function () {
	var __method = this, args = $A(arguments), object = args.shift();
	return function () {
		return __method.apply (object, args.concat($A(arguments)));
	}
}


// @function Function.bindAsEventListener
// @descr
//		Podpinanie funkcji/obiektow do wywolywanej innych - werja pod eventy (wykorzystywane w OOP)
// @example
//	c: Event.observe (document.body, 'click', handler.bindAsEventListener(obj, 1, 2, 3));

Function.prototype.bindAsEventListener = function (object) {
	var __method = this, args = $A(arguments), object = args.shift();
	return function (event) {
		return __method.apply (object, [event || window.event].concat(args));
	}
}


// =========================================================================================================
// ========================    ROZSZERZANIE PROTOTYPU ARRAY - BRAKUJACE W IE 5.0    ========================
// =========================================================================================================

// @function Array.pop
// @descr
//		zdejmuje ostatni element tablicy
// @output zdejmowany element

if (!Array.prototype.pop) {
    Array.prototype.pop = function() {
        var last;
        if (this.length) {
            last = this[this.length - 1];
            this.length -= 1;
        }
        return last;
    };
}

// @function Array.push
// @descr
//		dodaje jeden lub wiecej elementow na koniec tablicy
// @output dlugosc tablicy po wstawieniu

if (!Array.prototype.push) {
    Array.prototype.push = function() {
        for (var i = 0; i < arguments.length; ++i)
            this[this.length] = arguments[i];
        return this.length;
    };
}

// @function Array.pushArray
// @descr
//		dodaje jeden lub wiecej elementow tablicowych na koniec tablicy
// @output dlugosc tablicy po wstawieniu

if (!Array.prototype.pushArray) {
    Array.prototype.pushArray = function() {
		var i, j;
        for (i=0; i<arguments.length; ++i) {
			if (!isArray(arguments[i])) {
				arguments[i] = [arguments[i]];
			}
			for (j=0; j<arguments[i].length; j++) {
				this[this.length] = arguments[i][j];
			}
		}
        return this.length;
    };
}

// @function Array.shift
// @descr
//		zdejmuje pierwszy element tablicy
// @output zdejmowany element

if (!Array.prototype.shift) {
    Array.prototype.shift = function() {
        var first;
        if (this.length) {
            first = this[0];
            for (var i = 0; i < this.length - 1; ++i)
                this[i] = this[i + 1];
            this.length -= 1;
        }
        return first;
    };
}

// @function Array.unshift
// @descr
//		dodaje jeden lub wiecej elementow na poczatek tablicy tablicy
// @output dlugosc tablicy po wstawieniu

if (!Array.prototype.unshift) {
    Array.prototype.unshift = function() {
        if (arguments.length) {
            var i, len = arguments.length;
            for (i = this.length + len - 1; i >= len; --i)
                this[i] = this[i - len];
            for (i = 0; i < len; ++i)
                this[i] = arguments[i];
        }
        return this.length;
    };
}

// @function Array.splice
// @descr
//		dodaje/usuwa elementy tablicy

if (!Array.prototype.splice) {
    Array.prototype.splice = function(index, howMany) {
        var elements = [], removed = [], i;
        for (i = 2; i < arguments.length; ++i)
            elements.push(arguments[i]);
        for (i = index; (i < index + howMany) && (i < this.length); ++i)
            removed.push(this[i]);
        for (i = index + howMany; i < this.length; ++i)
            this[i - howMany] = this[i];
        this.length -= removed.length;
        for (i = this.length + elements.length - 1; i >= index + elements.length; --i)
            this[i] = this[i - elements.length];
        for (i = 0; i < elements.length; ++i)
            this[index + i] = elements[i];
        return removed;
    };
}

// @function Array.exists
// @descr
//		sprawdza czy element istneije w tablicy
// @output bool (true || false)

Array.prototype.exists = function (el) {
	for (var i=0, imax=this.length; i<imax; i++)
		if (el == this[i])
			return true;
	return false;
};


// =========================================================================================================
// ========================    ROZSZERZANIE PROTOTYPU STRING    ============================================
// =========================================================================================================

Object.extend (String.prototype, {

	// @function String.gsub
	// @descr Replacement z mozliwoscia podpiecia funkcji na kazdym pasujacym elementcie
	// @input
	//		* pattern - wzor poszukiwan (string lub regexp)
	//		* replacement - zastepujacy - string lub... funkcja :). Jezeli bedzie funkcja, wowczas przyjmuje ona jeden parametr
	// @example
	// 		c: 'aaa bbb ccc'.gsub(' ', '_'); zwroci "aaa_bbb_ccc"
	// 		c: 'aaa bbb ccc'.gsub(/\s\w/, function(match){ return match[0].toUpperCase(); }); zwroci "aaa Bbb Ccc"
	//		c: 'To jest test'.gsub(/(o|t)(\s)/, function(match){ return match[1].toUpperCase() + '-' + match[2]; }); zwroci "TO jesT test"

	gsub: function (pattern, replacement) {
		var r = '', src = this, match;
		replacement = arguments.callee.prepareReplacement (replacement);
		while (src.length > 0) {
			if ((match = src.match(pattern))) {
				r += src.slice(0, match.index);
				r += (replacement(match) || '').toString();
				src  = src.slice(match.index + match[0].length);
			} else {
				r += src, src = '';
			}
		}
		return r;
	},

	// @function String.trim
	// @descr Usuwa biale znaki z poczatku i konca stringu

	trim: function () {
		return this.replace(/^\s+|\s+$/, '');
	},

	// @function String.truncate
	// @descr Obcinanie stringu do podanej "length" oraz dodawanie zakonczenia "truncation"
	// @input
	//		* length - dlugosc (domyslnie 30)
	//		* truncation - zakonczenie

	truncate: function (length, truncation) {
		length = length || 30;
		truncation = (truncation === undefined ? '...' : truncation);
		return (this.length > length ?
			this.slice (0, length - truncation.length) + truncation : this);
	},

	// @function String.strip
	// @descr Usuwanie bialych znakow

	strip: function() {
		return this.replace(/^\s+/, '').replace(/\s+$/, '');
	},

	// @function String.stripTags
	// @descr Usuwanie tagow

	stripTags: function() {
		return this.replace(/<\/?[^>]+>/gi, '');
	},

	// @function String.stripScripts
	// @descr Usuwanie blokow <script />

	stripScripts: function() {
		return this.replace(new RegExp('(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 'img'), '');
	},

	// @function String.toCamel
	// @descr Zwraca string zamieniony na format "kamelowy"
	// @output string
	// @example
	// c: 'z-index'.toCamel

	toCamel: function () {
	    var splitted = this.split('-');
		if (splitted.length == 1)
			return splitted[0];
		var camelized = (this.indexOf('-') == 0
				? splitted[0].charAt(0).toUpperCase() + splitted[0].substring(1)
				: splitted[0]),
			i, imax, s;
		for (i=1, imax=splitted.length; i<imax; i++) {
			s = splitted[i];
			camelized += s.charAt(0).toUpperCase() + s.substring(1);
		}
		return camelized;
	}

});

String.prototype.gsub.prepareReplacement = function (replacement) {
	if (typeof replacement == 'function')
		return replacement;
	var template = new Template(replacement);
	return function (match) { return template.evaluate(match) };
}


// =========================================================================================================
// ========================    POBIERANIE OBIEKTOW    ======================================================
// =========================================================================================================

// @function $
// @descr Cross-Browser do pobieranie elementow
// @input
//		* e - ID elementu(-ów) do pobrania
// @output
//		* obiekt(-y)
// @example
//		c: $ ('id_elementu');

function $ () {
	var elements = [],
		e, i, imax;
	for (i=0, imax=arguments.length; i<imax; i++) {
		e = arguments[i];
		if (typeof e == 'string')
			e = document.getElementById(e);
		if (imax == 1)
      		return e;
		elements.push(e);
	}
	return elements;
}


// @function $A
// @descr Przetransformowanie elementow interacyjnych na typowe array-e
// @input
//		* iterable - element do transformacji
// @output
//		* array
// @example
//		c: $A(arguments);

function $A (iterable) {
	if (!iterable) return [];

	if (iterable.toArray) {
		return iterable.toArray();
	} else {
		var r=[], i;
		for (i=0; i<iterable.length; r.push(iterable[i++]));
		return r;
	}
}

// @function $F
// @descr Pobieranie lub nadawanie wartosci dla pola formularza
// @input
//		* n - nazwa pola
//		* v - (opcja) wartosc do nadania
//		* f - (opcja) formularz odniesienia
// @output
//		* w przypadku jednego argumentu zwraca wartosc
// @example
//		c: $F ('nazwa_pola'); - zwroci wartosc pola "nazwa_pola"
//		c: $F ('nazwa_pola', 'nowa_wartosc'); - nada wartosc "nowa_wartosc" polu "nazwa_pola"

function $F (n, v, f) {
	var f = f || $('form_main');
	var field = f.elements[n];
	if (field == undefined) return false;
	// pobieranie wartosci
	if (v == undefined) {
		var ret = '';
		if (field.length) {
			for (var i=0; i<field.length; i++) {
				// checkbox || radio
				if ((field[i].type == 'checkbox' || field[i].type == 'radio')) {
					if (field[i].checked) {
						ret = field[i].value;
						break;
					}
				} else
					ret += field[i].value + ((i < imax-1) ? "\0" : '' );
			}
		}
		// pozostale
		else
			ret = field.value;
		return ret;
	}
	// nadawanie wartosci
	else {
		// select
		if (field.options) {
			for (var i=0; i<field.options.length; i++) {
				if (field.options[i].value == v) {
					field.selectedIndex = i;
					break;
				}
			}
		}
		// checkbox || radio
		else if (field.length) {
			for (var i=0; i<field.length; i++) {
				if (field[i].value == v) {
					field[i].checked = true;
					break;
				}
			}
		}
		// pozostale
		else
			field.value = v;
	}
}

// @function getElementsByClassName
// @descr Zwraca liste elementow wystepujacych na stronie, zawierajacych okreslona klase
// @input
//		* node - wezel od ktorego ma byc rozpoczete przeszukiwanie - uchwyt obiektu
//		* clName - nazwa poszukiwanej klasy
// @output tablica pasujacych elementow
// @example
// c: getElementsByClassName ($('main'), 'moja_klasa')

function getElementsByClassName (node, clName) {
	try {
	    var classElements = [];
	    var reg = new RegExp('(^| )'+clName+'( |$)');
	    var nodeElements = node.getElementsByTagName("*");
	    for (var i=0; i<nodeElements.length; i++)
	        if (reg.test(nodeElements[i].className))
				classElements.push(nodeElements[i]);
	    return classElements;
    }
    catch (e) {
    	exceptionAlert ('Exception in getElementsByClassName function.', e);
		return false;
    }
}

// @function hasClassName
// @descr Czy elementowi zostala nadana wymieniona klasa
// @input
//		* node - wezel na ktorym bedzie dokonywane sprawdzanie
//		* className - nazwa poszukiwanej klasy
// @output bool
// @example
// c: hasClassName (this, 'jakas_klasa')

function hasClassName (node, className) {
	if (!(node = $(node))) return;
	var cn = node.className; 
	return (cn.length && (cn == className || cn.match (new RegExp("(^|\\s)" + className + "(\\s|$)"))));
}

// @function addClassName
// @descr Dodawanie klasy
// @input
//		* node - wezel na ktorym bedzie przeprowadzana operacja
//		* className - nazwa klasy
// @output bool
// @example
// c: addClassName (this, 'jakas_klasa')

function addClassName (node, className) {
	if (!(node = $(node)) || hasClassName(node, className)) return;
	node.className += (node.className ? ' ' : '') + className;
}

// @function removeClassName
// @descr Usuwanie klasy
// @input
//		* node - wezel na ktorym bedzie przeprowadzana operacja
//		* className - nazwa klasy
// @output bool
// @example
// c: removeClassName (this, 'jakas_klasa')

function removeClassName (node, className) {
	if (!(node = $(node))) return;
	node.className = node.className.replace (new RegExp("(^|\\s+)"+className+"(\\s+|$)"), ' ');
}

// @function toggleClassName
// @descr Naprzemienne usuwanie/dodawanie klasy
// @input
//		* node - wezel na ktorym bedzie przeprowadzana operacja
//		* className - nazwa klasy
// @output bool
// @example
// c: toggleClassName (this, 'jakas_klasa')

function toggleClassName (node, className) {
	if (!(node = $(node))) return;
	if (hasClassName(node, className)) {
		removeClassName (node, className);
	} else {
		addClassName (node, className);
	}
}

// =========================================================================================================
// ========================    EVENTY    ===================================================================
// =========================================================================================================

var Event = {
	observers: [],
	observersById: {},

	element: function (event) {
		return event.target || event.srcElement;
	},

    stop: function (event) {
        this.stopPropagation (event);
        this.preventDefault (event);
    },

    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    },

    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },

	observers: false,

	_observeAndCache: function (element, name, observer, useCapture, eventId) {
		if (!this.observers)
			this.observers = [];
		var save = false;

		if (element.addEventListener) {
			element.addEventListener(name, observer, useCapture);
			save = true;
		} else if (element.attachEvent) {
			element.attachEvent ('on' + name, observer);
			save = true;
		}

		if (save) {
			if (eventId)
				this.observersById[eventId] = [element, name, observer, useCapture];
			else
				this.observers.push ([element, name, observer, useCapture]);
		}
	},

	unloadById: function (ids) {
		if (!isArray(ids))
			ids = [ids];
		for (var i=0, imax=ids.length; i<imax; i++) {
			Event.stopObserving.apply (this, Event.observersById[ids[i]]);
			Event.observersById[ids[i]] = null;
		}
	},

	unloadCache: function () {
		if (Event.observers) {
			for (var i=0, imax=Event.observers.length; i<imax; i++) {
				Event.stopObserving.apply (this, Event.observers[i]);
				Event.observers[i][0] = null;
			}
			Event.observers = false;
		}

		if (Event.observersById) {
			for (var key in this.observersById) {
				Event.stopObserving.apply (this, Event.observersById[key]);
				Event.observers[key] = null;
			}
			Event.observersById = false;
		}
	},

	observe: function (e, name, observer, useCapture, eventId) {
		if (typeof e == 'string' && !(e=$(e))) return false;
		useCapture = useCapture || false;
		// onkeypress repeats arrow keys in Mozilla/Opera
		// onkeydown repeats arrow keys in IE/Safari
        //TODO: sprawdzic dla chrome
		if (name == 'keypress' && (isSafari || isIE))
			name = 'keydown';
		Event._observeAndCache (e, name, observer, useCapture, eventId);
	},

	stopObserving: function (e, name, observer, useCapture) {
		if (!(e = $(e))) return false;
		useCapture = useCapture || false;

		if (name == 'keypress' && (isSafari || isIE))
			name = 'keydown';

		if (e.removeEventListener) {
			e.removeEventListener (name, observer, useCapture);
		} else if (e.detachEvent) {
			try {
				e.detachEvent ('on' + name, observer);
			} catch (e) {}
		}
	}
};


// =========================================================================================================
// ========================    MY-owskie    ================================================================
// =========================================================================================================

// @function isNumber
// @descr Sprawdza czy wszystkie argumenty sa liczbami
// @input
//		* 0: - argumenty do sprawdzenia
// @output true gdy wszystkie argumenty sa liczbami, w przeciwnym wypadku false
// @example
// c: isNumber (e.style.top)

function isNumber () {
	for (var i=0, imax=arguments.length; i<imax; ++i)
		if (isNaN(arguments[i]) || typeof arguments[i] !='number')
			return false;
	return true;
}

// @function isArray
// @descr Sprawdza czy argument jest tablica (Array lub HTMLColectionObject)
// @input
//		* 0: - element do sprawdzenia
// @output true gdy jest tablica
// @example
// c: isArray (e)

function isArray (e) {
	return (e && (e.pop || e.item) ? true : false);
}

// @function isObject
// @descr Sprawdza czy argument jest obiektem (nie dziala na HTMLColectionObject)
// @input
//		* 0: - element do sprawdzenia
// @output true gdy jest obiekt
// @example
// c: isObject (e)

function isObject (e) {
	return (e && (typeof e == 'object') && !e.length ? true : false);
}

// @function myDisplay
// @descr pokazuje / ukrywa obiekty
// @input
//		* e - ID elementu lub element w formie obiektu
//		* show - [opt] flaga czy pokazac (1) czy ukryc (0), jezeli nie ma podanego parametru to obiekt bedzie na zmiane pokazywany/ukrywany
//		* noBlock = [opt] flaga czy ma nie stosowac wartosci 'block' do pokazywania
// @output brak
// @example
// c: myDisplay (element, 1)

function myDisplay (e, show, noBlock) {
	try {
	    if (typeof e == 'string') e = $(e);
		show = (show == undefined ? (getStyle (e, 'display') == 'none' ? 1 : 0) : show);
		setStyle (e, {'display' : (show ? (noBlock ? '' : 'block') : 'none')});
		return (show);
    }
    catch (e) {
    	exceptionAlert ('Exception in myDisplay function.', e);
    }
}

// @function isDisplayed
// @descr czy obiekt jest wyswietlany
// @input
//		* e - ID elementu lub element w formie obiektu
// @output brak
// @example
// c: isDisplayed (element)

function isDisplayed (e) {
	try {
	    if (typeof e == 'string') e = $(e);
		return (!e || getStyle (e, 'display') == 'none' ? false : true);
    }
    catch (e) {
    	exceptionAlert ('Exception in isDisplayed function.', e);
    }
}

// @function getStyle
// @descr Zwraca wartosc podanego styla (opcja dla getComputedStyle i currentStyle)
// @input
//		* e - element (obiekt lub nazwa)
//		* style - nazwa wlasnosci css
//		* int - [opt] flaga czy zwrocic wartosc w formie inta
// @output string lub przy nadaniu bInt=true integer podanej wlasnosci
// @example
// c: getStyle (element, 'padding-top', 1)

function getStyle (e, style, bInt) {
	try {
	    if (typeof e == 'string') e = $(e);
		var dv = document.defaultView,
	    	camelizedStyle = (style == 'float'
				? (typeof e.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat')
				: style
			).toCamel(),
	    	v = e.style[camelizedStyle],
			css;
		if (!v) {
	    	if (dv && dv.getComputedStyle) {
	        	css = dv.getComputedStyle (e, null);
	        	v = css ? css[camelizedStyle] : null;
	      	} else if (e.currentStyle) {
	       		v = e.currentStyle[camelizedStyle];
	      	}
	    }

	    if((v == 'auto') && ['width','height'].exists(style) && (e.getStyle('display') != 'none'))
	    	v = e['offset'+style.toCamel()] + 'px';

	    if (window.opera && ['left', 'top', 'right', 'bottom'].exists(style))
	    	if (e.getStyle(e, 'position') == 'static')
				v = 'auto';
	    return v == 'auto' ? null : (bInt ? (parseInt(v) || 0) : v);
    }
    catch (e) {
    	exceptionAlert ('Exception in getStyle function.', e);
		return false;
    }
}

// @function setStyle
// @descr Ustawianie styla dla podanego elementu
// @input
//		* e - element (obiekt lub nazwa)
//		* style - hash zawierajacy wlasnosci CSS
// @output element
// @example
// c: setStyle (element, {'padding-top':1+'px', 'maring-left':20+'px'})

function setStyle (e, styles) {
	try {
	    if (typeof e == 'string') e = $(e);
		var n;
		for (n in styles)
			e.style[n.toCamel()] = styles[n];
		return e;
    }
    catch (e) {
    	exceptionAlert ('Exception in setStyle function.', e);
		return false;
    }
}

// @function mySetOpacity
// @descr ustawia przezroczystosc
// @input
//		* e - ID elementu lub element w formie obiektu
//		* v - wartosc opacity (przedzial 0.0 - 1.0)
// @output nadane opacity
// @example
// c: mySetOpacity (element, 0.5)

function mySetOpacity (e, v) {
	try {
	    if (typeof e == 'string')
			e = $(e);
		if (v == 1) {
	    	v = (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
	    	if(/MSIE/.test(navigator.userAgent) && !window.opera)
				e.style.filter = getStyle(e, 'filter').replace(/alpha\([^\)]*\)/gi,'');
				var f = getStyle(e, 'filter');
				if (f != undefined)
					setStyle (e, {'filter':f.replace(/alpha\([^\)]*\)/gi,'')});
		} else {
			if(v < 0.00001)
				v = 0;
			if(/MSIE/.test(navigator.userAgent) && !window.opera) {
				var f = getStyle(e, 'filter');
				f = (f == undefined) ? '' : f.replace(/alpha\([^\)]*\)/gi,'');
				setStyle (e, {'filter':f+'alpha(opacity='+v*100+')'});
			}
		}
		return setStyle (e, {'opacity':v}) ? true : false;
    }
    catch (e) {
    	exceptionAlert ('Exception in mySetOpacity function.', e);
		return false;
    }
}

// @function myTop
// @descr Zwraca i opcjonalnie nadaje wspolrzedna Y podanemu elementowi
// @input
//		* e - ID elementu lub element w formie obiektu
//		* iY - [opt] wspolrzedna Y do nadania
// @output wspolrzedna Y
// @example
//		Zwracanie wspolrzednej Y dla podanego elementu
// c: myTop (element)
//		Nadawanie wspolrzednej Y podanemu elementowi
// c: myTop (element, 100)

function myTop (e, iY) {
	try {
	    if (typeof e == 'string') e = $(e);
		if(typeof e.style != 'undefined') {
			if (typeof e.style.top != 'undefined') {
				if (isNumber(iY))
					setStyle (e, {'top':iY+'px'});
				else
					iY = getStyle (e,'top',true);
			}
			else if (typeof e.style.pixelTop != 'undefined') {
				if (isNumber(iY))
					setStyle (e, {'pixelTop':iY});
				else
					iY = getStyle (e,'pixelTop');
			}
		}
		return iY || 0;
    }
    catch (e) {
    	exceptionAlert ('Exception in myTop function.', e);
		return false;
    }
}

// @function myLeft
// @descr Zwraca i opcjonalnie nadaje wspolrzedna X podanemu elementowi
// @input
//		* e - ID elementu lub element w formie obiektu
//		* iX - [opt] wspolrzedna X do nadania
// @output wspolrzedna X
// @example
//		Zwracanie wspolrzednej X dla podanego elementu
// c: myLeft (element)
//		Nadawanie wspolrzednej X podanemu elementowi
// c: myLeft (element, 100)

function myLeft (e, iX) {
	try {
	    if (typeof e == 'string') e = $(e);
		if (typeof e.style != 'undefined') {
			if (typeof e.style.left != 'undefined') {
				if (isNumber(iX))
					setStyle (e, {'left':iX+'px'});
				else
					iX = getStyle (e,'left',true);
			} else if (typeof e.style.pixelLeft != 'undefined') {
				if (isNumber(iX))
					setStyle (e, {'pixelLeft':iX});
				else
					iX = getStyle (e,'pixelLeft');
			}
		}
		return iX || 0;
    }
    catch (e) {
    	exceptionAlert ('Exception in myLeft function.', e);
		return false;
    }
}


// @function myCenter
// @descr Centrowanie elementu wzgledem podanego lub root-a dokumentu
// @input
//		* e 		- ID elementu lub element w formie obiektu
//		* parent 	- [OPT] parent wzgledem ktorego bedzie pozycjonowany
//		* parentSize- [OPT] wymiary parenta [width,height]
//		* offset	- [OPT] dodatkowe przesuniecie [X,Y]
//		* fixed		- [OPT] stala pozycja [X,Y]
// @output wspolrzedne X,Y
// @example
// 		c: myCenter (element)
// 		c: myCenter (element, parent, null, [100,200])
// 		c: myCenter (element, parent, [100,200], [10,5])

function myCenter (e, parent, parentSize, offset, fixed) {
	try {
		if (!(e = $(e))) return false;

		parentSize = parentSize || [null, null];
		offset = offset || [0,0];
		fixed = fixed || [null, null];

		var iX = fixed[0],
			iY = fixed[1];

		if (!parent && (iX == null || iY == null) && !parentSize[0] && !parentSize[1]) {
			var viewSize = myViewSize ();
		}
		// X nie podany w fixed
		if (iX == null) {
			iX = (parentSize[0] != null ? parentSize[0] : (parent ? myWidth (parent) : viewSize[0])) / 2 - myWidth(e)/2;
		}
		// Y nie podany w fixed
		if (iY == null) {
			iY = (parentSize[1] != null ? parentSize[1] : (parent ? myHeight (parent) : viewSize[1])) / 2 - myHeight(e)/2;
		}

		iX = Math.floor (iX + offset[0]);
		iY = Math.floor (iY + offset[1]);

		myLeft (e, iX);
		myTop (e, iY);

		return [iX,iY];
	}
	catch (e) {
    	exceptionAlert ('Exception in myCenter function.', e);
		return false;
    }
}


// @function makeUrl
// @descr Tworzy url na bazie podanej bazy i parametrow do przekazania w GET
// @input
//		* base - baza url, moze zawierac query_string
//		* dalsze parametry [opcjonalnie] - pary: nazwa paramertu, wartosc paramertu
// @output
//		* string url
// @example
//		c: makeUrl ('/webmail/mail/show?folder=123', 'id', 1234)

function makeUrl (base) {
	var i, tmp = base.split("?"),
		query = tmp[1] ? tmp[1].split("&") : [];
	for (i=1; i<arguments.length; i+=2)
		query.push (arguments[i]+'='+arguments[i+1]);
	return tmp[0]+'?'+query.join('&');
}

// @function myEncode
// @descr Laczy podana tablice w string polaczony \x0 i robi url encode
// @input
//		* tablica elementow
// @output
//		* escapowany string

function myEncode (args) {
    if (!args || args.length < 1) return '';
	return escape (args.join(String.fromCharCode(0)));
}

// @function htmlencode
// @descr encoduje znaki ktml
// @input
//		* string do zaencodowania
// @output
//		* zencodowany string

function htmlencode (text) {
    return text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

// @function htmldecode
// @descr decoduje znaki ktml
// @input
//		* string do zdecodowania
// @output
//		* zdecodowany string

function htmldecode (text) {
    return text.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&nbsp;/g, ' ').replace(/&oacute;/g, 'ó');
}

// @function toggleDisabled
// @descr
//		Naprzemienne wlaczanie i wylaczanie pol
// @input
//		* f	- formularz
//		* n	- nazwa pola
//		* d	- [bool] wylacz (1) / wlacz (0)
// @output sklonowany obiekt

function toggleDisabled (f, n, d) {
	if (!(f=$(f))) return;
	d = d || !f[n].disabled
	f[n].disabled = d;
}

// @function cloneObject
// @descr
//		klonowanie obiektow
// @input
//		* obj - obiekt do sklonowania
// @output sklonowany obiekt

function cloneObject (obj) {
	var _obj = {}, key;
	for (key in obj)
		_obj[key] = obj[key];
	return _obj;
}

// @function dump
// @descr
//		Dumpowanie zmiennych (nie wykorzystywac na obiektach HTMLColectionObject)
// @input
//		* obj 		- zmienna (lub tablica zmiennych) do zdumpowania
//		* ret 		- [opt] czy wynik ma byc zwracany (1) czy alert-owana (0)
//		* depth_max	- [opt] maksymalny poziom zaglebienia
// @output struktura zmiennej

function dump (obj, ret, depth_max) {
	if (!isArray(obj)) obj = [obj];
	var output = [], i = 0;
	for (; i<obj.length; i++) {
		output.push (dumpMap (obj[i], '', '', 0, (depth_max ? depth_max : 10)));
	}
	output = output.join ("\n\n");
	if (ret) return output; else alert (output);
}
function dumpMap (obj, name, indent, depth, depth_max) {
	// wciecie dla danego poziomu
	indent = (depth ? indent+"\t" : '');

	// zmienna wynikowa
	var output = indent + (depth ? name+': ' : '');

	// osiagnieto maksymalny dozwolony poziom
	if (depth > depth_max) {
		output += "<Maximum Depth Reached>\n";
	}

	// obiekt
	else if (isObject (obj)) {
		output += "<object>\n";
		for (var item in obj) {
			output += dumpMap (obj[item], item, indent, ++depth, depth_max);
		}
	}

	// tablica
	else if (isArray (obj)) {
		output += "<array>\n";
		for (var i=0; i<obj.length; i++) {
			output += dumpMap (obj[i], i, indent, ++depth, depth_max);
		}
	}

	// string
	else {
		output += obj
		return output + "\n";
	}

	return output;
}
function dump2_tabs (cnt) {
    var out = '';
    for (var i=0; i<cnt-1; i++) {
        out += "\t";
    }
    return out;
}
function dump2 (obj) {
    var maxlevel = (arguments[1] ? arguments[1] : false);
    var level = (arguments[2] ? arguments[2] : 0);
    var output = '';
    var key;

    if (maxlevel !== false && maxlevel == level) return;
    ++level;

	if (!obj) {
        output += dump2_tabs (level) + "NULL\n";
    } else if (obj.constructor == String) {
        output += dump2_tabs (level) + "String: " + obj + "\n";
    } else if (obj.constructor == Number) {
        output += dump2_tabs (level) + "Number: " + obj + "\n";
    } else if (obj.constructor == Function) {
        output += dump2_tabs (level) + "Function: " + obj + "\n";
    } else if (obj.constructor == Array) {
        output += dump2_tabs (level) + "Array: [\n";
        for (var i=0; i<obj.length; i++) {
            output += dump2 (obj[i], maxlevel, level);
        }
        output += dump2_tabs (level) + "]\n";
    } else if (obj.constructor == Object) {
        output += dump2_tabs (level) + "Object: [\n";
        for (key in obj) {
            output += dump2 (obj[key], maxlevel, level);
        }
        output += dump2_tabs (level) + "]\n";
    } else {
       output += dump2_tabs (level) + "Cos nieznanego :)\n";
    }

    if (level <= 1) {
        alert (output);
    } else {
        return output;
    }
}

// @function simpleSerialize
// @descr Prosta serializacja obiektow i tablic
// @input obiekt/tablica
// @output zserializowany element w postaci string-a

function simpleSerialize (e) {
	var s, a = [];
	// array
	if (isArray(e)) {
		for (var i=0; i<e.length; i++) {
			a.push (simpleSerialize(e[i]))
		}
		s = '['+a.join(',')+']';
	}
	// hash
	else if (isObject(e)) {
		var i;
		for (i in e) {
			a.push (i+':'+simpleSerialize(e[i]))
		}
		s = '{'+a.join(',')+'}';
	}
	// string
	else {
		s = (isNumber(e) ? e : '"'+e.replace(/"/g, '\\"')+'"');
	}
	return s;
}

// @function rightClick
// @descr Wykrywa right click myszy
// @input
//		* btt - event.button
// @output
//		* true/false
// @example
//		c: rightClick (event.button)

function rightClick (btt) {
	return btt == 2 ? true : false;
}

// @function selectClear
// @descr
//		Czysci zaznaczanie tekstu - dla Gecko
//		Moze byc funkcja pomocnicza dla selectPrevent()
// @input brak
// @output brak

function selectClear () {
	if (window.getSelection && !isSafari) {
		var s = window.getSelection ();
		if (s) {
			s.removeAllRanges ();
		}
	}
}

// @function removeHtmlTags
// @descr
//		Czysci tekst z tagow html - zwraca plain
//		Usuwa znaki nowej lini (obecne np w komentarzach)
//		Zamienia tagi <p>, </p>, <br/>, </tr> na \n
//		Pozostale tagi sa usuwane
// @input
//      * text - text html do oczyszczenia
// @output
//      * text - plain text

function removeHtmlTags (text) {
    //usuniecie zewnetrznego taga <p> (dla tinymce)
    text = text.replace (/^<\s*?p\s*?>/i , '');
    // wyrezanie znakow nowych linii
    text = text.replace (/\n/gi, '');
    //zamiana tagow <p>  </p> na \n
    text = text.replace(/<\/?\s*?p\s*?>/gi, "\n");
    //zamiana br na \n
    text = text.replace(/<\s*?br\s*?\/?>/gi, "\n");
    //zamiana </tr> na \n
    text = text.replace(/<\/\s*?tr\s*?>/gi, "\n");

    return text.stripTags();

}

// @function tooltip
// @descr Uaktywnia okienko podpowiedzi, wypelnia je trescia i animuje
// @input
//		* e - uchwyt eventa; przejmowany automatycznie, gdy wywolywany z eventListenera
//		* content - tekst do wyswietlenia w okienku
//		* noamin - flaga wylaczajaca animacje tooltipa
// @output brak
// @example
//		c: onmouseover="tooltip(event, 'Tresc komunikatu', 1)"

function tooltip (e, content, noanim) {
	// ustawienia poczatkowe
	var steps = 15,		// 15 krokow
		delay = 10,		// po 10ms opoznienia na kazdym
		w = 0,
		h = 0,
		o, tw, th;

	e = e || event;

	if ((o = $('tooltip')) && content) {
		o.style.width = '';
		o.style.height = '';

		o.innerHTML = content;
		tw = o.offsetWidth + 5;
		th = o.offsetHeight;

		var wStep = tw / steps,
			hStep = th / steps,

			realWidth = o.offsetWidth,
			realHeight = o.offsetHeight;

		// pozycjonuje okno tooltipa
		show = function (e) {
			var bcw = document.body.clientWidth,
				bch = document.body.clientHeight;
			o.style.left = o.style.right = o.style.top = o.style.bottom = '';

			if (e.clientX + realWidth + 10 < bcw) {
				o.style.left = e.clientX + 10 + 'px';
			} else {
				o.style.right = bcw - e.clientX + 10 + 'px';
			}

			if (e.clientY + realHeight + 5 < bch) {
				o.style.top = e.clientY + 5 + 'px';
			} else {
				o.style.bottom = bch - e.clientY + 5 + 'px';
			}
		}

		// ukrywa tooltipa
		hide = function () {
			o.innerHTML = '';
			o.style.height = '';
			o.style.visibility = 'hidden';
		}

		// animuje rozwijanie
		roll = function () {
			if (w >= tw || h >= th) {
				o.innerHTML = content;
				return true;
			}
		    o.style.width = Math.round(w) + 'px';
		    o.style.height = Math.round(h) + 'px';
		    w += wStep;
		    h += hStep;
		    setTimeout ("roll()", delay);
		    return true;
		}

		show (e);
		o.style.visibility = 'visible';
		if (!noanim) { roll (); }

		var parent = Event.element (e);
		Event.observe (parent, "mouseout", hide);
	}
}


// =========================================================================================================
// ========================    ROZMIARY    =================================================================
// =========================================================================================================

// @function myViewSize
// @descr Zwraca tablice z rozmiarami okna (viewport)
// @input brak
// @output Array (windowWidth, windowHeight)

function myViewSize () {
	var x,y;
	// wszystko poza IE
	if (self.innerHeight) {
		x = self.innerWidth;
		y = self.innerHeight;
	}
	// IE 6 Strict Mode
	else if (document.documentElement && document.documentElement.clientHeight) {
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	// pozostale IE
	else if (document.body) {
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return [x, y];
}

// @function myPageSize
// @descr Zwraca tablice z rozmiarami strony
// @input brak
// @output Array (pageWidth, pageHeight)

function myPageSize () {
	var x,y,
		b = document.body,
		test1 = b.scrollHeight,
		test2 = b.offsetHeight;

	// wszystko poza IE Mac
	if (test1 > test2) {
		x = b.scrollWidth;
		y = b.scrollHeight;
	}
	// IE Mac (zadziala takze dla IE 6 Strict Mode, Mozilla, Safari)
	else {
		x = b.offsetWidth;
		y = b.offsetHeight;
	}

	// gdy wymiary strony sa mniejsze od wymiarow okna
	winSize = myViewSize();
	y = (y < winSize[1]) ? winSize[1] : y;
	x = (x < winSize[0]) ? winSize[0] : x;

	return [x, y];
}

// @function myScrollSize
// @descr Zwraca tablice z ustawieniami scrollera
// @input brak
// @output Array (scrollWidth, scrollHeight)

function myScrollSize () {
	var b = document.body,
		e = document.documentElement;

	// wszystko poza IE
	if (self.pageYOffset) {
		return [self.pageXOffset, self.pageYOffset];
	}
	// IE 6 Strict
	else if (e && e.scrollTop) {
		return [e.scrollLeft, e.scrollTop]
	}
	// pozostale IE
	else if (b) {
		return [b.scrollLeft, b.scrollTop];
	} else {
		return [0, 0];
	}
}

// @function myWidth
// @descr Zwraca i opcjonalnie nadaje szerokosc elementowi
// @input
//		* e - element w formie obiektu
//		* w - [opt] szerokosc do nadania
// @output szerokosc
// @example
//		Zwracanie szerokosci dla podanego elementu
// c: myWidth (element)
//		Nadawanie szerokosci podanemu elementowi
// c: myWidth (element, 100)

function myWidth (e, w) {
	try {
	    if (typeof e == 'string')
			e = $(e);
		w = (isNumber(w)) ? ((w<0) ? 0 : Math.round(w)) : -1;
		var css = (typeof e.style != 'undefined');
		if (e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
			var pageSize = myPageSize ();
			w = pageSize[0];
		}
		else if (css && typeof e.offsetWidth != 'undefined' && typeof e.style.width == 'string') {
			if (w>=0) {
				var pl=0, pr=0, bl=0, br=0;
				if (document.compatMode == 'CSS1Compat') {
					pl = getStyle (e,'padding-left',1);
					if (pl !== null) {
						pr = getStyle (e,'padding-right',1);
						bl = getStyle (e,'border-left-width',1);
						br = getStyle (e,'border-right-width',1);
					}
					// getComputedStyle and currentStyle jeszcze nie istnieje
					else if (typeof e.offsetWidth != 'undefined' && typeof e.style.width != 'undefined'){
						e.style.width = w+'px';
						pl = e.offsetWidth-w;
					}
				}
				w -= (pl+pr+bl+br);
				if (isNaN(w) || w<0)
					return 0;
				else
					e.style.width = w+'px';
			}
			w = e.offsetWidth;
		}
		else if (css && typeof e.style.pixelWidth != 'undefined') {
			if (w>=0)
				e.style.pixelWidth = w;
			w = e.style.pixelWidth;
		}
		return w || 0;
    }
    catch (e) {
    	exceptionAlert ('Exception in myWidth function.', e);
		return false;
    }
}

// @function myHeight
// @descr Zwraca i opcjonalnie nadaje wysokosc elementowi
// @input
//		* e - element w formie obiektu
//		* h - [opt] wysokosc do nadania
// @output wysokosc
// @example
//		Zwracanie wysokosc dla podanego elementu
// c: myHeight (element)
//		Nadawanie wysokosc podanemu elementowi
// c: myHeight (element, 100)

function myHeight (e, h) {
	try {
	    if (typeof e == 'string')
			e = $(e);
		h = isNumber(h) ? (h<0 ? 0 : Math.round(h)) : -1;
		var css = (typeof e.style != 'undefined');
		if (e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
			var pageSize = myPageSize ();
			h = pageSize[1];
		}
		else if (css && typeof e.offsetHeight != 'undefined' && typeof e.style.height == 'string') {
			if (h>=0) {
				var pt=0, pb=0, bt=0, bb=0;
				if (document.compatMode == 'CSS1Compat') {
					pt = getStyle (e,'padding-top',1);
					if (pt !== null) {
						pb = getStyle (e,'padding-bottom',1);
						bt = getStyle (e,'border-top-width',1);
						bb = getStyle (e,'border-bottom-width',1);
					}
					// getComputedStyle & currentStyle jeszcze nie istnieje

					else if (typeof e.offsetHeight != 'undefined' && typeof e.style.height != 'undefined'){
						e.style.height = h+'px';
						pt = e.offsetHeight-h;
					}
				}
				h -= (pt+pb+bt+bb);
				if (isNaN(h) || h<0) {
					return 0;
				}
				else {
					e.style.height = h+'px';
				}
			}
			h = e.offsetHeight;
		}
		else if (css && typeof e.style.pixelHeight != 'undefined') {
			if (h>=0)
				e.style.pixelHeight = h;
			h = e.style.pixelHeight;
		}
		return h || 0;
    }
    catch (e) {
    	exceptionAlert ('Exception in myHeight function.', e);
		return false;
    }
}


// @function getOffset
// @descr Pobiera absolutna pozycje podanego elementu wzgledem dokumentu
// @input
//		* e - element
// @output [left, top]
// @example
// c: getOffset ('jakis_div')

function getOffset (el) {
	if (!(el = $(el))) return;

	var d = el.ownerDocument.documentElement;
	var b = el.ownerDocument.body

	// fajna funkcyjka dostepna od FF3 i IE >= 5
	if (el.getBoundingClientRect) {
		var rect = el.getBoundingClientRect();
		return [
			parseInt (rect.left + Math.max(d.scrollLeft, b.scrollLeft), 10) - parseInt (d.clientLeft, 10),
			parseInt (rect.top + Math.max(d.scrollTop, b.scrollTop), 10) - parseInt (d.clientTop, 10)
		];
	}
	// liczenie normalnie
	else {
		var parent = el.parentNode;
		var offsetChild = el;
		var offsetParent = el.offsetParent;
		var isSafari2 = (isSafari && parseInt(version) < 522 && !/adobeair/i.test(browser));
		var fixed = (getStyle(el, 'position') == 'fixed');

		var left = parseInt (el.offsetLeft, 10);
		var top = parseInt (el.offsetTop, 10);

		while (offsetParent) {
			left += parseInt (offsetParent.offsetLeft, 10);
			top += parseInt (offsetParent.offsetTop, 10);

			if (isMozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || isSafari && !isSafari2) {
				left += parseInt (getStyle(offsetParent, 'borderLeftWidth', true), 10);
				top += parseInt (getStyle(offsetParent, 'borderTopWidth', true), 10);
			}

			if (!fixed && getStyle(offsetParent, 'position') == 'fixed') fixed = true;

			offsetChild  = (/^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent);

			offsetParent = offsetParent.offsetParent;
		}

		while (parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
			if (!/^inline|table.*$/i.test(getStyle(parent, 'display'))) {
				left -= parseInt (parent.scrollLeft, 10);
				top -= parseInt (parent.scrollTop, 10);
			}

			if (isMozilla && getStyle(parent, 'overflow') != 'visible') {
				left += parseInt (getStyle(parent, 'borderLeftWidth', true), 10);
				top += parseInt (getStyle(parent, 'borderTopWidth', true), 10);
			}

			// nastepny parent
			parent = parent.parentNode;
		}

		if ((isSafari2 && (fixed || getStyle(offsetChild, 'position') == 'absolute')) || (isMozilla && getStyle(offsetChild, 'position') != 'absolute')) {
			left -= parseInt (b.offsetLeft, 10);
			top -= parseInt (b.offsetTop, 10);
		}
		if (fixed) {
			left += parseInt (Math.max(d.scrollLeft, b.scrollLeft), 10);
			top += parseInt (Math.max(d.scrollTop,  b.scrollTop), 10);
		}

		return [left, top];
	}
}


// =========================================================================================================
// ========================    SELECTBOX-Y    ================================================
// =========================================================================================================

// @function chooseboxMove
// @descr Przenoszenie pol pomiedzy selectami
// @input
//		* srcEl - element zrodlowy
//		* dstEl - element docelowy
//		* operation - operacja: move (przenoszenie), copy (kopiowanie), remove (tylko usuwanie)
// @output
//		* false

function chooseboxMove (srcEl, dstEl, operation) {
	try {
		if (typeof srcEl == 'string')
		   srcEl = $(srcEl);
		if (typeof dstEl == 'string')
			dstEl = $(dstEl);
		if (srcEl.selectedIndex != -1) {
			for (var i=0; i<=srcEl.options.length; i++) {
				var sel_item = srcEl.options[i];
				if (sel_item && sel_item.selected) {
					if (operation != 'remove')
						selectAddOption (dstEl, (!sel_item.text ? sel_item.innerText : sel_item.text), (sel_item.value ? sel_item.value : null));
					if (operation == 'move' || operation == 'remove') {
						srcEl.remove (i);
						i--;
					}
				}
			}
			if(operation == 'copy')
				srcEl.selectedIndex = -1;
		}
    }
    catch (e) {
    	exceptionAlert ('Exception in chooseboxMove function.', e);
    }
	finally { return false; }
}

// @function selectAddOption
// @descr Dodaje element (option) do selecta
// @input
//		* e - dany select,
//		* name - nazwa pola,
//		* value - wartosc pola
// @output
//		* brak
// @example
//		c: selectAddOption (obiekt_selecta, 'nazaw_dla_option', 'wartosc_dla_option')

function selectAddOption (e, name, value) {
	try {
		if (typeof e == 'string')
		   e = $(e);
		if (!name)
			return false;
		value = value || name;
		var newOption = new Option (name, value),
			lastIndex = e.options.length;

		// dla normalnych przegladarek
		if (e.options.add)
			e.options.add (newOption, lastIndex);
		// dla przegladarek z bugiem metody add(), np. Safari, Konqueror
		else
			e.options[lastIndex] = newOption;

		return true;
    }
    catch (e) {
    	exceptionAlert ('Exception in selectAddOption function.', e);
		return false;
    }
}

// @function selectChoose
// @descr Wybiera (lub zaznacza przy multi) element(y) podanego select-a
// @input
//		* e - select,
//		* v - wartosc(i) do zaznaczenia
// @output
//		* brak
// @example
//		c: selectChoose (select, 'wartosc')
//		c: selectChoose (select, ['wartosc1', 'wartosc2'])

function selectChoose (e, v) {
	try {
		if (typeof e == 'string')
		   e = $(e);
		var values = {},
			multi = isArray (v),
			i;
		if (multi) {
			for (i=0; i<v.length; i++)
				values[v[i]] = 1;
		} else
			values[v] = 1;
		for (i=0; i<e.options.length; i++) {
			if (values[e.options[i].value]) {
				e.options[i].selected = true;
				if (!multi)
					break;
			}
		}
		return true;
    }
    catch (e) {
    	exceptionAlert ('Exception in selectChoose function.', e);
		return false;
    }
}

// @function chooseboxSubmit
// @descr
//		Zaznaczanie wszystkich wybranych opcji w podanych selectach aby przelecialy po submicie
//		Separatorem selectow jest \0
// @input
//		* e - input z ktorego beda brane nazwy selectow do zaznaczania
// @output
//		* brak

function chooseboxSubmit (e) {
	try {
		var key, i;
		if (typeof e == 'string')
			e = $(e);
		selects = e.value.split(/\x0/);
		for (key=0; key<selects.length; key++) {
			s = $(selects[key]);
			for (i=0, imax=s.options.length; i<imax; i++)
				if (s.options[i])
					s.options[i].selected = true;
		}
		return true;
    }
    catch (e) {
    	exceptionAlert ('Exception in chooseboxSubmit function.', e);
		return false;
    }
}


// =========================================================================================================
// ========================    CHECKBOX-Y    ===============================================================
// =========================================================================================================

// @function countChecked
// @descr
//		Zwraca ilosc checkboxow zaznaczonych na wskazanym elemencie
// @input
//		* parent - nazwa parenta lub obiekt w ktorym beda szukane elementy
//		* name - name checkboxow do sprawdzenia
// @output
//		* ilosc zaznaczonych elementow

function countChecked (parent, name) {
	var checkedCnt = 0;
	try {
		if (typeof parent == 'string') { parent = $(parent); }
		var inputs = parent.getElementsByTagName ('INPUT');
		for (var i=0; i < inputs.length; i++) {
			if (inputs[i].type == 'checkbox' && inputs[i].name == name && inputs[i].checked) {
				checkedCnt++;
			}
		}
	}
	catch (e) {
		exceptionAlert ('Exception in countChecked() function', e);
	}
	finally { return checkedCnt; }
}

// @function getChecked
// @descr
//		Zwraca wartosci checkboxow zaznaczonych na wskazanym elemencie
// @input
//		* parent - nazwa parenta lub obiekt w ktorym beda szukane elementy
//		* name - name checkboxow do sprawdzenia
// @output
//		* zaznaczone elementy

function getChecked (parent, name) {
	var values = [];
	try {
		if (typeof parent == 'string') { parent = $(parent); }
		var inputs = parent.getElementsByTagName ('INPUT');
		for (var i=0; i < inputs.length; i++) {
			if (inputs[i].type == 'checkbox' && inputs[i].name == name && inputs[i].checked) {
				values.push (inputs[i].value);
			}
		}
	}
	catch (e) {
		exceptionAlert ('Exception in getChecked() function', e);
	}
	finally { return values; }
}

// @function checkboxesMark
// @descr
//		Zaznacza/odznacza checkboxy na wskazanym elemencie.
// @input
//		* parent - nazwa parenta lub obiekt w ktorym beda szukane elementy
//		* id - id checkboxow do sprawdzenia
// @output Brak

function checkboxesMark (parent, id) {
	try {
		if (typeof parent == 'string')
			parent = $(parent);
		if (typeof $TEMP['chboxMarked'] == 'undefined') {
			$TEMP['chboxMarked'] = {};
			$TEMP['chboxMarked'][id] = false;
		}
		var i, inputs = parent.getElementsByTagName ('INPUT');
		for (i=0; i < inputs.length; i++) {
			if (inputs[i].type == 'checkbox' && inputs[i].name == id)
				inputs[i].checked = ($TEMP['chboxMarked'][id] ? false : true);
		}
		$TEMP['chboxMarked'][id] = ($TEMP['chboxMarked'][id] ? false : true);
	}
	catch (e) {
		exceptionAlert ("Exception in checkboxesMark() function", e);
	}
	finally { return false; }
}

// @function checkboxesToggle
// @descr
//		Przelacz (toggle) checkboxy na wskazanym elemencie.
// @input
//		* parent - nazwa parenta lub obiekt w ktorym beda szukane elementy
//		* name - name checkboxow do sprawdzenia
//		* checked - [opcja] zaznacz/odznacz checkboxy
// @output Brak

function checkboxesToggle (parent, name, checked) {
	try {
		if (typeof parent == 'string') { parent = $(parent); }
		if (!parent || !name) return false;
		var i, inputs = parent.getElementsByTagName ('input');
		for (i=0; i < inputs.length; i++) {
			if (inputs[i].type == 'checkbox' && inputs[i].name == name) {
				inputs[i].checked = (typeof checked != 'undefined'
					? (checked ? true : false)
					: (inputs[i].checked ? false : true)
				);
			}
		}
	}
	catch (e) {
		exceptionAlert ("Exception in checkboxesToggle() function", e);
	}
	finally { return false; }
}

// =========================================================================================================
// ========================    COOKIES    ==================================================================
// =========================================================================================================

// @function setCookie
// @descr Ustawia cookie: pierwsze dwa argumenty sa obowiazkowe
// @input
//		standardowe wartosci dla cookie
// @output brak
// @example
//		c: setCookie ('nazwa_ciacha', 'jakas_wartosc', '', '/');

function setCookie (name, value, expires, path, domain, secure) {
	var curCookie = name + "=" + escape(value) +
		((expires) ? "; expires=" + expires.toGMTString() : "") +
		((path) ? "; path=" + path : "") +
		((domain) ? "; domain=" + domain : "") +
		((secure) ? "; secure" : "");
	document.cookie = curCookie;
}

// @function getCookie
// @descr Pobiera wartosc cookie
// @input
//		* name - nazwa ciastka
// @output zwraca wartosc ciaska o podanej nazwie
// @example
//		c: getCookie('nazwa_ciacha')

function getCookie (name) {
	var dc = document.cookie,
		prefix = name + "=",
		begin = dc.indexOf("; " + prefix);
	if (begin == -1) {
		begin = dc.indexOf(prefix);
		if (begin != 0)
			return null;
	} else
		begin += 2;
	var end = document.cookie.indexOf(";", begin);
	if (end == -1)
		end = dc.length;
	return unescape (dc.substring(begin + prefix.length, end));
}

// @function deleteCookie
// @descr Usuwa cookie: tylko name obowiazkowe
// @input
//		* standardowe parametry cookie: name, path, domain
// @output brak
// @example
//		c: deleteCookie ('storeconfig', '/');

function deleteCookie (name, path, domain) {
	if (getCookie(name)) {
		document.cookie = name + "=" +
			((path) ? "; path=" + path : "") +
			((domain) ? "; domain=" + domain : "") +
			"; expires=Thu, 01-Jan-70 00:00:01 GMT";
	}
}
