/**
 * soubor functions.js
 * obsahuje obecne funkce, ktere pouzivame v projektu Previo
 *
 * @author MITON Previo s.r.o.
 * @created 8.8.2006
 */




/**
 * vraci text za pomlckou, vyselektovane z retezce typu: text-cislo (delete-13)
 *
 * @return {String} retezec umisteny za pomlckou
 */
function returnLastNumberOfString(text) {
    return text.substring(text.lastIndexOf('-') + 1, text.length);
};


/**
 * vraci pocet zaznamu ulozenych v objektu - identicky pristup jako k poli Array
 *
 * @return {int} pocet zaznamu v objektu
 */
function returnObjectCount(object) {
    var count = 0;

    $H(object).each ( function(item) {
        count++;
    } );

    return count;
};


/**
 * odstrani vsechny potomky elementu "element"
 *
 * @return void
 */
function removeChildNodes(element) {
    while (element.childNodes[0]) {
        Element.remove(element.childNodes[0]);
    }
};

/**
 * zaokrouhleni na X desetinnych mist
 * @param val
 * @param precision
 * @return
 */
function round ( val, precision ) {
    return parseFloat(parseFloat(val).toFixed(precision));
}

/**
 * disabluje vsechny formularove potomky elementu "element"
 *
 * @return void
 */
function disableFormChildNodes(element) {
    $H(element.getElementsByTagName('input')).each ( function(item) {
        item.value.disabled = true;

        if (typeof item.value == 'object') {
            disableFormChildNodes(item.value);
        }
    } );
};


/**
 * vraci hodnotu parametru "value" v elementu "option", ktery byl v select liste vybran
 *
 * @param selectBox select lista
 * @return {String} hodnota parametru "value"
 */
function getSelectBoxValue(selectBox) {
	return selectBox.options[selectBox.selectedIndex].value;
};


/**
 * nastavuje hodnotu parametru "value" v elementu "option", ktery ma byt v select liste vybran
 *
 * @param selectBox select lista
 * @param value hodnota parametru value
 * @return void
 */
function setSelectBoxValue(selectBox, value) {
    for (var i = 0; i < selectBox.length; i++) {
        if (selectBox.options[i].value == value) {
            selectBox.options[i].selected = true;
        } else {
            selectBox.options[i].selected = false;
        }
	}
};

/**
 * Ziska VALUE radioBoxu, ktery je zatrzen
 * @param Array radioBoxes pole Elementu (INPUT[type=radio])
 * @return mixed hodnota, ktera je vybrana (NULL - nebylo vybrano nic)
 */
function getRadioBoxValue(radioBoxes) {
	var checkedValue = null;
	radioBoxes.each( function (radioBox) {
		if (radioBox.checked) checkedValue = radioBox.value;
	} );
	return checkedValue;
}


/**
 * @return {String} retezec bez prazdnych znaku na zacatku a konci retezce
 */
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/, '');
};

String.prototype.ucFirst = function() {
	return this.charAt(0).toUpperCase() + this.substring(1);
};

/**
 * Funkce pouze doplni NULU pred jednociferne cislo (pokud je cislo dvouciferne, tak nic nedoplni)
 * @todo dodelat parametry jako v PHP funkci str_pad :)
 * @return {String}
 */
String.prototype.strPad = function() {
	return (!isNaN(this) && this.toString().length == 1) ? "0" + this : this;
};

String.prototype.replaceAll = function(stringToFind, stringToReplace) {
    var temp = this;
    var index = temp.indexOf(stringToFind);
    while(index != -1){
        temp = temp.replace(stringToFind,stringToReplace);
        index = temp.indexOf(stringToFind);
    }
    return temp;
};

String.prototype.truncateFromEnd = function(length, truncation) {
    length = length || 30;
    truncation = Object.isUndefined(truncation) ? '…' : truncation;
    return this.length > length ?
    	truncation + this.slice(-length + truncation.length, this.length) :
    	String(this);
};


/**
 * @param tagName html tag, jehoz ID ma byt vraceno
 * @param parentLevel cislo udavajici, do jake urovne se ma jit (parentLevel)
 * @return {String} ID elementu, ktery je nadrazen Elementu predanemu v parametru
 */
function getParentElementIdByTagName(parentElement, tagName, parentLevel) {
    var found = "";
    // cyklus, ve kterem prochazime DOM nahoru, dokud nenarazime na prvek tagName
    while (found != "ok") {
        if (!parentElement) {
            return false;
        }
        if (parentElement.tagName.toLowerCase() == tagName.toLowerCase()) {
            parentLevel--;
            if (parentLevel <= 0) {
                found = "ok";
            } else {
                parentElement = parentElement.parentNode;
            }
        } else {
            parentElement = parentElement.parentNode;
        }
    }

    return parentElement.id;
};


// To find the left position, add this snippet to your code:
function getPositionLeft(element) {
    var element1 = element;
    var position = 0;

    while (element1) {
        position += element1.offsetLeft;
        element1 =  element1.offsetParent;
    }
    return position;
};


// To find the top position, add this snippet to your code:
function getPositionTop(element) {
    var element1 = element;
    var position = 0;

    while (element1) {
        position += element1.offsetTop;
        element1 =  element1.offsetParent;
    }

    return position;
};


/**
 * vraci souradnici X po kliknuti mysi
 *
 * @param e Event
 * @return {int} souradnice X
 */
function getEventPositionX(e) {
    return e.clientX;
};


/**
 * vraci souradnici Y po kliknuti mysi
 *
 * @param e Event
 * @return {int} souradnice Y
 */
function getEventPositionY(e) {
    return e.clientY;
};


/**
 * vklada novy element ZA jiny element
 *
 * @param parent - napriklad ID tabulky
 * @param referenceNode - napriklad ID radku v tabulce
 * @param node - napriklad ID noveho radku, ktery vkladame do tabulky
 * @link http://www-128.ibm.com/developerworks/xml/library/x-matters41.html
 */
function insertAfter(parent, referenceNode, node) {
    parent.insertBefore(node, referenceNode.nextSibling);
};


/**
 * Provadi serazeni pole, ktere je ziskano z parametru, dle zadaneho sloupce.
 *
 * @param arrayData pole, ktere ma byt serazeno
 * @param column sloupec, dle ktereho se ma radit
 * @param sortMethod metoda pro razeni (0 - abedecni ceske, 1 - celociselne)
 * @param sortDirection pole se smery razeni pro jednotlive sloupce
 */
function arraySort(arrayData, column, sortMethod, sortDirection) {

    /**
     * Funkce compare, kterou používá metoda sort (viz níže).
     *
     * @return
     */
    function compare(i, j) {
        var value1 = i[(column.toString() * 1) + 1].trim();
        var value2 = j[(column.toString() * 1) + 1].trim();

        switch (sortMethod) {
            case "0":
                return sortDirection[column] * value1.localeCompare(value2);
            case "1":
                return sortDirection[column] * (value1 - value2);
        }
    }

    arrayData.sort(compare);
};

function localeCompare(i, j) {
	var iDiacritic = char2Diacritic(i);
	var jDiacritic = char2Diacritic(j);
	if (iDiacritic == jDiacritic) return 0;
	else if (iDiacritic > jDiacritic) return 1;
	else return -1;
}

/**
 * funguje na principu přidávání dalšího znaku za aktuální znak.
 * V případě že narazí na český napíše jej bez diakritiky a přidá znak 'z'
 * V případě že narazí na Ch či ch udělá z něj jeden znak typu Ia nebo ia, čímž
 *     dojde ke korektnímu seřazení
 * Ostatní znaky přepisuje na znak a přidá znak 'f'
 *
 */
function char2Diacritic(transDiacritic)
{
	var charDiacritic = "áÁčČďĎéÉíÍĺĹľĽŇóÓÔŕŔřŘšŠťŤúÚůŮýÝžŽ";
	var numDiacritic =  "aAcCdDeEiIlLlLNoOOrRrRsStTúUuUyYzZ";
	var tmpDiacritic = "";
	var newDiacritic = "";
	for(i = 0; i < transDiacritic.length; ++i)
    {
        if (charDiacritic.indexOf(transDiacritic.charAt(i)) != -1)
            tmpDiacritic += numDiacritic.charAt(charDiacritic.indexOf(transDiacritic.charAt(i))) + 'z';
        else
            tmpDiacritic += transDiacritic.charAt(i) + 'f';
    }

    tmpDiacritic = tmpDiacritic.replace(/Cfhf/g,"Ia");
    tmpDiacritic = tmpDiacritic.replace(/cfhf/g,"ia");

    return tmpDiacritic;
}


/**
 * nastavuje text pro informacni hlasku
 *
 * @param text retezec, ktery ma byt vepsan
 * @param alert bool, vypis standartni hlasky nebo alertu
 * @param information bool, vypis stanadrtni hlasky nebo informacni
 */
function setTopMessageText(text, alert, information) {
    var style = '';
    if (alert) {
        style += "color: red;";
    } else if (!information) {
        style += "fontWeight: bold;";
    } else {
        style += "color: #7F7F7F;";
    }

    InfoBar.Instance.insertNewMessage({'text': text, 'style': style});
};

/**
 * Do elementu prida DIV s css vlastnosti "clear: both"
 * @param Element element
 */
appendClearer = function(element) {
	element.appendChild(
		new Element("div", {
			"style": "clear: both;"
		})
	);
};


/**
 * pokud je argument ciselneho typu , vrati true
 */
function isNumeric(x) {
    // regular expression that validates a value is numeric
    var regExp = /^(-)?(\d+)(\.?)(\d*)$/; // Note: this WILL allow a number that ends in a decimal: -452.
    // vedecky format /^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/
    re = new RegExp(regExp);
    var result = re.test(x);
    return result;
};

/**
 * Zjisti, zda je parametr kladne cele cislo
 * @param x
 * @return
 */
function isPositiveInt(x, allowZero) {
	var isPositiveNumber = false;
	x = parseInt(x + "");
	if (!isNaN(x)) {
		if (x > 0 || (allowZero && x == 0)) {
			isPositiveNumber = true;
		}
	}
    return isPositiveNumber;
}

function isNull(val) {
    return (val==null);
};

function isEven(num) {
    return !(num % 2);
};

function isOdd(num) {
    return (num % 2);
};

/**
 * posluchac onMouseOver pri najeti mysi nad element
 * nastavi styl, ktery zvyrazni dany element (element bude moci byt editovan)
 *
 * @param e Event
 */
function showEditableStyle(e) {
    var element = Event.element(e);
    element.className = "settings-editor settings-editor-hover";
};


/**
 * posluchac onMouseOut pri najeti mysi mimo element
 * odebere styl, ktery zvyraznil dany element (element bude moci byt editovan)
 *
 * @param e Event
 */
function hideEditableStyle(e) {
    var element = Event.element(e);
    element.className = "settings-editor settings-editor-idle";
};




/**
 * vraci datum vetsi o pocet dni, ktery se rovna parametru perioda
 */
function getOlderDate(datum, perioda) {
    var date = Date.fromDbDateString(datum);
    date.setDate(date.getDate()+perioda)

    return date.toDbDateString();
};



function parseDate(value,format) {
    format = format.toLowerCase();
    switch (format) {
        case "yyyy-mm-dd":
        case "rrrr-mm-dd":
            var separFirst = value.indexOf('-');
            var separLast  = value.lastIndexOf('-');
            var year       = parseInt(value.substring(0, separFirst), 10);
            var month      = parseInt(value.substring(separFirst+1, separLast), 10);
            var day        = parseInt(value.substring(separLast+1, value.length), 10);
        break;
		case 'dd.mm.rrrr':
		case 'dd.mm.yyyy':
        default:
            var separFirst = value.indexOf('.');
            var separLast  = value.lastIndexOf('.');
            var year       = parseInt(value.substring(separLast+1, value.length), 10);
            var month      = parseInt(value.substring(separFirs1+1, separLast), 10);
            var day        = parseInt(value.substring(0, separFirst), 10);
        break;
    }
    date = new Date();
    date.setFullYear(year,month-1,day);
    return date;
};

function dateDiff(dateFrom,dateTo) {
	var dayInMiliseconds = 24*60*60*1000;
	return (
		Math.floor(dateTo.getTime() / (dayInMiliseconds) - dateTo.getTimezoneOffset() / (60*24)) -
		Math.floor(dateFrom.getTime() / (dayInMiliseconds) - dateFrom.getTimezoneOffset() / (60*24))
	);

}


/**
 * porovnava mezi sebou 2 datumy
 *
 * @param {String} value1 1. datum
 * @param {String} value2 2. datum
 * @param {String} format format datumu (napr. "RRRR-MM-DD", "DD.MM.RRRR")
 * @return {int} 1 - 1. datum je vetsi, -1 - 2. datum je vetsi, 0 - rovnaji se
 */
function compareDates(value1, value2, format) {
    switch (format) {
        case "RRRR-MM-DD":
            var separFirst1 = value1.indexOf('-');
            var separLast1  = value1.lastIndexOf('-');
            var year1       = parseInt(value1.substring(0, separFirst1), 10);
            var month1      = parseInt(value1.substring(separFirst1+1, separLast1), 10);
            var day1        = parseInt(value1.substring(separLast1+1, value1.length), 10);

            var separFirst2 = value2.indexOf('-');
            var separLast2  = value2.lastIndexOf('-');
            var year2       = parseInt(value2.substring(0, separFirst2), 10);
            var month2      = parseInt(value2.substring(separFirst2+1, separLast2), 10);
            var day2        = parseInt(value2.substring(separLast2+1, value2.length), 10);

            break;
        //case "DD.MM.RRRR":
        default:
            var separFirst1 = value1.indexOf('.');
            var separLast1  = value1.lastIndexOf('.');
            var year1       = parseInt(value1.substring(separLast1+1, value1.length), 10);
            var month1      = parseInt(value1.substring(separFirst1+1, separLast1), 10);
            var day1        = parseInt(value1.substring(0, separFirst1), 10);

            var separFirst2 = value2.indexOf('.');
            var separLast2  = value2.lastIndexOf('.');
            var year2       = parseInt(value2.substring(separLast2+1, value2.length), 10);
            var month2      = parseInt(value2.substring(separFirst2+1, separLast2), 10);
            var day2        = parseInt(value2.substring(0, separFirst2), 10);
            break;
    }

    if (year1 > year2) return 1;
    else if (year1 < year2) return -1;
    else if (month1 > month2) return 1;
    else if (month1 < month2) return -1;
    else if (day1 > day2) return 1;
    else if (day1 < day2) return -1;
    else return 0;
};




/**
 * vraci pole s pocty dnu ve vsech mesicich (musi odpovidat danemu intervalu)
 *
 * @param {String} year rok, pro ktery chceme posty dnu znat
 * @param {String} termFrom termin od
 * @param {String} termTo termin do
 * @return {array} pole s pocty dnu pro vsechny mesice
 */
function getDaysByYearAndTerm(year, termFrom, termTo) {
    var months = new Array();
    months[1] = 31;
    months[2] = (year % 4 == 0) ? 29 : 28;
    months[3] = 31;
    months[4] = 30;
    months[5] = 31;
    months[6] = 30;
    months[7] = 31;
    months[8] = 31;
    months[9] = 30;
    months[10] = 31;
    months[11] = 30;
    months[12] = 31;


    var separFirst1 = termFrom.indexOf('-');
    var separLast1  = termFrom.lastIndexOf('-');
    var year1       = parseInt(termFrom.substring(0, separFirst1), 10);
    var month1      = parseInt(termFrom.substring(separFirst1+1, separLast1), 10);
    var day1        = parseInt(termFrom.substring(separLast1+1, termFrom.length), 10);

    var separFirst2 = termTo.indexOf('-');
    var separLast2  = termTo.lastIndexOf('-');
    var year2       = parseInt(termTo.substring(0, separFirst2), 10);
    var month2      = parseInt(termTo.substring(separFirst2+1, separLast2), 10);
    var day2        = parseInt(termTo.substring(separLast2+1, termTo.length), 10);


    if ((year == year1) && (year == year2)) {
        $H(months).each ( function(item) {
            if ((item.key == month1) && (item.key == month2))
                months[item.key] = day2 - day1 + 1;
            else if (item.key == month1)
                months[item.key] = months[item.key] - day1 + 1;
            else if (item.key == month2)
                months[item.key] = day2;
            else if ((item.key < month1) || (item.key > month2))
                months[item.key] = 0;
        } );
    } else if (year == year1) {
        $H(months).each ( function(item) {
            if (item.key == month1)
                months[item.key] = months[item.key] - day1 + 1;
            else if (item.key < month1)
                months[item.key] = 0;
        } );
    } else if (year == year2) {
        $H(months).each ( function(item) {
            if (item.key == month2)
                months[item.key] = day2;
            else if (item.key > month2)
                months[item.key] = 0;
        } );
    }

    return months;
};

function takeYear(theDate) {
    x = theDate.getYear();
    var y = x % 100;
    y += (y < 38) ? 2000 : 1900;
    return y;
};

function getTodaysDate () {
    function leadingZero(nr) {
    	if (nr < 10) nr = "0" + nr;
    	return nr;
    }

    var today = new Date();
    var Year = takeYear(today);
    var Month = leadingZero(today.getMonth()+1);
    var Day = leadingZero(today.getDate());

    return Year + "-" + Month + "-" + Day;
};


function getWeekNr (today)
{
    var year = takeYear(today);
	var month = today.getMonth();
	var day = today.getDate();

    var monthDays = getDaysByYearAndTerm(year, year+"-01-01", year+"-"+(month+1)+"-"+day);
	var daysInYear = 0;

    $H(monthDays).each ( function(item1) {
        daysInYear += monthDays[item1.key];
    } );

    return Math.ceil(daysInYear / 7);
};

/**
 * Odesle formular pro prepnuti hotelu
 */
function switchHotel() {
    $("switch-hotel-form").submit();
};

function selectText(e) {
    $(Event.element(e).id).focus();
    $(Event.element(e).id).select();
};

function applyForChildNodes(myparent, event, childTagName, method) {
    $A(myparent.getElementsByTagName(childTagName)).each ( function(item) {
        Event.observe(item, event, method);
    } );
};

function from10toRadix(value,radix) {
    var retVal = '';
    var convArray = new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
    var intNum;
    var tmpNum;
    var i = 0;

    intNum = parseInt(value,10);
    if (isNaN(intNum)){
        retVal = 'NaN';
    } else {
        while (intNum > 0.9){
            i++;
            tmpNum = intNum;
            // cancatinate return string with new digit:
            retVal = convArray[tmpNum % radix] + retVal;
            intNum = Math.floor(tmpNum / radix);
            if (i > 100){
                // break infinite loops
                retVal = 'NaN';
                break;
            }
        }
    }
    while (retVal.length < 2) {
        retVal = "0" + retVal;
    }
    return retVal;
};

/**
 * Konverze libovolne hodnoty na string
 *
 * Narozdil od interni JavaScript konverze konvertuje
 * objekty, pole, boolean, NaN, Infinite hodnoty do prazdneho retezce.
 * @param {mixed} value
 * @return Hodnota prevedena na string
 * @type String
 */
function toString(value) {
    if (typeof(value) == "string") {
        return value;
    }
    if (typeof(value) == "number" && !isNaN(value) && isFinite(value)) {
        return value + "";
    }
    return "";
}

/**
 * Konverze libovolne hodnoty na cele cislo
 *
 * Narozdil od parseInt() JavaScript konverze konvertuje
 * objekty, pole, boolean, NaN, Infinite hodnoty do 0 namisto do NaN.
 * @param {mixed} value
 * @return Hodnota prevedena na string
 * @type int
 */
function toInt(value) {
    var value = parseInt(value, 10);

    if (!isNaN(value) && isFinite(value)) {
        return value;
    }

    return 0;
}

/**
 * Konverze libovolne hodnoty na desetinne cislo
 *
 * Narozdil od parseFloat() JavaScript konverze konvertuje
 * objeky, pole, boolean, NaN, Infinite hodnoty do 0 namisto do NaN.
 * @param {mixed} value
 * @return Hodnota prevedena na string
 * @type int
 */
function toFloat(value) {
    value = parseFloat(value);

    if (!isNaN(value) && isFinite(value)) {
        return value;
    }

    return 0;
}

/**
 * Konverze libovolné hodnoty na objekt
 *
 * Výsledný objekt je vždy pouze typu Object, všechny
 * ostatní objekty jsou na něj převedeny.
 * @param {mixed} value
 * @return {Object}
 */
function toObject(value) {
    if (!value || value.constructor != Object) {
        value = {};
    }

    return value;
}

/**
 * Zjisti, zda je objekt prazdny
 * @param Object ob
 * @return boolean
 */
function isEmptyObject (ob) {
	for (var i in ob) {
		if (ob.hasOwnProperty(i)) {
			return false;
		}
	}
	return true;
}

/**
 * PHP Serializer
 */
function php_serialize(obj)
{
    var string = '';

    if (typeof(obj) == 'object') {
        if (obj instanceof Array) {
            string = 'a:';
            tmpstring = '';
            count = 0;
            for (var key in obj) {
                tmpstring += php_serialize(key);
                tmpstring += php_serialize(obj[key]);
                count++;
            }
            string += count + ':{';
            string += tmpstring;
            string += '}';
        } else if (obj instanceof Object) {
            classname = obj.toString();

            if (classname == '[object Object]') {
                classname = 'StdClass';
            }

            string = 'O:' + classname.length + ':"' + classname + '":';
            tmpstring = '';
            count = 0;
            for (var key in obj) {
                tmpstring += php_serialize(key);
                if (obj[key]) {
                    tmpstring += php_serialize(obj[key]);
                } else {
                    tmpstring += php_serialize('');
                }
                count++;
            }
            string += count + ':{' + tmpstring + '}';
        }
    } else {
        switch (typeof(obj)) {
            case 'number':
                if (obj - Math.floor(obj) != 0) {
                    string += 'd:' + obj + ';';
                } else {
                    string += 'i:' + obj + ';';
                }
                break;
            case 'string':
                string += 's:' + obj.length + ':"' + obj + '";';
                break;
            case 'boolean':
                if (obj) {
                    string += 'b:1;';
                } else {
                    string += 'b:0;';
                }
                break;
        }
    }

    return string;
}

/**
*
*  Javascript sprintf
*  http://www.webtoolkit.info/
*
*
**/

var sprintfWrapper = {

    init : function () {

        if (typeof arguments == "undefined") { return null; }
        if (arguments.length < 1) { return null; }
        if (typeof arguments[0] != "string") { return null; }
        if (typeof RegExp == "undefined") { return null; }

        var string = arguments[0];
        var exp = new RegExp(/(%([%]|(\-)?(\+|\x20)?(0)?(\d+)?(\.(\d)?)?([bcdfosxX])))/g);
        var matches = new Array();
        var strings = new Array();
        var convCount = 0;
        var stringPosStart = 0;
        var stringPosEnd = 0;
        var matchPosEnd = 0;
        var newString = '';
        var match = null;

        while (match = exp.exec(string)) {
            if (match[9]) { convCount += 1; }

            stringPosStart = matchPosEnd;
            stringPosEnd = exp.lastIndex - match[0].length;
            strings[strings.length] = string.substring(stringPosStart, stringPosEnd);

            matchPosEnd = exp.lastIndex;
            matches[matches.length] = {
                match: match[0],
                left: match[3] ? true : false,
                sign: match[4] || '',
                pad: match[5] || ' ',
                min: match[6] || 0,
                precision: match[8],
                code: match[9] || '%',
                negative: parseInt(arguments[convCount]) < 0 ? true : false,
                argument: String(arguments[convCount])
            };
        }
        strings[strings.length] = string.substring(matchPosEnd);

        if (matches.length == 0) { return string; }
        if ((arguments.length - 1) < convCount) { return null; }

        var code = null;
        var match = null;
        var i = null;

        for (i=0; i<matches.length; i++) {

            if (matches[i].code == '%') { substitution = '%' }
            else if (matches[i].code == 'b') {
                matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(2));
                substitution = sprintfWrapper.convert(matches[i], true);
            }
            else if (matches[i].code == 'c') {
                matches[i].argument = String(String.fromCharCode(parseInt(Math.abs(parseInt(matches[i].argument)))));
                substitution = sprintfWrapper.convert(matches[i], true);
            }
            else if (matches[i].code == 'd') {
                matches[i].argument = String(Math.abs(parseInt(matches[i].argument)));
                substitution = sprintfWrapper.convert(matches[i]);
            }
            else if (matches[i].code == 'f') {
                matches[i].argument = String(Math.abs(parseFloat(matches[i].argument)).toFixed(matches[i].precision ? matches[i].precision : 6));
                substitution = sprintfWrapper.convert(matches[i]);
            }
            else if (matches[i].code == 'o') {
                matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(8));
                substitution = sprintfWrapper.convert(matches[i]);
            }
            else if (matches[i].code == 's') {
                matches[i].argument = matches[i].argument.substring(0, matches[i].precision ? matches[i].precision : matches[i].argument.length)
                substitution = sprintfWrapper.convert(matches[i], true);
            }
            else if (matches[i].code == 'x') {
                matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16));
                substitution = sprintfWrapper.convert(matches[i]);
            }
            else if (matches[i].code == 'X') {
                matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16));
                substitution = sprintfWrapper.convert(matches[i]).toUpperCase();
            }
            else {
                substitution = matches[i].match;
            }

            newString += strings[i];
            newString += substitution;

        }
        newString += strings[i];

        return newString;

    },

    convert : function(match, nosign){
        if (nosign) {
            match.sign = '';
        } else {
            match.sign = match.negative ? '-' : match.sign;
        }
        var l = match.min - match.argument.length + 1 - match.sign.length;
        var pad = new Array(l < 0 ? 0 : l).join(match.pad);
        if (!match.left) {
            if (match.pad == "0" || nosign) {
                return match.sign + pad + match.argument;
            } else {
                return pad + match.sign + match.argument;
            }
        } else {
            if (match.pad == "0" || nosign) {
                return match.sign + match.argument + pad.replace(/0/g, ' ');
            } else {
                return match.sign + match.argument + pad;
            }
        }
    }
};

var sprintf = sprintfWrapper.init;

function _u(msgId) {
    return Lang.Messages[msgId] || msgId;
}

function _g(msgId) {
    return Lang.Messages[msgId] || msgId;
}


function _nu(msgIdSg, msgIdPl, n) {
	if (Lang.Messages[msgIdSg] != undefined) {
        var i = new Function("n", Lang.nSwitch)(n);
        return Lang.Messages[msgIdSg][i] ? Lang.Messages[msgIdSg][i] : Lang.Messages[msgIdSg][0];
    }
    return n > 1 ? msgIdPl : msgIdSg;
}

/**
 * Funkce slouzici k dynamickemu nacteni javascriptu
 * funguje tak, ze prida do HEADu novy tag SCRIPT se zadanym src
 * po nacteni javascriptu volitelne zavola callback
 * funkce je nezavisla na prototypu
 */
function includeJavascript(scriptURI,callback) {
	// najdeme tag HEAD
	var html_doc = document.getElementsByTagName('head').item(0);
    // vytvorime element SCRIPT s prislusnymi parametry
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', scriptURI);
    // prilepime ho do HEADU na konec
    html_doc.appendChild(js);

    // pokud je definovan callback, zavolame ho
    if (callback != undefined) {

    	// reseni pro FF/IE se lisi
	    js.onreadystatechange = function () {
    	 	if (js.readyState == 'complete') {
        	    	callback();
    		}
    	};

		// reseni pro FF/IE se lisi
		js.onload = function () {
    		callback();
    	};
    }
}

/**
 * Funkce slouzici k dynamickemu nacteni javascriptu pouze jednou - obdoba include_once z PHP
 * V pripade, ze uz JS nacten je, muze se callback zavolat volitelne
 */
function includeJavascriptOnce(scriptURI, callback, callEvenIfDuplicate) {
		// pokud globalni seznam includovanych JS neexistuje, vytvorime ho
		if (!window['included_files']) {
			window['included_files'] = new Array();
		}

		// pokud v seznamu jeste skript neni, nacteme ho
		if (!in_array(scriptURI, included_files)) {
			// predpokladame uspech
	        window['included_files'][included_files.length] = scriptURI;
			includeJavascript(scriptURI,callback);
		}
		// jinak alespon zavolame callback, je-li zajem
		else {
			if ((callback != undefined) && (callEvenIfDuplicate)) {
				callback();
			}
		}
}

/**
 * Zjisti, zda se jiz v poli dany prvek nachazi
 * pouze pro potreby includovani javascriptu
 * nezavisi na Prototype
 */

function in_array(needle, haystack) {
	for (var i = 0; i < haystack.length; i++) {
 		if (haystack[i] == needle) {
        	return true;
        }
    }
	return false;
}

/**
 * Vygeneruje nahodny retezec
 *
 * @params sChrs string vstupni mnozina snaku pro generovani retezce
 * @params iLen int delaka vygenerovaneho retezce
 */
function randomString(sChrs, iLen) {
    var sRnd = '';
    for (var i=0; i < iLen; i++) {
        var randomPoz = Math.floor(Math.random() * sChrs.length);
        sRnd += sChrs.substring(randomPoz, randomPoz + 1);
    }
    return sRnd;
}

/**
 * Vygeneruje nahodny retezec z alfanumerickych znaku
 *
 * @params iLen int delaka vygenerovaneho retezce
 */
function randomStringStandard(iLen) {
    var sChars = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ1234567890';
    return randomString(sChars, iLen);
}

/**
 * Vyexportuje PDF do nového okna
 *
 * @param {string} url Akce, která generuje pdf.
 * @param {number} resourceId Id zdroje, který se bude exportovat.
 * @param {string} [method] POST nebo GET. Vychozí je GET.
 */
function exportDocument(url, resourceId, method) {
    var fly = new FlyForm(url, method || "GET", "_blank");
    fly.set("res_id", resourceId);
    fly.submit();
}

/**
 * Vygenerování jedinečného id
 *
 * Id obsahuje i čísla aby nemohlo dojít
 * ke kolizi se stávajícími lidskými id.
 *
 * Takto vygenerované id se hodí
 * zejména pro elementy.
 * @param {string} [prefix] Volitelný prefix
 * @return {string}
 */
var $id = function() {
    var i = 0;
    var generator = function(prefix) {
        var j = i;
        //TODO: Řada není spojitá
        var id = i % 10;

        // ASCII 49 = 1, 57 = 9, 97 = a, 122 = z
        do {
            id = String.fromCharCode(97 + j % 25) + id;
            j = Math.floor(j / 25);
        } while(j > 0 || id.length < 3);

        id = (prefix || "") + id;
        ++i;
        return id;
    }
    return generator;
}();

/**
 * Url do css
 *
 * Prohlížeče akceptují obrázky na pozadí
 * jako řetězec url(url_obrázku).
 *
 * Tato funkce vezme skutečnou url obrázku a
 * obalí ji do css funkce url.
 * @param {string} url
 * @return {string}
 */
function url(url) {
    return "url(" + url + ")";
}

(function() {
    var __specials__ = "/.*+?|()[]{}\\".split("");
    var __sre__ = new RegExp("(\\" + __specials__.join("|\\") + ")", "g");
    RegExp.escape = function(text) { text.replace(__sre__, "\\$1"); }
})();

//
// Rekurzivni klonovani objektu
// http://www.faqts.com/knowledge_base/view.phtml/aid/6231
//
/*
Object.prototype.deepCopy = function() {
    if (this.constructor == Date) {
        var objectClone = new Date(this.valueOf());
        return objectClone;
    }
    var objectClone = new this.constructor();
    for (var property in this)
    if (typeof(this[property]) == 'object' && this[property] != null)
        objectClone[property] = this[property].deepCopy();
    else
        objectClone[property] = this[property];
    return objectClone;
};
*/
Object.deepCopy = function(object) {
    if (object.constructor == Date) {
        var objectClone = new Date(object.valueOf());
        return objectClone;
    }
    var objectClone = new object.constructor();
    for (var property in object)
    if (typeof(object[property]) == 'object' && object[property] != null)
        objectClone[property] = Object.deepCopy(object[property]);
    else
        objectClone[property] = object[property];
    return objectClone;
};

/**
 * Pro dany element nastavi text, ktery se objevi po najeti (Helper/Tooltip)
 */
Element.Methods.setTooltip =
	function(element, content) {
		if (!(element = $(element))) return;
		element.helperId = previoHelper.runAsObserver(element, content);

		return element;
	};

//detekce typu browseru v prototype
Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6;
Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 7;
Prototype.Browser.IE8 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 8;
Prototype.Browser.IE9 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 9;



Element.addMethods({

    /**
	 * Prohozeni dvou Elementu
	 * @param {Element} element1
	 * @param {Element} element2
	 * @return {Element} prvni element
	 */
	swap: function(element1, element2) {
		element1 = $(element1);
		element2 = $(element2);

		if (element1 == element2) return element1;

		var clone = element2.cloneNode(false); // no need to clone deep
		Element.replace(element1, clone);
		Element.replace(element2, element1);
		Element.replace(clone, element2); // make sure references (like event observers) are kept
		return element1;
	}
});

/* http://dandean.com/category/code/2009/hatin-on-textcontent-and-innertext/ */
Element.addMethods({

    /**
     *  Element#getTextContent(@element) -> String
     *  Cross-browser means of getting Element#textContent or Element#innerText
     */
    getTextContent: function(element) {
        if (!Object.isUndefined(element.textContent)) {
            return element.textContent;
        }
        return element.innerText;
    }
});



/* FIX pro CONSOLE.LOG mimo Firefox - odkomentovat, pokud budete potrebovat treba v IE */
/*if (!window.console && MODE == 3) {// DEV verze
	var console = {
		init : function() {
			console.d = new Element("div", {
				style: "position:fixed; z-index: 1000; bottom:0; left:0; width:98%; height: 60px; overflow: auto; border:1px solid #999; font-family:courier,monospace; background:#eee; font-size:7px; padding:5px;"
			});
			document.body.appendChild(console.d);
			var a = new Element("a", {
				style: "float:right; padding-left:1em; padding-bottom:.5em; text-align:right;"
			} );
			a.href = 'javascript:console.hide()';
			a.innerHTML = 'close';
			console.d.appendChild(a);
			var a = document.createElement('a');
			a.href = 'javascript:console.clear();';
			a.innerHTML = 'clear';
			console.d.appendChild(a);
			var id = 'IEconsole';
			if (!document.getElementById(id)) {
				console.d.id = id;
			}
			console.hide();
		},
		hide : function() {
			console.d.style.display = 'none';
		},
		show : function() {
			console.d.style.display = 'block';
		},
		log : function(o) {
			console.d.innerHTML += '<br/>' + o;
			console.show();
		},
		clear : function() {
			console.d.parentNode.removeChild(console.d);
			console.init();
			console.show();
		},
		addLoadEvent : function(func) {
			var oldonload = window.onload;
			if (typeof window.onload != 'function') {
				window.onload = func;
			} else {
				window.onload = function() {
					if (oldonload) {
						oldonload();
					}
					func();
				}
			}
			;
		}
	};
	console.addLoadEvent(console.init);
}*/

