This Might Be Useful

Динамическое создание обработчиков событий

Вчера столкнулся с необходимостью в зависимости от действий пользователя менять реакцию некоторых элементов страницы на разные события (в частности - onClick). Выяснилось, что простое присвоение в данное свойство не дает желаемых результатов. После некоторых раздумий и консультаций с коллегами решение было найдено.

Все дело в том, что есть два разных способа установки обработчиков событий, предназначенные для разных браузеров.

JAVASCRIPT:
  1. var Tag = document.getElementById('photo_larr');
  2. if(Tag.addEventListener) {
  3.   if (num > 1) {
  4.     Tag.addEventListener('click', function() {show_popup_photo(num - 1);}, true);
  5.   }
  6.   else {
  7.     Tag.removeEventListener('click', function() {}, true);
  8.   }
  9. } // Firefox или Opera
  10. else {
  11.   if (num > 1) {
  12.     Tag.attachEvent('onclick', function() {show_popup_photo((num - 1));});
  13.   }
  14.   else {
  15.     Tag.detachEvent('onclick');
  16.   }
  17. } // MSIE

Также вместо того, чтобы создавать функцию, можно указать имя уже существующей. Правда, в этом случае надо внимательно отнестись к ее параметрам.

В случае Firefox и Opera создаваемой функции можно давать имя. Это позволит прицепить в качестве обработчиков несколько действий.

Примечание: функция show_popup_photo(), переменная num и объект photo_larr в данном случае не имеют значения - на их месте может быть все, что угодно. Целью было просто создать некий пример использования определенных функций.

· Создание прямой ссылки на Network Connections
· Создание скриншотов в Windows Vista с сохранением всех визуальных эффектов
· MySQL функция для конвертирования bigint IP адресов в удобоваримые varchar
· Создаем свою captcha
· Создание PDF-файлов с помощью PHP и FPDF

- Коментировать
- Trackback

11 Responses to “Динамическое создание обработчиков событий”


  1. d1pr3d Says:

    ага, еще месяца два назад разбирался с этим, какраз и на описанные грабли ступал :)

  2. Filosoff Says:

    я уже несколько раз с этим разбирался. каждый раз успешно забывал, к чему привели разбирательства :). сейчас вот решил, наконец, записать.

  3. dimzon541 Says:

    Есть более универсальный способ.
    Изначально на этот photo_larr вешается в качетве обработчика функция назовём её photo_larr_OnClick()

    потом когда нужно изменить реакцию делаем
    eval('function photo_larr_OnClick(){alert("ПРЕВЕД!");}');

    Таким образом мы глобально замещаем одну реализацию другой, причём всё в рамках стандарта javaScript безо всяких там обыгрываний DOM

  4. Filosoff Says:

    я испытываю большую неприязнь к eval() и стараюсь нигде и никогда его не использовать. если надо, могу пояснить почему.

  5. dimzon541 Says:

    Поясни если не сложно

    Кстати, опять-таки если не нравится eval можно использовать такой код

    function someFunction1(){alert('someFunction1');}
    function someFunction2(){alert('someFunction2');}

    var photo_larr_OnClick_PROXY = someFunction1;

    function photo_larr_OnClick(){photo_larr_OnClick_PROXY();}

    И соответственно когда её надо изменить можно позвать
    photo_larr_OnClick_PROXY = someFunction2;

  6. Filosoff Says:

    сначала по поводу приведенного варианта. он очень занятный. только понял я его со второго раза :). в общем-то, он тоже вполне жизнеспособен.

    а про eval() - это, в общем, большая дырка. изначально это у меня пошло от PHP и Perl, где он медленный и может привести к различным проблемам с security. да и всегда можно обойтись без него.
    в JavaScript он, в принципе, также может привести к проблемам. поэтому я не использую его вообще. просто перестраховка.

  7. dimzon541 Says:

    По поводу eval в JavaScript - если это работает на клиенте то в принципе дырок нет, тем более если ты знаешь что за строчку ты передаешь в eval
    На самом деле eval бывает очень полезен. Он, к примеру, используется как основная фича в JSON
    Иногда при помощи eval можно сделать очень элегантные вещи. Допустим есть некоторая операция getSomeValue() которая может выполняться долго но результат её выполнения можно "закэшировать".

    классический способ:
    var getSomeValue_Cahce = 0;
    function getSomeValue()
    {
    if(getSomeValue_Cahce==0)
    getSomeValue_Cahce = getSomeValue_Actual();
    return getSomeValue_Cahce;
    }

    использование eval()
    function getSomeValue()
    { var n=getSomeValue_Actual();
    eval('function getSomeValue(){return ' + n + ';}')
    return n;
    }

  8. Filosoff Says:

    вполне возможно. но все равно eval() вызывает у меня неприязнь. и я не очень понимаю, чем второе решение элегантнее первого. оно несколько более сложно для понимания, как минимум. да и сработает чуть медленнее, по-моему. понятно, что ты просто оверрайднеш функцию сразу после кеширования. но как-то это некрасиво. не стыкуется с моим представлением о культуре программирования :) (ничего личного, если что).

  9. dimzon541 Says:

    Второе решение несколько замедляет ПЕРВЫЙ вызов но ускоряет последующие за счёт того что экономим на IF
    Если вызов getSomeValue частый то общая экономия заметна. К тому-же избавляемся от глобальной переменной
    Вообще в моей практике я достаточно часто использую eval чтобы генерировать некоторый код (причём бывает достаточно сложный) на лету.
    Другое применение eval находит например для обыгрывания пользовательского интерфейса. К примеру есть таблица в которой надо отобразить записи, причём записи получаются с сервера (используем AJAX). Тогда например достаточно изящный способ - в заголовке таблицы доп-аттрибутами у ячейки я указываю выражение на JavaScript для форматирования. Например
    [TD formatString="item.FirstName + ' ' + item.LastName + ' ' + item.MiddleName"]ФИО[/TD]
    [TD formatString="item.Bithday"]День рождения[/TD]
    Тогда при заполнении я использую универсальную функцию
    function getTextForCell(item, formatString){return eval(formatString);}

  10. Filosoff Says:

    отчасти согласен. но я очень против eval'а полученных данных. это потенциально несекьюрно. конечно, если это только для вывода, тогда ничего. но если потом данные в каком-то виде снова идут на сервер - это нехорошо.
    в общем, предлагаю сойтись на том, что eval() надо использовать аккуратно :)

    P.S. как я уже говорил в самом начале, все мои претензии к eval() связаны с тем, что я трепетно отношусь к security.

  11. dimzon541 Says:

    }}в общем, предлагаю сойтись на том, что eval() надо использовать аккуратно :)

    Естественно :) Как любит говорить мой коллега про некоторые "фичи":
    Фича "какая-то фича" это острая бритва при прмощи которой при неправильном обращении можно отрезать себе яй#а

    }}как я уже говорил в самом начале, все мои претензии к eval() связаны с тем, что я трепетно отношусь к security.

    Это и понятно :) Я вот в своё время даже экзамены сдавал http://www.microsoft.com/learning/exams/70-340.mspx

Leave a Reply

code