//---------------------------------------------------------------------------------
// PCL's Speckled Band Engine 0.2 RC3
// JavaScript Integrator
// http://www.manhunter.ru
// Build date: 08.09.2010
//---------------------------------------------------------------------------------

//---------------------------------------------------------------------------------
// Bender JavaScript Framework 1.2.12.0
// Copyright (C) ManHunter / PCL
// http://www.manhunter.ru
//---------------------------------------------------------------------------------
// У меня будет свой фреймворк JavaScript, с блэкджеком и шлюхами!
//---------------------------------------------------------------------------------

// Вспомогательная функция для инициализации фреймворка
function extend() {
    if (arguments.length==1) {
        var newMethods=arguments[0];
        for (var newMethod in newMethods) {
            if (typeof Element!='undefined') {
                Element.prototype[newMethod]=newMethods[newMethod];
            }
            Object.prototype[newMethod]=newMethods[newMethod];
        }
    }
    else {
        var newMethods=arguments[1];
        var objTarget=arguments[0];
        for (var newMethod in newMethods) {
            objTarget.prototype[newMethod]=newMethods[newMethod];
        }
    }
}

//---------------------------------------------------------------------------------
// Функция подавления штатного действия браузера на событие
//---------------------------------------------------------------------------------
function cancelEvent(e) {
    e = e ? e : window.event;
    if (e.stopPropagation) {
        e.stopPropagation();
    }
    if (e.preventDefault) {
        e.preventDefault();
    }
    e.cancelBubble = true;
    e.cancel = true;
    e.returnValue = false;
    return false;
}

//---------------------------------------------------------------------------------
// Функция определения браузера IE
//---------------------------------------------------------------------------------
function isIE() {
    return ("\v"=="v");
}

//---------------------------------------------------------------------------------
// Функция проверки строки на соответствие шаблону email
//---------------------------------------------------------------------------------
function isEmail(str) {
    return ((/^([-a-z0-9_\.])+\@([a-z0-9][-a-z0-9]*\.){1,}[a-z]{2,}$/i).test(str.trim()));
}

//---------------------------------------------------------------------------------
// Получение объекта или списка объектов
// По id возвращается отдельный элемент, по тегам или классу
// всегда возвращается массив
//---------------------------------------------------------------------------------
function $() {
    // Если ничего не передано, то вернуть false
    if (arguments.length == 0) { return false; }

    // Родительский элемент
    var p=document;
    if (!(this=='[object Window]' || this=='[object DOMWindow]')) {
        p=this;
    }

    // Массив элементов
    var elements = new Array;
    var only_one=false;

    for (var i=0; i<arguments.length; i++) {
        var element_type=arguments[i];
        if (typeof element_type=='string') {
            // #id
            if (element_type.charAt(0)=='#') {
                var element = p.getElementById(element_type.substring(1));
                if (element) {
                    elements.push(element);
                    only_one=true;
                }
            }
            // .class
            else if (element_type.charAt(0)=='.') {
                var tags=p.getElementsByTagName('*');
                var pattern = new RegExp("(^|\\s)"+element_type.substring(1)+"(\\s|$)");

                if (tags.length) {
                    for (var j=0; j<tags.length; j++) {
                        if (pattern.test(tags[j].className)) {
                            elements.push(tags[j]);
                        }
                    }
                }
            }
            // tags
            else {
                var tags=p.getElementsByTagName(element_type);
                if (tags.length) {
                    for (var j=0; j<tags.length; j++) {
                        elements.push(tags[j]);
                    }
                }
            }
        }
        // element
        else if (typeof element_type=='object') {
            elements.push(element_type);
            if (element_type!=document) {
                only_one=true;
            }
        }
    }

    // Если не найдено ни одного элемента, то вернуть false
    if (elements.length==0) {
        return false;
    }
    else {
        if (elements.length==1 && only_one) {
            return elements[0];
        }
        else {
            return elements;
        }
    }
}

//---------------------------------------------------------------------------------
// Метод 'object.html'
// Получение или установка содержимого элемента или элементов
//---------------------------------------------------------------------------------
// Вызов без параметров - получение содержимого элементов
// Параметр (string) - установка содержимого элементов
//---------------------------------------------------------------------------------
function html() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }
    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (arguments.length == 0) {
                return el.innerHTML;
            }
            else {
                // Таблицы под IE не меняются
                if (!(isIE() && el=='[object HTMLTableElement]')) {
                    el.innerHTML = arguments[0];
                    el.css('height','auto');
                }
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.css'
// Получение или установка стилей элемента или элементов
//---------------------------------------------------------------------------------
// Вызов без параметров - получение стиля элементa
// Параметр (string) - установка стиля элементов
//---------------------------------------------------------------------------------
function css() {
    if (typeof this!='object') { return this; }
    if (arguments.length == 0) { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }

    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            // Установка атрибутов
            if (arguments.length > 1) {
                el.style[arguments[0]] = arguments[1];
            }
            // Получение атрибутов
            else {
                return el.style[arguments[0]];
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.fade'
// Плавное затухание или появление элемента
//---------------------------------------------------------------------------------
// Параметром передается задержка тип (0 - затухание, 1 - появление) и
// пауза между итерациями в милисекундах (по умолчанию значение = 50)
//---------------------------------------------------------------------------------
function fade() {
    if (typeof this!='object') { return this; }
    if (arguments.length == 0) { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }

    var speed=(arguments[1]-0);
    if (isNaN(speed) || speed<1) { speed=50; }

    var op=0;
    var stop=1.1;
    var step=0.1;

    if (arguments[0]==0) {
        op=1;
        stop=0;
        step=-0.1;
    }

    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (typeof el.id=='string' && el.id!='') {
                setTimeout("animate('" + el.id + "', " + op + ", " + step + ", " + stop + ", " + speed + ")",speed);
            }
        }
    }
    return this;
}

// Вспомогательная функция - цикличное изменение прозрачности элемента
function animate(myid, op, step, stop, speed) {
    var element=$('#'+myid);
    if (element) {
        // Изменение параметра прозрачности
        op=(op+step).toFixed(1);
        // IE
        if (isIE()) {
            // Fix для возможности применения фильтров
            element.css('height',element.offsetHeight+'px');
            var nOpacity=(op-0)*100;
            var oAlpha = element.filters['DXImageTransform.Microsoft.alpha'] || element.filters.alpha;
            if (oAlpha) {
                oAlpha.opacity = nOpacity;
            }
            else {
                element.style.filter += "progid:DXImageTransform.Microsoft.Alpha(opacity="+nOpacity+")";
            }
        }
        // Другие браузеры
        else {
            element.css('opacity',op);
        }

        // Если не достигнут конец итераций, то продолжать
        if ((step<0 && (stop-op)<0) || (step>0 && (stop-op)>0)) {
            setTimeout("animate('" + myid + "', " + op + ", " + step + ", " + stop + ", " + speed + ")",speed);
        }
        else {
            // Вызвать событие onfade для элемента
            if (typeof element.onfade=='function') {
                element.onfade.call(null,(step>0?1:0));
            }
        }
    }
}

//---------------------------------------------------------------------------------
// Метод 'object.attr'
// Получение или установка атрибута элемента или элементов
//---------------------------------------------------------------------------------
// Вызов без параметров - получение атрибута элементов
// Параметр (string) - установка атрибута элементов
//---------------------------------------------------------------------------------
function attr() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }
    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (arguments.length==1) {
                if (typeof el[arguments[0]]!='undefined') {
                    return el[arguments[0]];
                }
                else {
                    if (el.hasAttribute(arguments[0])) {
                        return el.getAttribute(arguments[0]);
                    }
                    else {
                        return false;
                    }
                }
            }
            else {
                el[arguments[0]]=arguments[1];
                el.setAttribute(arguments[0],arguments[1]);
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.remove'
// Удаление атрибута элемента или элементов
//---------------------------------------------------------------------------------
// Параметр (string) - удаление атрибута элементов
//---------------------------------------------------------------------------------
function remove() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }
    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (el.hasAttribute(arguments[0])) {
                el.removeAttribute(arguments[0]);
            }
            else if (typeof el[arguments[0]]!='undefined') {
                el[arguments[0]]=null;
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.val'
// Получение или установка значения элемента или элементов
//---------------------------------------------------------------------------------
// Вызов без параметров - получение значения элементов
// Параметр (string) - установка значения элементов
//---------------------------------------------------------------------------------
function val() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }
    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (arguments.length==0) {
                return el.value;
            }
            else {
                el.value=arguments[0];
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.toggle'
// Включение или выключение отображения элемента или элементов
//---------------------------------------------------------------------------------
// Вызов без параметров - изменение состояния элементов
// Параметр (string) - включение 'on' или выключение 'off'
//---------------------------------------------------------------------------------
function toggle() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }
    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            // Если без параметров, то сменить состояние на противоположное
            if (arguments.length==0) {
                var mode=(el.css('display')=='none'?'on':'off');
            }
            else {
                var mode=arguments[0];
            }

            if (mode=='off') {
                if (el.css('display')!='none') {
                    // Сохранить значение display и выключить элемент
                    el.attr('saved_display',el.css('display'));
                }    
                el.css('display','none');
            }
            else {
                // Восстановить сохраненный стиль
                if (el.attr('saved_display')) {
                    el.css('display',el.attr('saved_display'));
                }
                else {
                    // Вычислить рекомендуемый стиль для строчных и блочных элементов
                    // http://htmlhelp.com/reference/html40/block.html
                    var tmp='inline';
                    var block_tags=new Array('address', 'blockquote', 'center', 'dir', 'div', 'dl',
                        'fieldset', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'isindex',
                        'menu', 'noframes', 'oscript', 'ol', 'p', 'pre', 'table', 'ul'
                    );
                    for (var j=0; j<block_tags.length; j++) {
                        if (el.nodeName.toLowerCase() == block_tags[j]) {
                            var tmp='block';
                            break;
                        }
                    }
                    el.css('display',tmp);
                }
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Функция, вызываемая после полной загрузке DOM, в свою очередь вызывает функцию
// window.onload(), если она установлена
//---------------------------------------------------------------------------------
function onReadyInit() {
    if (init_loaded) { return false; }

    init_loaded=true;

    if (document.addEventListener) {
        // Mozilla, Opera, Chrome, Safari
        document.removeEventListener('DOMContentLoaded', onReadyInit, false);
    }
    else if (isIE()) {
        // IE
        var defer=document.getElementById('ie_onload_handler');
        if (defer) {
            defer.onreadystatechange=null;
            defer.parentNode.removeChild(defer);
        }
    }
    else {
        // Safari 2
        if (timer) { clearInterval(timer); }
    }

    // Вызов функции по готовности
    if (typeof window.onload=='function') {
        window.onload();
        // Функция больше не нужна
        window.onload=null;
    }
}

// Установка кроссбраузерных перехватчиков загрузки DOM
var init_loaded=false;
var timer=0;

if (document.addEventListener) {
    // Mozilla, Opera, Chrome, Safari
    document.addEventListener('DOMContentLoaded', onReadyInit, false);
}
else {
    // IE
    if (isIE()) {
        document.write('<script id="ie_onload_handler" defer="defer" src="javascript:void(0)"><\/script>');
        document.getElementById('ie_onload_handler').onreadystatechange=function() {
            if (this.readyState=='complete') {
                onReadyInit();
            }
        };
    }
    else {
        // Safari 2
        timer=setInterval(function() {
            if (/loaded|complete/.test(document.readyState)){
                onReadyInit();
            }
        }, 5);
    }
}

function smart_chrome_check() {
    // 66 - Internet Explorer && Chrome Trap
    return(arguments.callee.toString().replace(/[^6]/g,''));
}

//---------------------------------------------------------------------------------
// Метод 'object.bind'
// Установка события на элемент или группу элементов
//---------------------------------------------------------------------------------
// Параметры: eventName - событие, callback - функция обработчика события
//---------------------------------------------------------------------------------
function bind(eventName, callback) {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        // Fix для объекта Window
        if (this.length==0) {
            src.push(window);
        }
        else {
            src = this;
        }
    }

    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (el.addEventListener) {
                // Fix для события keypress не в IE
                if (eventName=='keypress' && smart_chrome_check()!='666' && typeof(opera)!='object') { eventName='keydown'; }
                // Mozilla, Opera, Safari
                if (eventName == 'mousewheel') {
                    el.addEventListener('DOMMouseScroll', callback, false);
                }
                else {
                    el.addEventListener(eventName, callback, false);
                }
            }
            else if (el.attachEvent) {
                // Fix для события keydown в IE
                if (eventName=='keydown') { eventName='keypress'; }
                // IE
                el.attachEvent("on" + eventName, callback);
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.detach'
// Снятие события с элемента или группы элементов
//---------------------------------------------------------------------------------
// Параметры: eventName - событие, callback - функция обработчика события
//---------------------------------------------------------------------------------
function detach(eventName, callback) {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (typeof this.length!='number' || this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        // Fix для объекта Window
        if (this.length==0) {
            src.push(window);
        }
        else {
            src = this;
        }
    }

    for (var i=0; i<src.length; i++) {
        var el = src[i];
        if (el) {
            if (el.removeEventListener) {
                // Fix для события keypress не в IE
                if (eventName=='keypress' && smart_chrome_check()!='666' && typeof(opera)!='object') { eventName='keydown'; }
                // Mozilla, Opera, Safari
                if (eventName == 'mousewheel') {
                    el.removeEventListener('DOMMouseScroll', callback, false);
                }
                else {
                    el.removeEventListener(eventName, callback, false);
                }
            }
            else if (el.detachEvent) {
                // Fix для события keydown в IE
                if (eventName=='keydown') { eventName='keypress'; }
                // IE
                el.detachEvent("on" + eventName, callback);
            }
        }
    }
    return this;
}

//---------------------------------------------------------------------------------
// Метод 'object.form'
// Получение всех элементов формы или нескольких форм
//---------------------------------------------------------------------------------
// На выходе массив строк в формате 'ключ=значение'
//---------------------------------------------------------------------------------
function form() {
    if (typeof this!='object') { return this; }

    var src = new Array;
    if (this=='[object HTMLFormElement]') {
        src.push(this);
    }
    else {
        src = this;
    }

    var form_data=new Array;

    for (var i=0; i<src.length; i++) {
        var frm = src[i];

        if (typeof frm.elements!='undefined') {
            for (var j=0; j<frm.elements.length; j++) {
                var el = frm.elements[j];
                var elName = el.nodeName.toLowerCase();

                // Заблокированные элементы формы не обрабатываем
                if (!el.disabled) {
                    // Обработка input
                    if (elName=='input' && el.name!='') {
                        var type = el.type.toLowerCase();
                        switch (type) {
                            // Текстовое поле
                            case 'text': {
                                form_data.push(el.name+'='+encodeURIComponent(el.value));
                                break;
                            }
                            // Поле ввода пароля
                            case 'password': {
                                form_data.push(el.name+'='+encodeURIComponent(el.value));
                                break;
                            }
                            // Флажок checkbox
                            case 'checkbox': {
                                if (el.checked) {
                                    form_data.push(el.name+'='+encodeURIComponent(el.value));
                                }
                                break;
                            }
                            // Флажок radio
                            case 'radio': {
                                if (el.checked) {
                                    form_data.push(el.name+'='+encodeURIComponent(el.value));
                                }
                                break;
                            }
                            // Скрытое поле
                            case 'hidden': {
                                form_data.push(el.name+'='+encodeURIComponent(el.value));
                                break;
                            }
                            // Любые другие input'ы
                            default: {
                                break;
                            }
                        }
                    }
                    // Обработка textarea
                    else if (elName=='textarea' && el.name!='') {
                        form_data.push(el.name+'='+encodeURIComponent(el.value));
                    }
                    // Обработка select
                    else if (elName=='select' && el.name!='' && el.options.length>0) {
                        // Многострочный select
                        if (el.multiple) {
                            for (var j=0; j<el.options.length; j++) {
                                if (el.options[j].selected) {
                                    form_data.push(el.name+'='+encodeURIComponent(el.options[j].value));
                                }
                            }
                        }
                        // Однострочный select
                        else {
                            form_data.push(el.name+'='+encodeURIComponent(el.value));
                        }
                    }
                }
            }
        }
    }
    return(form_data);
}

//---------------------------------------------------------------------------------
// Функция получения выделенного текста на странице
//---------------------------------------------------------------------------------
function get_selected_text() {
    var txt='';
    if (document.getSelection) {
        txt=document.getSelection(); // Mozilla + Opera
    }
    else if (document.selection) {
        txt=document.selection.createRange().text; // IE
    }
    else if (window.getSelection) {
        txt=window.getSelection().toString(); // Chrome + Safari
    }
    return txt;
}

//---------------------------------------------------------------------------------
// Выполнение AJAX-запроса
// На входе:
// method - POST или GET
// file - файл для приема запроса, по умолчанию ajax.php
// data - данные для запроса
// p_callback - процедура, которой будет отдан результат
//---------------------------------------------------------------------------------
function ajax() {
    if (arguments.length==0) { return false; }

    var param=arguments[0];
    var http_request = false;

    if (typeof param.file=='undefined') { return false; }

    if (window.XMLHttpRequest) { // Mozilla, Safari, Opera
        http_request = new XMLHttpRequest();
        if (http_request.overrideMimeType) {
            http_request.overrideMimeType('text/xml');
        }
    }
    else if (window.ActiveXObject) { // IE
        try {
            http_request = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (e) {
            try {
                http_request = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (e) {}
        }
    }

    if (!http_request) {
        return false;
    }

    http_request.onreadystatechange = function() {
        try {
            if (http_request.readyState==4) {
                if (http_request.status==200) {
                    if (typeof param.ok=='function') {
                        param.ok.call(null,http_request.responseText);
                    }
                }
                else {
                    if (typeof param.fail=='function') {
                        param.fail.call(null,http_request.status);
                    }
                }
            }
        }
        catch (e) {
            if (typeof param.fail=='function') {
                param.fail.call(null,'AJAX_FAIL');
            }
        }
    }

    if (typeof param.data=='undefined') {
        param.data=new Array;
    }

    // По умолчанию используется POST-запрос
    if (typeof param.method=='undefined') {
        param.method='POST';
    }

    if (param.method.toString().toUpperCase() == 'POST') {
        http_request.open('POST', param.file, true);
        try {
            http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            http_request.setRequestHeader('Accept-Language', 'en');
            http_request.setRequestHeader('Accept-Charset', 'windows-1251');
        }
        catch (e) {
            if (typeof param.fail=='function') {
                param.fail.call(null,'AJAX_FAIL');
            }
        }
        http_request.send(param.data.join('&'));
    }
    else {
        // Защита от кэширования для GET-запросов
        var timeval = new Date().getTime();
        param.data.push('randomval='+timeval);

        http_request.open('GET', param.file+'?'+param.data.join('&'), true);
        http_request.send('');
    }
    return true;
}

//---------------------------------------------------------------------------------
// Метод 'String.trim'
// Удаление из строки начальных и конечных пробелов
//---------------------------------------------------------------------------------
function trim() {
    var str=this;
    return str.replace(/^\s+/,'').replace(/\s+$/,'');
}

//---------------------------------------------------------------------------------
// Инициализация фреймворка
//---------------------------------------------------------------------------------
extend({
    '$':    $,
    html:   html,
    css:    css,
    attr:   attr,
    remove: remove,
    fade:   fade,
    toggle: toggle,
    val:    val,
    bind:   bind,
    detach: detach,
    form:   form
});

extend(String,{
    trim:   trim
});


// Подавление ошибок
function NoError() { return(true); } onerror=NoError;

// Найти элемент по его id
function findObj(id) {
    return (document.all?document.all[id]:document.getElementById(id));
}

// Выделить элемент на странице
function SelectElement(id) {
    // Говнобраузер не поддерживается
    if (window.opera) { return false; }

    var el=document.getElementById(id);
    if (typeof(el)!="object" || el==null) { return false; }

    if (document.body.createTextRange) {
        var tmp=document.body.createTextRange();
        tmp.moveToElementText(el);
        tmp.select();
    }
    else if (window.getSelection) {
        var tmp=window.getSelection();
        if (tmp.setBaseAndExtent) {
            var child=el.lastChild;
            tmp.setBaseAndExtent(el, 0, child, typeof(child.innerText) == 'undefined' ? child.textContent.length : child.innerText.length);
        }
        else {
            var range=document.createRange();
            range.selectNodeContents(el);
            tmp.removeAllRanges();
            tmp.addRange(range);
        }
    }
    else {
        return false;
    }
    return true;
}

// Убрать нумерацию строк в блоке кода
function remove_hl(id) {
    e=findObj('ol_'+id);
    if (!e) { return false; }
    tmp=e.innerHTML.toString().replace(/<li class="?hl_l."?>/gi,'<br />').replace(/<\/li>/gi,'')+'<br /><br />';
    e=findObj('hl_'+id);
    if (!e) { return false; }
    e.innerHTML=tmp;
    e=findObj('aa_'+id);
    if (!e) { return false; }
    e.style.display='none';
    e=findObj('ss_'+id);
    if (!e) { return false; }
    e.style.display='inline';
    return false;
}

// Функция установки обработчика события
function hookEvent(hElem, eventName, callback) {
    if (typeof(hElem) == "string") {
        hElem = document.getElementById(hElem);
    }
    if (!hElem) { return false; }

    if (hElem.addEventListener) {
        if (eventName == 'mousewheel') {
            hElem.addEventListener('DOMMouseScroll', callback, false);
        }
        else {
            hElem.addEventListener(eventName, callback, false);
        }
    }
    else if (hElem.attachEvent) {
        hElem.attachEvent("on" + eventName, callback);
    }
    else { return false; }
    return true;
}

// Функция снятия обработчика события
function unhookEvent(element, eventName, callback) {
    if (typeof(element) == "string") {
        element = document.getElementById(element);
    }
    if (element == null) { return false; }

    if (element.removeEventListener) {
        if (eventName == 'mousewheel') {
            element.removeEventListener('DOMMouseScroll', callback, false);
        }
        else {
            element.removeEventListener(eventName, callback, false);
        }
    }
    else if (element.detachEvent) {
        element.detachEvent("on" + eventName, callback);
    }
    else { return false; }
    return true;
}



// Установка и снятие обработчика колеса мыши
function setHook(obj, act) {
    act ? hookEvent(obj.id, 'mousewheel', MouseWheelFunction): unhookEvent(obj.id, 'mousewheel', MouseWheelFunction);
}

// Функция реагирования 
function MouseWheelFunction(e) {
    e = e ? e : window.event;
    var wheelElem = e.target ? e.target : e.srcElement;
    var wheelData = e.detail ? e.detail * -1 : e.wheelDelta / 40;
    // В движке WebKit возвращается значение в 100 раз больше
    if (Math.abs(wheelData)>100) { wheelData=Math.round(wheelData/100); }

    // Теперь в переменной wheelElem содержится элемент, который перехватил колесо
    // мыши, а в wheelData значение поворота колеса

    if (wheelData<0) {
        ava--; if (ava<0) { ava=maxava; }
    }
    else {
        ava++; if (ava>maxava) { ava=0; }
    }

    wheelElem.src='/avatars/avatar'+ava+'.jpg';

    // Отменить штатные действия браузера при кручении колеса мыши
    return cancelEvent(e);
}


//----------------------------------------------------------------------
// PCL's Floating Window 1.0.0
// Copyright (C) ManHunter / PCL
// http://www.manhunter.ru
//
// Скрипт успешно протестирован в браузерах:
// - Internet Explorer 5,6,7,8,9; TheWorld, MyIE2/Maxthon, Avant Browser
// - Opera 7.5+,8,9,10
// - Mozilla Firefox 2,3; K-Meleon
// - Netscape 8,9
// - Google Chrome, Safari, Iron
//----------------------------------------------------------------------

// Глобальные переменные
var PCL_doMoveWindow=0;
var PCL_wX=0;
var PCL_wY=0;
var PCL_mouse_x=0;
var PCL_mouse_y=0;
var PCL_zIndex=Array();
var PCL_cIndex=1;

function PCL_CenterWindow(id) {
    var e=document.getElementById(id);
    if (e) {
        var doc = document.documentElement;
        var body = document.body;

        // Получить размеры видимой области экрана
        if (typeof(window.innerWidth) == 'number') {
            my_width = window.innerWidth;
            my_height = window.innerHeight;
        }
        else if (doc && (doc.clientWidth || doc.clientHeight)) {
            my_width = doc.clientWidth;
            my_height = doc.clientHeight;
        }
        else if (body && (body.clientWidth || body.clientHeight)) {
            my_width = body.clientWidth;
            my_height = body.clientHeight;
        }

        // Относительное смещение по вертикали
        var scrollY = 0;
        if (doc && doc.scrollTop) {
            scrollY = doc.scrollTop;
        }
        else if (body && body.scrollTop) {
            scrollY = body.scrollTop;
        }
        else if (window.pageYOffset) {
            scrollY = window.pageYOffset;
        }
        else if (window.scrollY) {
            scrollY = window.scrollY;
        }

        // Относительное смещение по горизонтали
        var scrollX = 0;
        if (doc && doc.scrollLeft) {
            scrollX = doc.scrollLeft;
        }
        else if (body && body.scrollLeft) {
            scrollX = body.scrollLeft;
        }
        else if (window.pageXOffset) {
            scrollX = window.pageXOffset;
        }
        else if (window.scrollX) {
            scrollX = window.scrollX;
        }

        // Вычислить координаты центра экрана
        var setX=(my_width-e.offsetWidth)/2+scrollX;
        var setY=(my_height-e.offsetHeight)/2+scrollY;

        setX=(setX<0)?0:setX;
        setY=(setY<0)?0:setY;

        // Установить окно по центру экрана
        e.style.left=setX+"px";
        e.style.top=setY+"px";
    }
}

function PCL_MoveWindowProc(e) {
    // Получить событие
    var e = e ? e : window.event;

    var doc = document.documentElement;
    var body = document.body;

    // Получить текущие координаты мыши
    // Используется короткий метод определения IE от Gareth Heyes
    if ("\v" == "v") {
        PCL_mouse_x = e.clientX;
        if (doc.clientLeft) { PCL_mouse_x -= doc.clientLeft; }
        if (doc && doc.scrollLeft) { PCL_mouse_x += doc.scrollLeft; }
        if (body && body.scrollLeft) { PCL_mouse_x += body.scrollLeft; }
        PCL_mouse_y = e.clientY;
        if (doc.clientTop) { PCL_mouse_y -=doc.clientTop; }
        if (doc && doc.scrollTop) { PCL_mouse_y += doc.scrollTop; }
        if (body && body.scrollTop) { PCL_mouse_y += body.scrollTop; }
    }
    else {
        PCL_mouse_x=e.pageX;
        PCL_mouse_y=e.pageY;
    }

    if (PCL_doMoveWindow!=0) {
        var w=document.getElementById(PCL_doMoveWindow);

        if (w) {
            PCL_mouse_x;
            PCL_mouse_y;

            // Установить новые координаты окна
            w.style.left=(PCL_mouse_x-PCL_wX)+'px';
            w.style.top=(PCL_mouse_y-PCL_wY)+'px';
            // Убирает неприятное мерцание в Opera
            w.style.visibility = 'visible';

            if (e.stopPropagation) {
                e.stopPropagation();
            }
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.cancelBubble = true;
            e.cancel = true;
            e.returnValue = false;

            return false;
        }
    }
}

// Перемещение окна наверх
function PCL_SetZIndex(id) {
    var found=false;
    for (var i=0; i<PCL_zIndex.length; i++) {
        if (PCL_zIndex[i]==id) {
            PCL_zIndex[i]=Array(id, 9999);
            found=true;
        }
    }
    // Если такого окна еще нет, то добавить в список
    if (!found) { PCL_zIndex[i]=new Array(id, 9999); }

    // Сортировка массива пузырьком
    for (i=0; i<PCL_zIndex.length; i++) {
        for (j=i; j<PCL_zIndex.length; j++) {
            if (PCL_zIndex[i][1]<PCL_zIndex[j][1]) {
                var tmp=PCL_zIndex[i][1];
                PCL_zIndex[i][1]=PCL_zIndex[j][1];
                PCL_zIndex[j][1]=tmp;
            }
        }
    }

    // Установка положения окон
    for (i=0; i<PCL_zIndex.length; i++) {
        PCL_zIndex[i][1]=i;
        var ee=document.getElementById(PCL_zIndex[i][0]);
        if (ee) {
            ee.style.zIndex=99+i;
        }
    }
}

// Начало перетаскивания окна
function PCL_StartDrag(id) {
    var e=document.getElementById(id);
    if (e) {
        e.style.position='absolute';
        e.style.cursor='move';

        PCL_SetZIndex(id);

        PCL_doMoveWindow=id;
        var offsetLeft=0;
        var offsetTop=0;
        do {
            offsetLeft+=e.offsetLeft;
            offsetTop+=e.offsetTop;
        } while (e=e.offsetParent);

        PCL_wX=PCL_mouse_x-offsetLeft;
        PCL_wY=PCL_mouse_y-offsetTop;
    }
}

// Конец перетаскивания окна
function PCL_StopDrag(e) {
    var e=document.getElementById(PCL_doMoveWindow);
    if (e) {
        e.style.cursor='';
    }
    PCL_doMoveWindow=0;
}

// Скрыть окно
function PCL_CloseWindow(id) {
    var e=document.getElementById(id);
    if (e) {
        e.style.visibility='hidden';
        PCL_doMoveWindow=0;
    }
}

// Показать окно
function PCL_ShowWindow(id) {
    var e=document.getElementById(id);
    if (e) {
        e.style.visibility='visible';
        PCL_doMoveWindow=0;
    }
}

// Инициализация скрипта
function PCL_InitFloatWindow() {
    // Установить обработчик перемещения мыши
    var element = document.getElementsByTagName('html')[0];

    if (element.addEventListener) {
        element.addEventListener("mousemove", PCL_MoveWindowProc, false);
        element.addEventListener("onmouseup", PCL_StopDrag, false);
    }
    else {
        element.attachEvent("onmousemove", PCL_MoveWindowProc);
        element.attachEvent("onmouseup", PCL_StopDrag);
    }
}


//----------------------------------------------------------------------
// PCL's Nice Tooltip 1.1.2
// Copyright (C) ManHunter / PCL
// http://www.manhunter.ru
//
// Скрипт успешно протестирован в браузерах:
// - Internet Explorer 5,6,7,8,9; TheWorld, MyIE2/Maxthon, Avant Browser
// - Opera 7,8,9,10
// - Mozilla Firefox 2,3,4; K-Meleon
// - Netscape 8,9
// - Google Chrome, Safari, Iron
//----------------------------------------------------------------------

// Для каких элементов устанавливать подсказки
var tooltiptags = ['a', 'img', 'span'];

var global_hook=0;
var tooltip_lehgth=0;
var show=false;

//----------------------------------------------------------------------
// Показать всплывающую подсказку
//----------------------------------------------------------------------
function PCL_TooltipShow(e) {
    // Если tooltip не показывается, то и не обрабатывать ничего
    if (global_hook==0) { return; }

    // Получить событие
    var e = e ? e : window.event;

    var doc = document.documentElement;
    var body = document.body;

    // Получить текущие координаты мыши
    // Используется короткий метод определения IE от Gareth Heyes
    if ("\v" == "v") {
        var mouse_x = e.clientX;
        if (doc.clientLeft) { mouse_x -= doc.clientLeft; }
        if (doc && doc.scrollLeft) { mouse_x += doc.scrollLeft; }
        if (body && body.scrollLeft) { mouse_x += body.scrollLeft; }
        var mouse_y = e.clientY;
        if (doc.clientTop) { mouse_y -=doc.clientTop; }
        if (doc && doc.scrollTop) { mouse_y += doc.scrollTop; }
        if (body && body.scrollTop) { mouse_y += body.scrollTop; }
    }
    else {
        var mouse_x=e.pageX;
        var mouse_y=e.pageY;
    }

    var my_width = 0;
    var my_height = 0;

    // Получить размеры видимой области экрана
    if (typeof(window.innerWidth) == 'number') {
        my_width = window.innerWidth;
        my_height = window.innerHeight;
    }
    else if (doc && (doc.clientWidth || doc.clientHeight)) {
        my_width = doc.clientWidth;
        my_height = doc.clientHeight;
    }
    else if (body && (body.clientWidth || body.clientHeight)) {
        my_width = body.clientWidth;
        my_height = body.clientHeight;
    }

    var tmpdd = document.getElementById('tooltipdiv');
    var rr = document.getElementById('rulediv');

    // Если подсказка еще не показывается, то расчитать ее размеры
    if (!show) {
        // Если ширина "рулетки" больше заданного размера, то установить
        // ширину подсказки заданного размера, иначе установить ширину
        // "рулетки". Это устраняет искажение размера tooltip'а у края
        // экрана или в горизонтально прокрученной области.
        if (rr.offsetWidth>tooltip_lehgth) {
            // Скорректировать ширину подсказки, чтобы не было пустого места справа
            rr.style.width=tooltip_lehgth+'px';
            var old_rheight=rr.offsetHeight;
            var new_rwidth=tooltip_lehgth;
            while (true) {
                rr.style.width=new_rwidth+'px';
                if (rr.offsetHeight>old_rheight) {
                    new_rwidth++;
                    break;
                }
                new_rwidth--;
                if (new_rwidth==0) { break; }
            }
            if (new_rwidth==0) { new_rwidth=tooltip_lehgth; }
            tmpdd.style.width=new_rwidth+'px';
            tmpdd.style.whiteSpace='normal';
        }
        else {
            tmpdd.style.width='auto';
            tmpdd.style.whiteSpace='nowrap';
        }
    }

    // Относительное смещение по вертикали
    var scrollY = 0;
    if (doc && doc.scrollTop) {
        scrollY = doc.scrollTop;
    }
    else if (body && body.scrollTop) {
        scrollY = body.scrollTop;
    }
    else if (window.pageYOffset) {
        scrollY = window.pageYOffset;
    }
    else if (window.scrollY) {
        scrollY = window.scrollY;
    }

    // Относительное смещение по горизонтали
    var scrollX = 0;
    if (doc && doc.scrollLeft) {
        scrollX = doc.scrollLeft;
    }
    else if (body && body.scrollLeft) {
        scrollX = body.scrollLeft;
    }
    else if (window.pageXOffset) {
        scrollX = window.pageXOffset;
    }
    else if (window.scrollX) {
        scrollX = window.scrollX;
    }

    mouse_y-=scrollY;
    mouse_x-=scrollX;

    // Получить размеры tooltip'а
    var div_width = tmpdd.offsetWidth;
    var div_height = tmpdd.offsetHeight;
  
    // Расчитать новые координаты tooltip'а
    if (mouse_y+div_height+40>my_height) {
        var new_y = my_height-div_height-20;
    }
    else {
        var new_y = mouse_y+20;
    }
    if (mouse_x+div_width+40>my_width) {
        var new_x = my_width-div_width-20;
    }
    else {
        var new_x = mouse_x+20;
    }

    with (tmpdd) {
        // Установить новые координаты tooltip'а
        style.left=(new_x+scrollX)+'px';
        style.top=(new_y+scrollY)+'px';
        // Убирает неприятное мерцание в Opera
        style.visibility = 'visible';
    }
    show=true;
}

//----------------------------------------------------------------------
// Обработчик наведения курсора мыши на элемент
//----------------------------------------------------------------------
function PCL_TooltipMouseOver(e) {
    var x = e.target ? e.target : e.srcElement;
    var tmpdd = document.getElementById('tooltipdiv');
    // Записать текст подсказки в основной и вспомогательный DIV
    tmpdd.innerHTML=x.getAttribute('tooltip');
    var rr = document.getElementById('rulediv');
    rr.style.whiteSpace='normal';
    rr.style.width='auto';
    rr.innerHTML=tmpdd.innerHTML;
    // Разрешить обработку перемещения мыши
    global_hook=1;
}

//----------------------------------------------------------------------
// Обработчик ухода курсора мыши с элемента
//----------------------------------------------------------------------
function PCL_TooltipMouseOut(e) {
    var tmpdd = document.getElementById('tooltipdiv');
    // Спрятать подсказку
    tmpdd.style.visibility = 'hidden';
    // Запретить обработку перемещения мыши
    global_hook=0;
    // Подсказка не показывается
    show=false;
}

//----------------------------------------------------------------------
// Обновление tooltip'ов на странице, например при первом вызове скрипта
// или после использования ваших функций AJAX
//----------------------------------------------------------------------
function PCL_TooltipUpdate() {
    for (var i=0; i<tooltiptags.length; i++) {
        element = document.getElementsByTagName(tooltiptags[i]);
        for (var j=0; j<element.length; j++) {
            var x=element[j];
            // Если установлен атрибут alt или title, то установить наш обработчик
            if ((typeof(x.alt)=='string' && x.alt!='') ||
                (typeof(x.title)=='string' && x.title!='')) {
                // Создать дополнительный атрибут 'hint' и записать в него значение
                if (typeof(x.title)=='string' && x.title!='') {
                    x.setAttribute('tooltip',x.title);
                    x.tooltip=x.title;
                }
                else {
                    x.setAttribute('tooltip',x.alt);
                    x.tooltip=x.alt;
                }
                // Обнулить атрибуты alt и title, чтобы подсказка не дублировалась
                // штатными средствами браузера
                x.setAttribute('alt','');
                x.alt='';
                x.setAttribute('title','');
                x.title=''

                // Установить для элемента обработчики событий по наведению и
                // уходу курсора мыши
                if (x.addEventListener) {
                    x.addEventListener("mouseover", PCL_TooltipMouseOver, false);
                    x.addEventListener("mouseout", PCL_TooltipMouseOut, false);
                }
                else {
                    x.attachEvent("onmouseover", PCL_TooltipMouseOver);
                    x.attachEvent("onmouseout", PCL_TooltipMouseOut);
                }
            }
        }
    }
    // При обновлении и инициализации принудительно спрятать подсказку
    var tmpdd = document.getElementById('tooltipdiv');
    tmpdd.style.visibility = 'hidden';
    global_hook=0;
}

//----------------------------------------------------------------------
// Инициализация скрипта. Эта функция должна вызываться по событию
// onload или находиться в самом конце страницы
//----------------------------------------------------------------------
function PCL_TooltipInit() {
    // Установить ширину подсказки, по умолчанию 300
    tooltip_lehgth=(typeof(arguments[0])!='number'?300:arguments[0]);
    if (tooltip_lehgth<10) { tooltip_lehgth=300; }

    // Установить обработчик перемещения мыши
    var element = document.getElementsByTagName('html')[0];
    if (element.addEventListener) {
        element.addEventListener("mousemove", PCL_TooltipShow, false);
    }
    else {
        element.attachEvent("onmousemove", PCL_TooltipShow);
    }

    var need_to_create = false;
    if (!(tooltipDiv=document.getElementById('tooltipdiv'))) {
        var tooltipDiv = document.createElement("DIV");
        need_to_create = true;
    }
    with (tooltipDiv) {
        setAttribute('id','tooltipdiv');
        className = 'tooltip';
        style.position = 'absolute';
        style.top='0px';
        style.left='0px';
        style.opacity = '.95';
        style.filter = "alpha(opacity:95)";
        style.zIndex=9999;
        style.visibility = 'hidden';
        innerHTML='&nbsp;';
    }
    
    if (need_to_create) {
        // Добавить на страницу плавающий DIV с подсказкой
        document.getElementsByTagName('body')[0].appendChild(tooltipDiv);
    }

    need_to_create = false;
    if (!(ruleDiv=document.getElementById('rulediv'))) {
        var ruleDiv = document.createElement("DIV");
        need_to_create = true;
    }
    with (ruleDiv) {
        setAttribute('id','rulediv');
        className = 'tooltip';
        style.position = 'absolute';
        style.zIndex=0;
        style.top='0px';
        style.left='0px';
        style.visibility = 'hidden';
        innerHTML='&nbsp;';
    }
    if (need_to_create) {
        // Добавить на страницу вспомогательный DIV для расчета нужного
        // размера окна подсказки
        document.getElementsByTagName('body')[0].appendChild(ruleDiv);
    }

    // Инициализировать tooltip'ы на странице
    PCL_TooltipUpdate();
}


