var U={

        ////////////////////////////////////////////////////////////////////
        // unsorted
        ////////////////////////////////////////////////////////////////////
        newin: function(link){
                if(link && link.href){
                        var newin=window.open(link.href);
                        return false;
                }
        },

        popup: function(url,w,h,hash){
                var hash=(hash || {});
                var name=(hash.name || '_blank');
                if(!(window.screen
                        && window.screen.height
                        && window.screen.height > (h+50)
                        && window.screen.width
                        && window.screen.width > (w+50)
                )){
                        w=(window.screen.width>(w+50))?(w+25):(window.screen.width-50);
                        h=(window.screen.height>(h+50))?(h+25):(window.screen.height-50);
                        hash.s=1;
                }
                var left=(U.getCookie('lastPopupLeft') || 75);
                left=parseInt(left)+ 25;
                if(window.screen && window.screen.width && left+parseInt(w)>window.screen.width)left=50;
                U.setCookie('lastPopupLeft',left);
                var top=(U.getCookie('lastPopupTop') || 75);
                top=parseInt(top)+ 25;
                if(window.screen && window.screen.height && top+parseInt(w)>window.screen.height)top=50;
                U.setCookie('lastPopupTop',top);
                var params='';
                params+='left='+ parseInt(left)+ ',';
                params+='top='+ parseInt(top)+ ',';
                params+='width='+ parseInt(w)+ ',';
                params+='height='+ parseInt(h)+ ',';
                params+='scrollbars='+ (hash.s || hash.scroll || hash.scrollbars || '0')+ ',';
                params+='resizable='+ (hash.r || hash.resize || hash.resizable || '0')+ ',';
                params+='menubar='+ (hash.m || hash.menu || hash.menubar || '0')+ ',';
                //params+='titlebar='+ (hash.titlebar || '0')+ ',';
                params+='toolbar='+ (hash.toolbar || '0')+ ',';
                params+='location='+ (hash.location || '0')+ ',';
                //params+='directories='+ (hash.directories || '0')+ ',';
                //params+='hotkeys='+ (hash.hotkeys || '0')+ ',';
                params+='status='+ (hash.status || '0')+ ',';
                //params+='dependent='+ (hash.dependent || '0')+ ',';
                //if(hash.fullscreen){params+='fullscreen='+ hash.fullscreen+ ',';}
                //params+='channelmode='+ (hash.channelmode || '0');
                //alert(params);
                var win=window.open(url,name,params);
                try{
                        win.focus();
                        return win;
                }catch(e){}
        },

        popimg: function(im,w,h,hash){
                var alt=(hash.a || hash.alt || '');
                var p=(hash.p==1 || hash.print==1)?'onload="window.print()"':'';
                var cc=(hash.cc==1 || hash.clickclose==1)?'onclick="self.close();"':'';
                var bc=(hash.bc==1 || hash.blurclose==1)?'onBlur="self.close()"':'';
                var popimgwin = U.popup('',w,h,hash);
                popimgwin.document.open("text/html");
                popimgwin.document.writeln('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><title>'+alt+'<\/title><style type="text/css" title="">* {padding:0;margin:0;background:#fff;}<\/style><\/head>');
                popimgwin.document.writeln('<body '+bc+' '+p+'><div '+cc+'><img src="'+im+'" width="'+w+'" height="'+h+'" alt="'+alt+'" border="0" align="left" \/><\/div><\/body><\/html>');
                popimgwin.document.close();
                popimgwin.focus();
        },

        props: function(hash){
                var result='';
                for(var i in hash){
                        result+=''+ i+ ': '+ hash[i]+ '\n';
                }
                return result;
        },

        defvar: function(def,data){//возвращает дефолтное значение, если отсутствуют данные
                return (data)?data:def;
        },

        hashToStr: function(hash){//эта функция получает хэш и превращает его в строку
                //если тип параметра object
                if(typeof hash=='object'){
                        //инициализируем результат
                        var result='hash={};';
                        //пробегаем по свойствам
                        for(var i in hash){
                                //собираем результат
                                result+='hash.'+ i+ '="'+ hash[i]+ '";';
                        }
                }
                //делаем escape
                result=escape(result);
                //возвращаем результат
                return result;
        },

        hashFromStr: function(str){//эта функция получает строку и выполняет unescape и eval; используется в паре с hashToStr()
                eval(unescape(str));
                return hash;
        },

        loadBigImage: function(hash){//загружает большое изображение и на время загрузки отображает анимированный гиф процесса загрузки
                //проверяем все ли данные переданы
                if(hash.bigImgBoxId && hash.bigImgSrc && hash.previewId && hash.loaderBgcolor && hash.loaderSrc){
                        //проверяем существуют ли на странице переданные id
                        if(U.gbi(hash.bigImgBoxId) && U.gbi(hash.previewId)){
                                //проверяем загружена ли в браузер картинка анимированного лоадера
                                //если нижеупомянутое действие еще не производилось
                                if(!U.loadBigImage_loaderImage){
                                        //создаем объект Image для лоадера
                                        U.loadBigImage_loaderImage=new Image();
                                        //назначаем src
                                        U.loadBigImage_loaderImage.src=hash.loaderSrc;
                                }
                                //запускаем проверку загрузки лоадера
                                U.loadBigImageTestLoader(U.hashToStr(hash))
                        }
                }
        },

        loadBigImageTestLoader: function(hash){//эта функция нужна для ожидания загрузки картинки лоадера (вызывается из loadBigImage())
                //если загрузка лоадера закончена
                if(U.loadBigImage_loaderImage.complete){
                        //вызываем loadBigImageEnd()
                        U.loadBigImageEnd(hash);
                }else{
                        //иначе еще раз вызываем loadBigImageTestLoader()
                        setTimeout('U.loadBigImageTestLoader("'+ hash+ '")', 100);
                }
        },

        loadBigImageEnd: function(hash){//эта функция запускается после загрузки картинки лоадера и ждет загрузки большого изображения
                //распаковываем наш hash
                var hash=U.hashFromStr(hash);
                //если нижеописанное действие не производилось
                if(!U.loadBigImage_bigImage){
                        //впервые создаем хэш с объектами Image, которые будут хранить все запрошенные загрузки
                        U.loadBigImage_bigImage={};
                }
                //если нижеописанное действие не производилось
                if(!U.loadBigImage_bigImage[hash.previewId]){
                        //создаем новый объект Image для текущей большой картинки (ассоциатором должен быть hash.previewId, поскольку hash.bigImgBoxId может быть общим для многих)
                        U.loadBigImage_bigImage[hash.previewId]=new Image();
                        //определяем ему src
                        U.loadBigImage_bigImage[hash.previewId].src=hash.bigImgSrc;
                }
                //если загрузка большого изображения закончена
                if(U.loadBigImage_bigImage[hash.previewId].complete){
                        //помещаем новое изображение в приготовленное место
                        U.gbi(hash.bigImgBoxId).innerHTML='<img src="'+ U.loadBigImage_bigImage[hash.previewId].src+ '" width="'+ U.loadBigImage_bigImage[hash.previewId].width+ '" height="'+ U.loadBigImage_bigImage[hash.previewId].height+ '" alt="">';
                        //если превьюшка была заменена на лоадер
                        if(U.loadBigImage_bigImage[hash.previewId].loaderElement){
                                //делаем на лоадер ссылку для упрощения кода
                                var loader=U.loadBigImage_bigImage[hash.previewId].loaderElement;
                                //заменяем лоадер на превьюшку
                                loader.parentNode.replaceChild(U.loadBigImage_bigImage[hash.previewId].previewElement, loader);
                                //удаляем объект лоадера, он больше не понадобится, поскольку изображение есть в кэше
                                U.loadBigImage_bigImage[hash.previewId].loaderElement=null;
                        }
                        //если был передан код на исполнение, исполняем его
                        if(hash.functionToRun){eval(hash.functionToRun);}
                        //завершаем работу
                        return;
                }else{
                        //иначе
                        if(!preview){
                                //делаем ссылку на превьюшку
                                var preview=U.gbi(hash.previewId);
                        }
                        //если нижеописанное действие не производилось
                        if(!U.loadBigImage_bigImage[hash.previewId].loaderElement){
                                //создаем элемент картинки загрузчика
                                U.loadBigImage_bigImage[hash.previewId].loaderElement=document.createElement('IMG');
                                //делаем на этот элемент ссылку для упрощения кода
                                var loader=U.loadBigImage_bigImage[hash.previewId].loaderElement;
                                //устанавливаем загрузчику основные атрибуты
                                loader.setAttribute('src',U.loadBigImage_loaderImage.src);
                                loader.setAttribute('width',U.loadBigImage_loaderImage.width);
                                loader.setAttribute('height',U.loadBigImage_loaderImage.height);
                                //определяем его будущие позицию, родителя и отступы (которые будут сделаны с помощью бордеров с нужным цветом)
                                var borderLeft=parseInt((preview.offsetWidth-loader.width)/2);
                                var borderRight=preview.offsetWidth-loader.width-borderLeft;
                                var borderTop=parseInt((preview.offsetHeight-loader.height)/2);
                                var borderBottom=preview.offsetHeight-loader.height-borderTop;
                                var top=preview.offsetTop;
                                var left=preview.offsetLeft;
                                //устанавливаем стили
                                loader.style.position='relative';
                                loader.style.zIndex=999;
                                loader.style.borderColor=hash.loaderBgcolor;
                                loader.style.borderTopWidth=borderTop+ 'px';
                                loader.style.borderRightWidth=borderRight+ 'px';
                                loader.style.borderBottomWidth=borderBottom+ 'px';
                                loader.style.borderLeftWidth=borderLeft+ 'px';
                                //дублируем старую певьюшку перед тем как удалить ее из кода страницы
                                U.loadBigImage_bigImage[hash.previewId].previewElement=preview;
                                //заменяем превьюшку на лоадер
                                preview.parentNode.replaceChild(loader, preview);
                        }
                        //еще раз вызываем loadBigImageEnd()
                        setTimeout('U.loadBigImageTestLoader("'+ U.hashToStr(hash)+ '")', 100);
                }
        },

        scrollBottom: function(node){
                node.scrollTop=node.scrollHeight;
        },

        sboxSelect: function(sbox,value){
                if(sbox && sbox.options){
                        var ops=sbox.options;
                        for(var i=0; i<ops.length; i++){
                                if(ops[i].value==value){
                                        ops.selectedIndex=i;
                                        break;
                                }
                        }
                }
        },

        sboxValue: function(sbox){
                var index=sbox.options.selectedIndex;
                var current=sbox.options[index].value;
                return current;
        },

        sboxText: function(sbox){
                var index=sbox.options.selectedIndex;
                var text=sbox.options[index].text;
                return text;
        },

        playFLV: function(flv,w,h,eI){//четвертым параметром может быть id элемента,
                //в который нужно установить проигрыватель, иначе будет открыто новое окно
                if(eI){
                        var FO = { movie:'/admin/fw/js/flvplayer.swf', width:w, height:h, majorversion:7, build:0, bgcolor:'#ffffff', flashvars:'file='+flv+'&showdigits=true&autostart=true&showfsbutton=false' };
                        UFO.create(FO, eI);
                }else{
                        var flvwin = U.popup('',w,h);
                        flvwin.document.open("text/html");
                        flvwin.document.writeln('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN" "http://www.w3.org/TR/html4/strict.dtd">');
                        flvwin.document.writeln('<html><head><title>'+flv+'<\/title>');
                        flvwin.document.writeln('<script type="text/javascript" src="/admin/fw/js/ufo.js"><\/script>');
                        flvwin.document.writeln('<style type="text/css" title="">* {padding:0;margin:0;background:#fff;}<\/style><\/head>');
                        flvwin.document.writeln('<body><div id="flvDiv"><\/div>');
                        flvwin.document.writeln('<script language="javascript" type="text/javascript">');
                        flvwin.document.writeln('var FO = { movie:"/admin/fw/js/flvplayer.swf", width:'+w+', height:'+h+', majorversion:7, build:0, bgcolor:"#ffffff", flashvars:"file='+flv+'&showdigits=true&autostart=true&showfsbutton=false" };');
                        flvwin.document.writeln('UFO.create(FO, "flvDiv");<\/script>');
                        flvwin.document.writeln('<\/body><\/html>');
                        flvwin.document.close();
                        flvwin.focus();
                }
        },

        aclocal: function(form_id,elem_name,values_arr,regexp_arr){//autocomplete
                var form=U.gbi(form_id);
                var elem=form.elements[elem_name];
                elem.setAttribute('autocomplete','off');
                U.addEvent(elem,'keyup',function(event){return U.aclocalCatchKeyUp(event,form_id,elem_name)});
                U.addEvent(elem,'keydown',function(event){return U.aclocalCatchKeyDown(event,form_id,elem_name)});
                U['aclocal#'+form_id+'~'+elem_name]={
                        'values_arr': values_arr,
                        //если массив regexp_arr не был передан, определяем свой массив из двух регулярок,
                        //позволяющих найти строку, которая содержит набираемое слово (независимо от порядкового номера слова)
                        'regexp_arr': (regexp_arr || [function(str){return new RegExp('^'+str,'i')},function(str){return new RegExp('\\s'+str,'i')}]),
                        'start_str': null,
                        'likes': null,
                        'current_link': 0
                };
        },

        aclocalCatchKeyUp: function(event,form_id,elem_name){
                if(event.keyCode==38 || event.keyCode==40 || event.keyCode==13){return;}
                var str=U.gbi(form_id).elements[elem_name].value;
                U['aclocal#'+form_id+'~'+elem_name].start_str=str;//запоминаем исходное напечатанное

                var likes=U.aclocalLikes(str,form_id,elem_name);

                var ac=U.gbi(form_id+'AutoComplete');
                if(!ac){alert('на странице не определен элемент #'+form_id+'AutoComplete, в котором будут выводится совпадения');}

                if(likes && likes.length){
                        ac.style.width=U.gbi(form_id).elements[elem_name].clientWidth + 'px';
                        ac.innerHTML=U.aclocalLikesCode(likes,form_id,elem_name);
                        U['aclocal#'+form_id+'~'+elem_name].likes=likes;
                        ac.style.display='block';
                }else{
                        ac.style.display='none';
                }

                var current_link=U['aclocal#'+form_id+'~'+elem_name].current_link;
                U.doOutAclocalLink(form_id+'~'+elem_name+'~link'+current_link,true);
        },

        aclocalLikes: function(str,form_id,elem_name){
                var result=[];
                var values_arr=U['aclocal#'+form_id+'~'+elem_name].values_arr;
                if(str!=''){
                        if(values_arr && values_arr.length){
                                for(var i in values_arr){
                                        if(U.aclocalCheckEq(str,form_id,elem_name,values_arr[i])){
                                                result.push(values_arr[i]);
                                        }
                                }
                        }
                }

                return result;
        },

        aclocalCheckEq: function(str,form_id,elem_name,value_to_check){
                var regexp_arr=U['aclocal#'+form_id+'~'+elem_name].regexp_arr;
                var result=false;
                for(var i in regexp_arr){
                        var re=regexp_arr[i](str);
                        if(value_to_check.search(re)>=0){
                                result=true;
                                break;
                        }
                }
                return result;
        },

        aclocalLikesCode: function(likes,form_id,elem_name){
                var result='';
                for(var i in likes){
                        var num=1+parseInt(i);
                        result+='<a id="'+form_id+'~'+elem_name+'~link'+num+'" onmouseover="U.doOverAclocalLink(this.id)" onmouseout="U.doOutAclocalLink(this.id)" href="javascript:U.doSelectAclocalLink(\''+form_id+'~'+elem_name+'~link'+num+'\')">'+likes[i]+'<br></a>';
                }

                return result;
        },

        doOverAclocalLink: function(id,replaceValue){
                var form_id=id.split('~')[0];
                var elem_name=id.split('~')[1];
                var link=U.gbi(id);
                if(link){
                        var current_link=id.split('~')[2].substr(4);
                        U['aclocal#'+form_id+'~'+elem_name].current_link=current_link;
                        link.className='ho';
                        if(replaceValue){
                                U.gbi(form_id).elements[elem_name].value=U['aclocal#'+form_id+'~'+elem_name].likes[current_link-1];
                        }
                }else{
                        U['aclocal#'+form_id+'~'+elem_name].current_link=0;
                }
        },

        doOutAclocalLink: function(id,replaceValue){
                var link=U.gbi(id);
                var form_id=id.split('~')[0];
                var elem_name=id.split('~')[1];
                if(link){
                        U.gbi(id).className='';
                        U['aclocal#'+form_id+'~'+elem_name].current_link=0;
                        if(replaceValue){
                                U.gbi(form_id).elements[elem_name].value=U['aclocal#'+form_id+'~'+elem_name].start_str;
                        }
                }
        },

        doSelectAclocalLink: function(id){
                var form_id=id.split('~')[0];
                U.gbi(form_id+'AutoComplete').style.display='none';
                var elem_name=id.split('~')[1];
                var likes=U['aclocal#'+form_id+'~'+elem_name].likes;
                var current_link=parseInt(U['aclocal#'+form_id+'~'+elem_name].current_link);
                var value=likes[current_link-1];
                console.log('value is '+value);
                U.gbi(form_id).elements[elem_name].value=value;
                U.gbi(form_id).submit();
        },

        aclocalCatchKeyDown: function(event,form_id,elem_name){
                if(U['aclocal#'+form_id+'~'+elem_name].current_link > 0){
                        var current_link=parseInt(U['aclocal#'+form_id+'~'+elem_name].current_link);
                }

                if(event.ctrlKey==13 && current_link){
                        U.doSelectAclocalLink(form_id+'~'+elem_name+'~link'+current_link);
                        U.stopEvent(event);
                }//else if(event.ctrlKey || event.altKey || event.shiftKey){return;}

                if(event.keyCode==40 || event.keyCode==38){
                        var likes=U['aclocal#'+form_id+'~'+elem_name].likes;

                        if( !current_link ){
                                var current_link=(event.keyCode==40) ? 1 : likes.length;
                        }else{
                                U.doOutAclocalLink(form_id+'~'+elem_name+'~link'+current_link,true);
                                if(event.keyCode==40 && (current_link < likes.length)){
                                        current_link+=1;
                                }else if(event.keyCode==38 && (current_link > 1)){
                                        current_link-=1;
                                }else{
                                        current_link=0;
                                }
                        }

                        U.doOverAclocalLink(form_id+'~'+elem_name+'~link'+current_link,true);
                        U.stopEvent(event);
                }
        },

        ////////////////////////////////////////////////////////////////////
        // tests
        ////////////////////////////////////////////////////////////////////
        isfirst: function(){//
                return (location.pathname=='/' || location.pathname=='/index.html');
        },

        ispda: function(){
                if(window.top && window.top.screen && window.top.screen.width){
                        return window.top.screen.width<640;
                }else{
                        return true;
                }
        },

        isajax: function(){
                var result=false;
                try{
                        var req=new JsHttpRequest();
                        result=(typeof req=='object');
                }catch(e){}
                return result;
        },

        ////////////////////////////////////////////////////////////////////
        // cookies
        ////////////////////////////////////////////////////////////////////
        setCookie: function(cookieName,cookieContent,cookieExpireTime){
                if(cookieExpireTime>0){
                        var expDate=new Date();
                        expDate.setTime(expDate.getTime()+cookieExpireTime*1000*60*60);
                        var expires=expDate.toGMTString();
                        document.cookie=cookieName+"="+escape(cookieContent)+"; path="+escape('/')+"; expires="+expires;
                }else{
                        document.cookie=cookieName+"="+escape(cookieContent)+"; path="+escape('/')+"";
                }
        },

        getCookie: function(cookieName){
                var ourCookie=document.cookie;
                if(!ourCookie || ourCookie=="")return "";
                        ourCookie=ourCookie.split(";");
                var i=0;
                var Cookie;
                while(i<ourCookie.length){
                        Cookie=ourCookie[i].split("=")[0];
                        if(Cookie.charAt(0)==" ")
                                Cookie=Cookie.substring(1);
                        if(Cookie==cookieName){
                                return unescape(ourCookie[i].split("=")[1]);
                        }
                        i++;
                }
                return ""
        },


        ////////////////////////////////////////////////////////////////////
        // events
        ////////////////////////////////////////////////////////////////////
        addEvent: function(node,event,func){
                if(!node)return;
                if(node.addEventListener){
                        node.addEventListener(event,func,false);
                }else{
                        if(node.attachEvent){
                                event='on'+event;
                                node.attachEvent(event,func);
                        }
                }
        },

        removeEvent: function(node,event,func){
                if(!node)return;
                if(node.addEventListener){
                        node.removeEventListener(event,func,false);
                }else{
                        if(node.detachEvent){
                                event='on'+event;
                                node.detachEvent(event,func);
                        }
                }
        },

        stopEvent: function(event){
                event.cancelBubble = true; //отключить бег события выше для ИЕ
                event.returnValue = false; //отключить стандартное действие
                //то же самое для Мозиллы
                if(event.preventDefault) event.preventDefault();
                if(event.stopPropagation) event.stopPropagation();
        },

        tryUntil: function(function2run,testCondition){
                var testCondition=unescape(testCondition);
                var function2run=unescape(function2run);
                if(eval(testCondition)){
                        try{
                                eval(function2run);
                        }catch(e){/*поскольку событие было отложено, возможно что к моменту реализации функция уже перестанет существовать*/}
                }else{
                        var date=new Date();
                        var mls=parseInt(arguments[2] || 100);
                        setTimeout('U.tryUntil("'+ escape(function2run)+ '","'+ escape(testCondition)+ '",'+ mls+ ')',mls);
                }
        },

        clientX: function(){//определяем координату мыши по X
                return U.clientXY()[0];
        },

        clientY: function(){//определяем координату мыши по Y
                return U.clientXY()[1];
        },

        clientTarget: function(){//определяем элемент под мышью
                return U.clientXY()[2];
        },

        clientXY: function(evt){//возвращает координаты мыши
                if(evt){//автовызов, инициированный обработчиком событий
                        U.clientXY_x=evt.clientX;
                        U.clientXY_y=evt.clientY;
                        U.clientXY_target=(evt.target)?evt.target:evt.srcElement;
                }else{//вызвал программист
                        if(typeof U.clientXY_x=='undefined'){
                                U.clientXY_x=0;
                                U.clientXY_y=0;
                                U.clientXY_target=null;
                                U.addEvent(document,'mousemove',U.clientXY);
                        }
                        return [U.clientXY_x,U.clientXY_y,U.clientXY_target];
                }
        },

        ctrlEnter: function(event){//отслеживает нажатие ctrl Enter
                if(event.keyCode==13 && event.ctrlKey){
                        return true;
                }
                return false;
        },

        ////////////////////////////////////////////////////////////////////
        // string
        ////////////////////////////////////////////////////////////////////

        splitText: function(str,step){
                var step=step||1;
                var tmpArr=[];
                var result=[];
                var tmp, symb;
                for(var i=0; i<str.length; i++){
                        symb=str.substr(i,1);
                        if(symb=='&' && str.substr(i).indexOf(';')){
                                tmp='&';
                                do{
                                        i++;
                                        symb=str.substr(i,1);
                                        tmp+=symb;
                                }while(symb && symb!=';');
                                tmpArr.push(tmp);
                        }else{
                                if(symb=='<' && str.substr(i).indexOf('>')){
                                        tmp='<';
                                        do{
                                                i++;
                                                symb=str.substr(i,1);
                                                tmp+=symb;
                                        }while(symb && symb!='>');
                                        tmpArr.push(tmp);
                                }else{
                                        tmpArr.push(symb);
                                }
                        }
                }
                if(step==1)return tmpArr;
                for(var i=0; i<tmpArr.length; i+=step){
                        tmp='';
                        for(var j=0; j<step; j++){
                                tmp+=tmpArr[i+j]||'';
                        }
                        result.push(tmp);
                }
                return result;
        },

        trim: function(str){
                var result=str;
                result=result.replace(/^[\s]+/,'');
                result=result.replace(/[\s]+$/,'');
                return result;
        },

        validateEmail: function(email){
                var result=email.search(/^[^@\s]+@[^@\s]+\.[^@\s]{2,}$/);
                result=(result==0)?true:false;
                return result;
        },

        ////////////////////////////////////////////////////////////////////
        // DOM
        ////////////////////////////////////////////////////////////////////

        append: function(parent_or_id,child){
                try{
                        var parent=(typeof parent_or_id=='string')?U.gbi(parent_or_id):parent_or_id;
                        parent.appendChild(child);
                        if(navigator.appName=='Microsoft Internet Explorer'){
                                parent.innerHTML+='';
                        }
                }
                catch(e){/*alert(e)*/}
        },

        insert: function(parent_or_id,child,ref_or_id){
                try{
                        var parent=(typeof parent_or_id=='string')?U.gbi(parent_or_id):parent_or_id;
                        var ref=(typeof ref_or_id=='string')?U.gbi(ref_or_id):ref_or_id;
                        parent.insertBefore(child,ref);
                        if(navigator.appName=='Microsoft Internet Explorer'){
                                parent.innerHTML+='';
                        }
                }
                catch(e){/*alert(e)*/}
        },

        rmv: function(elem_or_id){
                try{
                        if(typeof elem_or_id=='string'){
                                var elem=U.gbi(elem_or_id);
                        }else{
                                var elem=elem_or_id;
                        }
                        var parent=elem.parentNode;
                        parent.removeChild(elem);

                        return true;
                 }
                catch(e){alert('cant remove element: '+elem_or_id);}
        },

        gbi: function(id){
                return document.getElementById(id);
        },

        gbt: function(tagname,elem_or_id){
                var parent=(elem_or_id)?
                        (typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id
                        :document;
                var result=parent.getElementsByTagName(tagname);
                if(result && result.length){
                        return result;
                }
        },

        gbtr: function(tagname,elem_or_id){
                var parent=(elem_or_id)?
                        (typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id
                        :document;
                var elem=(typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id;
                U.tags=new Array();
                U.gbtRecursive(tagname,parent);
                var result=U.tags;
                U.tags=null;
                if(result && result.length){
                        return result;
                }
        },

        gbtc: function(tagname,classname,elem_or_id){
                var result=[];
                var parent=(elem_or_id)?
                        (typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id
                        :document;
                var tags=U.gbt(tagname,parent);
                if(tags){
                        for(var i=0; i<tags.length; i++){
                                if(tags[i].className==classname){
                                        result.push(tags[i]);
                                }
                        }
                }
                if(result && result.length){
                        return result;
                }
        },

        gbtcr: function(tagname,classname,elem_or_id){
                var result=[];
                var parent=(elem_or_id)?
                        (typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id
                        :document;
                var tags=U.gbtr(tagname,parent);
                if(tags){
                        for(var i in tags){
                                if(tags[i].className==classname){
                                        result.push(tags[i]);
                                }
                        }
                }
                if(result && result.length){
                        return result;
                }
        },

        gbtRecursive: function(tagname,parent){
                for(var i=0; i<parent.childNodes.length; i++){
                        if(parent.childNodes[i].nodeType==1){
                                if(parent.childNodes[i].tagName==tagname){
                                        U.tags.push(parent.childNodes[i]);
                                }
                                U.gbtRecursive(tagname,parent.childNodes[i]);
                        }
                }
        },

        layerX: function(elem_or_id){//определяем левую координату слоя
                var elem=(typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id;
                return U.layerXY(elem)[0];
        },

        layerY: function(elem_or_id){//определяем верхнюю координату слоя
                var elem=(typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id;
                return U.layerXY(elem)[1];
        },

        layerXY: function(elem_or_id){//определяем обе координаты слоя
                var x=0;
                var y=0;
                var elem=(typeof elem_or_id=='string')?U.gbi(elem_or_id):elem_or_id;
                while(elem){
                        x+=elem.offsetLeft;
                        y+=elem.offsetTop;
                        if(elem.tagName=='BODY'){
                                break;
                        }else{
                                elem=elem.offsetParent;
                                if(elem){
                                        x-=elem.scrollLeft;
                                        y-=elem.scrollTop;
                                }
                        }
                }
                return [x,y];
        },

        showhide: function(id){
                if(U.gbi(id)){
                        if(U.gbi(id).offsetHeight>0){
                                U.gbi(id).style.display='none';
                        }else{
                                U.gbi(id).style.display='block';
                        }
                }
        },

        sh: function(id){
                U.showhide(id);
        },

        bodyTag: function(){
                if(!U.bodyTagElement){
                        U.bodyTagElement=document.getElementsByTagName('BODY')[0];
                }
                return U.bodyTagElement;
        },

        htmlTag: function(){
                if(!U.htmlTagElement){
                        U.htmlTagElement=document.getElementsByTagName('HTML')[0];
                }
                return U.htmlTagElement;
        },

        ////////////////////////////////////////////////////////////////////
        // array
        ////////////////////////////////////////////////////////////////////
        array: {
                find: function(array,value){
                        for(var i=0; i<array.length; i++){
                                if(array[i]==value){
                                        return i;
                                }
                        }
                        return -1;
                },

                remove: function(array,index){
                        array.splice(index,1);
                        return array;
                },

                fr: function(array,value){//fiend then remove
                        var index=U.array.find(array,value);
                        if(index>=0){
                                U.array.remove(array,index);
                        }
                }
        },

        ////////////////////////////////////////////////////////////////////
        // object
        ////////////////////////////////////////////////////////////////////
        object: {
                af: function(obj,hash){//apply fields
                        var fieldsArr=obj._af.split(',');
                        var fieldName='';
                        for(var i in fieldsArr){
                                fieldName=fieldsArr[i];
                                obj[fieldName]=(hash[fieldName]||null);
                        }
                },

                join2str: function(obj){//join fields to a string
                        var fieldsArr=obj._af.split(',');
                        var fieldName='';
                        var result='';
                        for(var i in fieldsArr){
                                fieldName=fieldsArr[i];
                                if(obj[fieldName]!=null){
                                        result+=fieldName+ ':"'+ obj[fieldName]+ '",';
                                }
                        }
                        if(result)result=result.substr(0,result.length-1);
                        return result;
                }
        },

        ////////////////////////////////////////////////////////////////////
        // animation
        ////////////////////////////////////////////////////////////////////
        mouseScroll: function(hash){//осуществляет скроллирование слоя, контролируемое движением мыши
                /*
                        hash имеет следующие поля
                        id - id элемента для скроллирования
                        repeat - способ прокрутки (xy, x, y, no), по умолчанию без прокрутки
                        zone - ограничение зоны чувствительности мыши (xy, x, y, no), по умолчанию без ограничения
                        methodX (methodY) - матем.метод (пока только sin, он же по умолчанию), описывающий движение слоя //kx (ky) - коэфициент ускорения (от 0 до ...) по оси X (Y), по умолчанию 0,  поэтому если не передан, движение не будет осуществляться по данной оси
                */
                this._af='id,repeat,methodX,methodY,presets';
                U.object.af(this,hash);

                var layerid='layer'+ this.id;

                //находим слой для прокрутки
                var layer=U.gbi(this.id);
                //находим родителя
                var parentLayer=layer.parentNode;

                //если это первый вызов
                if(this[layerid]!='object'){
                        this[layerid]={};
                        this._af='id,repeat,methodX,methodY,layer'+ this.id;
                        //у родителя фиксируем ширину, высоту, position и overflow
                        parentLayer.style.width=parentLayer.offsetWidth+ 'px';
                        parentLayer.style.height=parentLayer.offsetHeight+ 'px';
                        parentLayer.style.position='relative';
                        parentLayer.style.overflow='hidden';
                        //теперь у слоя для прокрутки фиксируем position
                        layer.style.position='absolute';
                        //запоминаем некоторые величины
                        this[layerid].layerWidth=layer.offsetWidth;
                        this[layerid].layerHeight=layer.offsetHeight;
                        this[layerid].parentWidth=parentLayer.offsetWidth;
                        this[layerid].parentHeight=parentLayer.offsetHeight;
                        this[layerid].parentLeft=parentLayer.offsetLeft;
                        this[layerid].parentTop=parentLayer.offsetTop;
                }
                //вычисляем смещение
                        //определяем центр родителя
                        var bodyWidth=document.getElementsByTagName('body')[0].offsetWidth;
                        if(this[layerid].centerCoords && this[layerid].bodyWidth && this.bodyWidth==bodyWidth){
                        }else{
                                this[layerid].bodyWidth=bodyWidth;
                                this[layerid].centerCoords=U.layerXY(parentLayer);
                                this[layerid].centerCoords[0]+=parentLayer.offsetWidth/2;
                                this[layerid].centerCoords[1]+=parentLayer.offsetHeight/2;
                        }
                        //определяем шаг
                        var step=[0,0];
                        if(this.methodX!=null)
                                step[0]=-50*Math.sin((U.clientX()/this[layerid].centerCoords[0]-1)*Math.PI/2);
                        if(this.methodY!=null)
                                step[1]=-50*Math.sin((U.clientY()/this[layerid].centerCoords[1]-1)*Math.PI/2);
                //перерисовываем слой
                if(step[0]){
                        var layerLeft=layer.offsetLeft + step[0];
                        if(this.repeat!='x' && this.repeat!='xy'){
                                if(layerLeft+this[layerid].layerWidth < this[layerid].parentWidth)
                                        layerLeft=this[layerid].parentWidth - this[layerid].layerWidth;
                                if(layerLeft > 0)layerLeft=0;
                        }
                        layer.style.left=layerLeft+ 'px';
                }
                if(step[1])
                        var layerTop=layer.offsetTop + step[1];
                        if(this.repeat!='y' && this.repeat!='xy'){
                                if(layerTop+this[layerid].layerHeight < this[layerid].parentHeight)
                                        layerTop=this[layerid].parentHeight - this[layerid].layerHeight;
                                if(layerTop > 0)layerTop=0;
                        }
                        layer.style.top=(layer.offsetTop + step[1])+ 'px';
                //рекурсивно вызываем функцию
                setTimeout('U.mouseScroll({'+ U.object.join2str(this)+ '})',20);
        },

        typewriter: function(id,text,speed,endfunc){//эффект печатной машинки
                /*
                        id - id элемента для применения эффекта
                        text - сам текст, может содержать конечные теги, типа <br>
                        speed - скорость вывода (необязательный параметр)
                        endfunc - строка кода, который будет выполнен по окончании вывода текста
                */

                //получаем текст в виде массива
                var step=U.defvar(1,parseInt(speed));
                var textArr=U.splitText(text,step);
                var arrStr=textArr.join('¬');
                var endfunc=(endfunc!='')?escape(endfunc):'';
                //создаем хэш для таймеров
                if(!U.typewriterTimer){U.typewriterTimer={};}
                //формируем функцию для рекурсивного вызова и запускаем ее
                U.typewriterRec(id,arrStr,endfunc);
        },

        typewriterRec: function(id,arrStr,endfunc,position){
                var textArr=arrStr.split('¬');
                var position=position||0;
                if(position==0){U.gbi(id).innerHTML='';}
                if(position<textArr.length && U.gbi(id)){
                        //определяем очередную порцию текста
                        var textPortion=textArr[position];
                        //меняем пробелы на табуляцию, чтобы пробелы не проглатывались маками
                        textPortion=textPortion.replace(/ /g, '&#9;');
                        //в уже напечатанном тексте делаем обратную замену
                        var textExisted=U.gbi(id).innerHTML
                        textExisted=textExisted.replace(/&#9;/g, ' ');
                        //добавляем очередную порцию текста
                        U.gbi(id).innerHTML=textExisted+ textPortion;
                        position++;
                        U.typewriterTimer[id]=setTimeout('U.typewriterRec("'+ id+ '","'+ arrStr+ '","'+ endfunc+ '","'+ position+ '")',25);
                }else{
                        var endfunc=unescape(endfunc);
                        eval(endfunc);
                }
        }
}

