[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Либа для работы с событиями (JS)
vasa_c
В JS не "готовых решений", так что сюда кину. Может пригодится кому-нибудь.
Код
/**
* Работа с обработчиками событий
*
* @package   Events
* @version   1.0
* @author    Григорьев О.С. aka vasa_c
* @copyright © vasa_c, 2007
* @license   LGPL (http://www.gnu.org/copyleft/lesser.html)
*
* ВОЗМОЖНОСТИ ЛИБЫ:
* - Унификация для всех браузеров:
*     - установки/удаления обработчиков (без проверки addEventListener/attachEvent)
*     - доступа к целевому объекту и объекту event
*     - отмены действия по умолчанию и дальнейшего распространения
* - Более гибкий вызов обработчика (см. ниже)
* - Группы обработчиков (см.ниже)
* - Централизованное удаление всех обработчиков в конце (для борьбы с утечками памяти)
* - Возможность указания объектов, как непосредственно, так и через id
* - Обращение к установленным обработчикам по идентификаторам
*
* Недостатки:
* - Браузеры не поддерживающие последние модели событий идут лесом (ошибок не происходит, но обработчики не устанавливаются)
* - Не поддерживается погружение событий
* - Не поддерживается генерация событий
*
*
* ФОРМАТ ОБРАБОТЧИКОВ
* В качестве обработчиков можно передавать:
* - function
* - string - пропускается через eval()
* - массив формата [function, объект, параметры, нестандартный вызов], обязателен только первый параметр
*     "объект" - объект в контексте которого вызывается функция.
*                не указан или false - window
*                true - целевой объект события
*                можно указывать строку, например "one.two.three", при вызове она будет
*                резволиться в объект (для тех случаев, когда объекта нет на стадии установки обработчиков)
*     "параметры" - массив параметров с которыми вызывается обработчик
*     "нестандартный вызов" - если указан, то обработчик считается нестандартным, не указан - стандартным (см. ниже)
*
* При "стандартном" вызове в обработчик передаются три параметра - node, event. Если был задан массив "параметры",
* то они добавляются начиная с третьего.
*     node  - целевой объект
*     event - объект Event
*
* При "нестандартном" эти три параметра не передаются.
* Он используется для вызова существующих функций с определенным списком параметров.
* Разруливание доступа к элементу и event ложится на плечи самого обработчика.
*
*
* ГРУППЫ ОБРАБОТЧИКОВ
* Работа приложения может состоять из набора устойчивых состояний и переходов между ними.
* Каждое состояние может характеризоваться набором действующих в нем обработчиков.
* При переходе из одного в другое, следует удалить все старые обработчики и установить новые.
* В данной либе можно устанавливать обработчики один раз, при этом привязывая их к какой-либо
* группе, а потом включать/отключать их синхронно.
* Группа идентифицируется именем. Группа по умолчанию - "0".
*
* ФУНКЦИИ
* add - установка обработчика
* remove, groupRemove, enable, disable, groupEnable, groupDisable -
*     удаление, включение/выключение отдельных обработчиков и групп
* preventDefault, stopPropagation - отмена дальнейшего распространения и действия по умолчанию
* using - вывод в глобальное пространство имен
*
*
* Тестировалось в IE6, FF2, Opera9
*/

/**
* @var object Events - пространство имен библиотеки
*/
var Events = new function() {

/********** PUBLIC **********/

/**
* Установка обработчика
*
* @param mixed  node    - целевой элемент (или его id)
* @param string event   - имя события (без "on")
* @param mixed  handler - обработчик (формат описан в шапке файла)
* @param string group   - имя группы (по умолчанию "0")
* @param bool   enb     - изначальный вкл/выкл обработчика (по умолчанию true)
*
* @return int           - идентификатор обработчика
*/
this.add = (
    function( node, event, handler, group, enb )
    {

        if ( typeof( node ) != "object" ) {
            node = document.getElementById( node );
        }
        
        if ( arguments.length < 5 ) {
            enb = true;
            if ( arguments.length < 4 ) {
                group = "0";
            }
        }

        if ( ( typeof( handler ) ) == "object" ) {
            if ( !handler[ 1 ] ) {
                handler[ 1 ] = window;
            } else if ( handler[ 1 ] === true ) {
                handler[ 1 ] = node;
            }
            if ( !handler[ 2 ] ) {
                handler[ 2 ] = [];
            }
        } else if ( typeof( handler ) == "function" ) {
            handler = [ handler, window, [] ];
        }
        
        var id = aHandlers.length;
        aHandlers[ id ] = {
            "node":    node,
            "event":   event,
            "handler": handler,
            "group":   group,
            "enb":     enb,
            "h":       addE( id )
        };
        
        if ( !aGroups[ group ] ) {
            aGroups[ group ] = {
                "enb": true,
                "A": [ id ]
            };
        } else {
            aGroups[ group ].A[ aGroups[ group ].A.length ] = id;
        }
        
        add( node, event, aHandlers[ id ].h );
        
        return id;
        
    } ); // add().
    
/**
* Удаление обработчика
*
* @param int id - его идентификатор
*/
this.remove = (
    function( id )
    {
        var h = aHandlers[ id ];
        if ( !h ) {
            return false;
        }
        remove( h.node, h.event, h.h );
        aHandlers[ id ] = false;
        return true;
    } );
    
/**
* Включение обработчика
*
* @param int id - его идентификатор
*/
this.enable = (
    function( id )
    {
        if ( aHandlers[ id ] ) {
            aHandlers[ id ].enb = true;
        }
        return true;
    } );
    
/**
* Выключение обработчика
*
* @param int id - его идентификатор
*/
this.disable = (
    function( id )
    {
        if ( aHandlers[ id ] ) {
            aHandlers[ id ].enb = false;
        }
        return true;
    } );
    
/**
* Удаление группы
*
* @param string group - ее имя
*/
this.groupRemove = (
    function( name )
    {
        if ( !aGroups[ name ] ) {
            return false;
        }
        var g = aGroups[ name ].A;
        for ( var i = 0; i < g.length; i++ ) {
            _this.remove( g[ i ] );
        }
        aGroups[ name ] = false;
        return true;
    } );
    
/**
* Включение группы
*
* @param string group - ее имя
*/
this.groupEnable = (
    function( name )
    {
        if ( aGroups[ name ] ) {
            aGroups[ name ].enb = true;
        }
        return true;
    } );
    
/**
* Выключение группы
*
* @param string group - ее имя
*/
this.groupDisable = (
    function( name )
    {
        if ( aGroups[ name ] ) {
            aGroups[ name ].enb = false;
        }
        return true;
    } );
    
/**
* Вывод функций в глобальную область видимости
*
* @param string prefix - префикс имен функций (по умолчанию "events").
*
* Функции либы выводятся в глобальное пространство имен.
* При указании непустого префикса, он добавляется к имени функции,
* которое приводится к криволинейной нотации. "add" --> "eventsAdd"
*/
this.using = (
    function( prefix )
    {
        if ( arguments.length == 0 ) {
            prefix = "events";
        }
        for ( var name in this ) {
            if ( name == "using" ) {
                continue;
            }
            var pName =
                prefix.length ?
                    prefix + name.charAt( 0 ).toUpperCase() + name.substr( 1, name.length - 1 ) :
                    name;
            window[ pName ] = this[ name ];
        }
    } ); // using().

/**
* Остановка дальнейшего распространения события.
* Вызывается внутри обработчика в виде Events.stopPropagation().
*/
this.stopPropagation = (
    function()
    {
        addE.stopPropagation = true;
        return true;
    } );
    
/**
* Отмена действия по умолчанию
* Вызывается внутри обработчика в виде Events.preventDefault().
*/
this.preventDefault = (
    function()
    {
        addE.preventDefault = true;
        return true;
    } );


/********** PRIVATE **********/

/**
* @var array  aHandlers - обработчики
* @var object aGroups   - группы
*/
var aHandlers = [];
var aGroups   = {};

/**
* Получение настоящего обработчик для устанавливаемого обработчика :)
* Возвращает функцию, которая будет установлена в качестве обработчика.
* В ней разруливаются признаки вкл/выкл, объекты, отмена распространения и т.п.
* и вызывается окончательный обработчик.
*
* @param  int id   - идентификатор обработчика
* @return function - "настоящий" обработчик
*/
function addE( id ) { return (
    function( e )
    {

        var h = aHandlers[ id ];

        if ( !( ( h ) && ( h.enb ) && ( aGroups[ h.group ] ) && ( aGroups[ h.group ].enb ) ) ) {
            return;
        }

        if ( typeof( h.handler ) != "object" ) {
            return eval( h.handler );
        }
        
        var prm = [];
        if ( !h.handler[ 3 ] ) {
            prm[ 0 ] = h.node;
            e = window.event || e;
            prm[ 1 ] = e;
            for ( var i = 0; i < h.handler[ 2 ].length; i++ ) {
                prm[ i + 2 ] = h.handler[ 2 ][ i ];
            }
        } else prm = h.handler[ 2 ];

        var obj = h.handler[ 1 ];
        if ( typeof( obj ) != "object" ) {
            obj = ( function( path ) {
                path = path.split( "." );
                var o = window;
                for ( var i = 0; i < path.length; i++ ) {
                    if ( !o[ path[ i ] ] ) {
                        return window;
                    }
                    o = o[ path[ i ] ];
                }
                return o;
            }( obj ) );
        }

        addE.stopPropagation = false;
        addE.preventDefault  = false;
        
        var ret = h.handler[ 0 ].apply( obj, prm );

        if ( addE.stopPropagation ) {
            if ( e.stopPropagation ) {
                e.stopPropagation();
            } else {
                e.cancelBubble = true;
            }
        }
        if ( addE.preventDefault ) {
            if ( e.preventDefault ) {
                e.preventDefault();
            } else {
                return false;
            }
        }

        return ret;
        
    } ) }; // addE().


/**
* Унификация установки/удаления обработчиков.
*/
if ( window.addEventListener ) {
    var add = (
        function( el, event, handler ) {
            return el.addEventListener( event, handler, false );
        } );
    var remove = (
        function( el, event, handler ) {
            return el.removeEventListener( event, handler, false );
        } );
} else if ( window.attachEvent ) {
    var add = (
        function( el, event, handler ) {
            return el.attachEvent( "on" + event, handler );
        } );
    var remove = (
        function( el, event, handler ) {
            return el.detachEvent( "on" + event, handler );
        } );
} else {
    var add    = ( function() {} );
    var remove = add;
}

/**
* @var object _this - алиас для this, на случай использования using().
*/
var _this = this;

/**
* Удаление обработчиков по унлоаду
*/
add( window, "unload", ( function() {
    for ( var name in aGroups ) {
        _this.groupRemove( name );
    }
    return true;
} ) );

}(); // Events.


Типа тест:


Код
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
    <head profile="http://gmpg.org/xfn/11">
        <title>Events.js — тест</title>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="./events.js"></script>
    </head>
    <body>

        <h1>Events.js — тест</h1>


        <h2>Установка обработчиков, включение/выключение групп</h2>

        <ul>
            <li id="lione">Раз</li>
            <li id="litwo">
                Два
                <ul>
                    <li id="litwoone" style="font-weight:normal;color:black">Два.Один</li>
                    <li id="litwotwo" style="font-weight:normal;color:black">Два.Два</li>
                </ul>
            </li>
            <li id="lithree">Три</li>
        </ul>
        
        <p>Жмите на пункты списка.</p>
        <table border="0">
            <tr>
                <td>Группа «litest» («Два.Один» и «Три»)</td>
                <td><input type="checkbox" value="1" onchange="this.checked ? Events.groupEnable( &quot;litest&quot; ) : Events.groupDisable( &quot;litest&quot; );" checked="checked" /></td>
                <td>— снимите галочку, чтобы отключить</td>
            </tr>
            <tr>
                <td>Группа по умолчанию (все остальные)</td>
                <td><input type="checkbox" value="1" onchange="this.checked ? Events.groupEnable( &quot;0&quot; ) : Events.groupDisable( &quot;0&quot; );" checked="checked" /></td>
                <td> </td>
            </tr>
        </table>
        
        <p>Отменить дальнейшее распространение для «Два.Два»:
           <input type="checkbox" value="1" id="ilitesttwo" />
           — установите галочку и событие не дойдет до пункта «Два».
        </p>
        
        <p><input type="submit" value="Убить группу litest" onclick="if (confirm(&quot;Все обработчики группы litest будут удалены навсегда&quot;)) {this.style.display=&quot;none&quot;;Events.groupRemove(&quot;litest&quot;);}" /></p>
        
        <script type="text/javascript">
            function litest( node )
            {
                node.style.color = "red";
                node.style.fontWeight = "bold";
                setTimeout( function() {
                    node.style.color = "black";
                    node.style.fontWeight = "normal";
                    }, 1000 );
                return true;
            }
            function litesttwo( node )
            {
                litest( node );
                if ( document.getElementById( "ilitesttwo" ).checked ) {
                    Events.stopPropagation();
                }
                return true;
            }
            Events.add( "lione",    "click", litest );
            Events.add( "litwo",    "click", litest );
            Events.add( "litwoone", "click", litest, "litest" );
            Events.add( "litwotwo", "click", litesttwo );
            Events.add( "lithree",  "click", litest, "litest" );
        </script>


        <h2>Назначение обработчиков</h2>
        
        <p><a href="#" id="a2func">На эту ссылку обработчик установлен, как простая функция</a></p>
        <p><a href="#" id="a2stand">Обработчик этой ссылке выполняется в контексте объекта данной ссылки с доп.параметрами 1,2,3</a></p>
        <p><a href="#" id="a2nstand">Нестандартный обработчик с параметрами 1,2,3, в контексте объекта one.two.three</a></p>

        <script type="text/javascript">
            function func2() {
                Events.preventDefault();
                var str = "Функция вызвана в контексте ";
                if ( this == window ) {
                    str += "объекта window";
                } else if ( this.tagName ) {
                    str += "DOM-элемента \"" + this.tagName + '"';
                } else {
                    str += "пользовательского объекта" + ( this.name ? ( ' "' + this.name + '"' ) : "" );
                }
                str += "\nВ нее переданы аргументы в количестве: " + arguments.length;
                for ( var i = 0; i < arguments.length; i++ ) {
                    str += "\n" + ( i + 1 ) + ". " + arguments[ i ];
                }
                alert( str );
                return true;
            }
            Events.add( "a2func", "click", func2 );
            Events.add( "a2stand", "click", [ func2, true, [ 1, 2, 3 ] ] );
            Events.add( "a2nstand", "click", [ func2, "one.two.three", [ 1, 2, 3 ], true ] );
            var one = { "two": { "three": { name: "one.two.three" } } };
        </script>
        
        <h3 style="font-weight:bold">Обработчик в виде строки для eval():</h3>

        <p>Повесить на следующию ссылку пользовательский код:
           <input type="text" value="alert(1)" id="ia2eval" />
           <input type="submit" value="повесить" onclick="a2evalH()" />
           (разработчик не несет ответственности за то, что вы здесь напишите)
        </p>
        <p><a href="#" id="a2eval">Ссылка с eval-обработчиком</a></p>

        <script type="text/javascript">
            function a2evalH()
            {
                if ( a2evalH.idHandler ) {
                    Events.remove( a2evalH.idHandler );
                }
                a2evalH.idHandler = Events.add( "a2eval", "click", document.getElementById( "ia2eval" ).value );
                return true;
            }
            a2evalH();
            Events.using( "" );
        </script>
        

        <h2>Отмена действия по умолчанию</h2>
        
        <p>Обработчик <a href="http://yandex.ru" id="aYa">данной ссылки</a> отменяет действие по умолчанию.
           Поставьте здесь галочку, чтобы он этого не делал —
           <input type="checkbox" value="1" id="iaYa" />
        </p>
        
        <script type="text/javascript">
            Events.add( "aYa", "click", ( function() {
                if ( !document.getElementById( "iaYa" ).checked ) {
                    Events.preventDefault();
                }
                return true;
            } ) );
        </script>
        
    </body>
</html>


Качать (6 К)



Спустя 5 часов, 26 минут, 5 секунд (12.04.2007 - 22:35) md5 написал(а):
материал для прозрения

Спустя 9 часов, 55 минут, 45 секунд (13.04.2007 - 08:30) vasa_c написал(а):
Цитата
материал для прозрения

чо?

Спустя 4 минуты, 15 секунд (13.04.2007 - 08:35) md5 написал(а):
я говорю все прозрели =)


_____________
Блог ГО | Таблица символов Юникода | Графомания
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.