try{
    console.log('q');
}catch(e){
    console={
	log:function(s){

//	    var currentFunction = arguments.callee.caller;
	    var callstack=[];
/*	    while (currentFunction) {
		var fn = currentFunction.toString();
		var fname = fn.substring(fn.indexOf("function") + 8, fn.indexOf("(")) || "anonymous";
		callstack.push(fname);
		currentFunction = currentFunction.caller;
	    }
*/
	    if(s.message){
//		alert(s.message+"\n--\n"+callstack.join("\n"));
	    }else{
		// alert(s);
	    }
	}
    }
}


function __cmp__(s1, s2){
    if (s1==s2) return 0;
    if (s1 < s2) return -1;
    return 1;
}
function appendAuth(url){
    ret=url;
    var rand=Math.round(Math.random()*100000);
    if(SESSION_ID){
        ret += 'sid='+SESSION_ID+'&';
    }
    ret+='random='+rand;
    return ret;
}
function getUpdateUrl(url_handler){
    var ret= $_URLS[url_handler];
    var rand=Math.round(Math.random()*100000);
    if(!ret){
        return false;
    }
    ret+='?';
    if(SESSION_ID){
        ret += 'sid='+SESSION_ID+'&';
    }
    ret+='random='+rand;
    return ret;
}

Date.prototype.formatDate = function(format)
{
    var date = this;
    if (!format)
        format="MM/dd/yyyy";
    var month = date.getMonth() + 1;
    var year = date.getFullYear();
    format = format.replace("MM",month.toString().padL(2,"0"));
    if (format.indexOf("yyyy") > -1)
            format = format.replace("yyyy",year.toString());
    else if (format.indexOf("yy") > -1)
            format = format.replace("yy",year.toString().substr(2,2));
    format = format.replace("dd",date.getDate().toString().padL(2,"0"));
    var hours = date.getHours();
    if (format.indexOf("t") > -1)
    {
        if (hours > 11)
            format = format.replace("t","pm")
        else
            format = format.replace("t","am")
    }
    if (format.indexOf("HH") > -1)
            format = format.replace("HH",hours.toString().padL(2,"0"));
    if (format.indexOf("hh") > -1) {
            if (hours > 12) hours - 12;
            if (hours == 0) hours = 12;
                    format = format.replace("hh",hours.toString().padL(2,"0"));
            }
    if (format.indexOf("mm") > -1)
            format = format.replace("mm",date.getMinutes().toString().padL(2,"0"));
    if (format.indexOf("ss") > -1)
            format = format.replace("ss",date.getSeconds().toString().padL(2,"0"));
    return format;
}


String.repeat = function(chr,count)
{
    var str = "";
    for(var x=0;x<count;x++) {str += chr};
    return str;
}

String.prototype.padL = function(width,pad)
{
    if (!width ||width<1)
        return this;
    if (!pad) pad=" ";
    var length = width - this.length
    if (length < 1) return this.substr(0,width);
    return (String.repeat(pad,length) + this).substr(0,width);
}

String.prototype.padR = function(width,pad)
{
    if (!width || width<1)
        return this;
    if (!pad) pad=" ";
    var length = width - this.length
    if (length < 1) this.substr(0,width);
    return (this + String.repeat(pad,length)).substr(0,width);
}


String.prototype.tagReplace = function(tag,outtag)
{
    if(!outtag) outtag=tag
    return this.replaceAll('['+tag+']','<'+outtag+'>',true).replaceAll('[/'+tag+']','</'+outtag+'>',true)
}

String.prototype.replaceAll = function(
    strTarget, // The substring you want to replace
    strSubString, // The string you want to replace in.
    caseSensitive
){
    var strText = this;
    var intIndexOfMatch;
    
    if(caseSensitive){
        strTarget=strTarget.toLowerCase()
    }
    intIndexOfMatch = strText.indexOf( strTarget );
    // Keep looping while an instance of the target string
    // still exists in the string.
    while (intIndexOfMatch != -1){
	// Relace out the current instance.
	    strText = strText.replace( strTarget, strSubString )
	
	// Get the index of any next matching substring.
    	intIndexOfMatch = strText.indexOf( strTarget );
    }
    
    if(caseSensitive){
        strTarget=strTarget.toUpperCase();
        intIndexOfMatch = strText.indexOf( strTarget );
        // Keep looping while an instance of the target string
        // still exists in the string.
        while (intIndexOfMatch != -1){
    	// Relace out the current instance.
    	strText = strText.replace( strTarget, strSubString )
    	
    	// Get the index of any next matching substring.
    	intIndexOfMatch = strText.indexOf( strTarget );
        }
    }
    
    // Return the updated string with ALL the target strings
    // replaced out with the new substring.
    return( strText );
}


Element.addMethods({
    onmouseenter: function(element,observer) {
        element = $(element);
        element.observe('mouseover',
                        function(evt,currentTarget) {
                            var relatedTarget = $(evt.relatedTarget || evt.fromElement);
                            if( relatedTarget!=currentTarget && relatedTarget.childOf(currentTarget)==false)
                                observer(element);
                        }.bindAsEventListener({},element));
        return element;
    },
    onmouseleave: function(element,observer) {
        element = $(element);
        element.observe('mouseout',
                        function(evt,currentTarget) {
                            var relatedTarget = $(evt.relatedTarget || evt.toElement);
                            if(!relatedTarget || !$(relatedTarget)){
                                return;
                            }
                            if(relatedTarget!=currentTarget && $(relatedTarget).childOf(currentTarget)==false )
                                observer(element);
                        }.bindAsEventListener({},element));
        return element;
    }
});




// Работа с выделениями, иначе пиздец

var textAreaSelectionObjects = [];
// Получаем экземпляр объекта
function getTextAreaSelection(id) {
    if (typeof(textAreaSelectionObjects[id]) == "undefined") {
        textAreaSelectionObjects[id] = new textAreaSelectionHelper(id);
    }
    return textAreaSelectionObjects[id];
}
// Конструктор, принимает в качестве аргумента ID текстарии
function textAreaSelectionHelper(id) {
    var obj = document.getElementById(id);
    this.target = obj;
    // Создаем свойства carretHandler для доступа к объекту в контексте узла
    // из обработчиков событий
    this.target.carretHandler = this;
    // Добавляем обработчик событий

    Event.observe(this.target,'change',_textareaSaver)
    Event.observe(this.target,'click',_textareaSaver)
    Event.observe(this.target,'keyup',_textareaSaver)
    Event.observe(this.target,'focus',_textareaSaver)

    // this.target.onchange = _textareaSaver;
    // this.target.onclick = _textareaSaver;
    // this.target.onkeyup = _textareaSaver;
    // this.target.onfocus = _textareaSaver;
    if(document.attachEvent) this.target.onselect = _textareaSaver;
    // Свойства для запоминания позиции выделения
    this.start=-1;
    this.end=-1;
    this.scroll=-1;
    this.iesel=null;
}
// В прототип записываем методы
textAreaSelectionHelper.prototype = {
    // Получим выделение
    getSelectedText : function() {
        return this.iesel? this.iesel.text: (this.start>=0&&this.end>this.start)? this.target.value.substring(this.start,this.end): "";
    },
    // Установим текстовые фрагменты до выделения - text
    // и после него, если нужно - secondtag
    setSelectedText : function(text, secondtag) {
        if (this.iesel) {
            if (typeof(secondtag) == "string") {
                var l = this.iesel.text.length;
                this.iesel.text = text + this.iesel.text + secondtag;
                this.iesel.moveEnd("character", -secondtag.length);
                this.iesel.moveStart("character", -l);   
            } else {
                this.iesel.text = text;
            }
            this.iesel.select();
        } else if (this.start >= 0 && this.end >= this.start) {
            var left = this.target.value.substring(0, this.start);
            var right = this.target.value.substr(this.end);
            var scont = this.target.value.substring(this.start, this.end);
            if (typeof(secondtag) == "string") {
                this.target.value = left + text + scont + secondtag + right;
                this.end = this.target.selectionEnd=this.start+text.length+scont.length;
                this.start = this.target.selectionStart = this.start + text.length;    
            } else {
                this.target.value = left + text + right;
                this.end = this.target.selectionEnd = this.start + text.length;
                this.start = this.target.selectionStart = this.start + text.length;
            }
            this.target.focus();
	    var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
	    is_chrome  = is_chrome || (navigator.userAgent.toLowerCase().indexOf('iron/') > -1);
	    if(is_chrome){
                this.end = this.target.selectionEnd=this.target.value.length;
                this.start = this.target.selectionStart = this.target.value.length;
	    } else {
		left = this.target.value.substring(0, this.start);
		right = this.target.value.substr(this.end);
		scont = this.target.value.substring(this.start, this.end);
	    }

            this.target.scrollTop = this.scroll;
        } else {
            this.target.value += text + ((typeof(secondtag) == "string") ? secondtag: "");
            if (this.scroll >= 0) this.target.scrollTop = this.scroll;
        }
    }
};
// Обработчик событий. Занимается сохранением информации о выделении и позиции скролла
function _textareaSaver() {
    if(document.selection) {
        this.carretHandler.iesel = document.selection.createRange().duplicate();
    } else if(typeof(this.selectionStart) != "undefined") {
	// alert("start = "+this.carretHandler.start);
        this.carretHandler.start = this.selectionStart;
        this.carretHandler.end = this.selectionEnd;
        this.carretHandler.scroll = this.scrollTop;
    } else {
        this.carretHandler.start = this.carretHandler.end = -1;
    }
}

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}



function expandableMenu(id, timeout){
    var el = $(id);
    if(!el) return;
    var _over=function(event){
	$$('li.open').each(function(el){el.className='';});
	el.className="open";
	if(el.to){
	    window.clearTimeout(el.to);
	    el.to=null;
	}
    }

    var _out=function(event){
	if(el.to){
	    window.clearTimeout(el.to);
	    el.to=null;
	}
	el.to=window.setTimeout(function(){
	    el.className='';
	},timeout*1000);
    }

    el.onmouseover=_over;
    el.onmouseout= _out;
    el.onclick = function(){
	if(el.to){
	    window.clearTimeout(el.to);
	    el.to=null;
	}
	// alert(el);
	if(el.className == 'open'){
	    el.className='';
	}else{
	    el.className='open';
	}	    
	// alert('done');
	return false;
    };
}


function createCookie(name,value,days) {
    if (days) {
	var date = new Date();
	date.setTime(date.getTime()+(days*24*60*60*1000));
	var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}


function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
	var c = ca[i];
	while (c.charAt(0)==' ') c = c.substring(1,c.length);
	if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function eraseCookie(name) {
    createCookie(name,"",-1);
}


function addslashes( str ) {
    return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
}


function get_html_translation_table (table, quote_style) {
    // Returns the internal translation table used by htmlspecialchars and htmlentities  
    // 
    // version: 908.406
    // discuss at: http://phpjs.org/functions/get_html_translation_table
    // +   original by: Philip Peterson
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: noname
    // +   bugfixed by: Alex
    // +   bugfixed by: Marco
    // +   bugfixed by: madipta
    // +   improved by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Frank Forte
    // +   bugfixed by: T.Wild
    // +      input by: Ratheous
    // %          note: It has been decided that we're not going to add global
    // %          note: dependencies to php.js, meaning the constants are not
    // %          note: real constants, but strings instead. Integers are also supported if someone
    // %          note: chooses to create the constants themselves.
    // *     example 1: get_html_translation_table('HTML_SPECIALCHARS');
    // *     returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
    
    var entities = {}, hash_map = {}, decimal = 0, symbol = '';
    var constMappingTable = {}, constMappingQuoteStyle = {};
    var useTable = {}, useQuoteStyle = {};
    
    // Translate arguments
    constMappingTable[0]      = 'HTML_SPECIALCHARS';
    constMappingTable[1]      = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';

    useTable       = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';

    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: "+useTable+' not supported');
        // return false;
    }

    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }

    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';


    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }
    
    return hash_map;
}

function htmlspecialchars (string, quote_style) {
    // http://kevin.vanzonneveld.net
    // +   original by: Mirek Slugen
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Nathan
    // +   bugfixed by: Arno
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Ratheous
    // -    depends on: get_html_translation_table
    // *     example 1: htmlspecialchars("<a href='test'>Test</a>", 'ENT_QUOTES');
    // *     returns 1: '&lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;'
 
    var hash_map = {}, symbol = '', tmp_str = '', entity = '';
    tmp_str = string.toString();
    
    if (false === (hash_map = get_html_translation_table('HTML_SPECIALCHARS', quote_style))) {
        return false;
    }
    
    hash_map["'"] = '&#039;';
    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(symbol).join(entity);
    }
    
    return tmp_str;
}


function clone(obj){
    if(obj == null || typeof(obj) != 'object')
        return obj;
    var temp = new obj.constructor(); // changed (twice)
    for(var key in obj)
        temp[key] = clone(obj[key]);
    return temp;

}
