Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Добавление обработчика события, как сделать, чтоб в Опере 8.5- работало? 
:(
    Опции темы
12345c
Дата 21.12.2006, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Известно, что есть функция добавления обработчика к фиксированнному событию, например, к onload. Смысл её такой, что если в обработчике обнаруживается function, то он переопределяется как новая функция, составленная из последовательности двух. С такой функцией добавления нет проблем, она работает. Но понадобился добавитель к переменному обработчику. Проблемы началисть с того, что передать объект-обработчик как параметр не получилось - передаётся почему-то не объект, а его копия (потому что внутри функции присваивание работает, а по окончании значение объекта-обработчика остаётся старым. Вот пример неработающего кода, но не будем на нём долго останавливаться:
Код
onresize=function(){abcde=12345;
fghij=67890;}
DebMonScrl=function(){a=12345;
b=67890;}
addEvent=function(eve,f){var f0;
  eve=typeof(eve)=='function'?(f0=eve,new Function('ev','('+f0.toString()+')(ev);('+f.toString()+')(ev)')):f;
  alert(eve)
}
addEvent(onresize,DebMonScrl);
alert(onresize)
Видим, что прекрасно присваивается, а "потом - опять за старое". Чем его лечить? Делать нечего, методы должны быть суровые. Берём имя обработчика и грубым выполнением выжигаем в нём новое значение:
Код
addEvent=function(evS,f){var f0;
  eval(evS+'='+(typeof(f0=eval(evS))=='function'?new Function('ev','('+f0.toString()+')(ev);('+f.toString()+')(ev)'):f).toString()+';');
return f;}
//...далее можем:
addEvent('onresize',addEvent('onscroll',function(){alert(12345);}));
Нормально, работает, но тут незадача случается с Оперой: до версии 9.00 она отказывается выполнять в eval() присваивание функции или вообще употребление функции - диагностика невнятная. Более-менее чётко говорит об этом она, начиная с 8.0, что у них, мол, это не принято. Как же быть? Ради гибкости скрипта ударились во все тяжкие, применили eval, получили желаемое (переменный обработчик), а в старых Операх пользователям придётся прозябать или разработчикам работать по-старинке?

Кто предложит решение? (до версии Опера 8.53)) Чтобы присвоить переменному обработчику новую функцию, но не применять function в eval? И вообще, почему не присвоилась функция в первом случае и можно ли сделать красИвее?

Дополнение: Получилось решение, оставляю задачку для тренировки умов, она несложная, из серии "не в лоб, так по лбу" smile.
...А Опера 9.0 с отрисовкой заметно помедленнела. Интересно, исправят ли, или это дань продвинутости?

Это сообщение отредактировал(а) 12345c - 21.12.2006, 23:51
PM WWW   Вверх
Zeroglif
Дата 21.12.2006, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(12345c @  21.12.2006,  22:14 Найти цитируемый пост)
Проблемы началисть с того, что передать объект-обработчик как параметр не получилось - передаётся почему-то не объект, а его копия (потому что внутри функции присваивание работает, а по окончании значение объекта-обработчика остаётся старым.

В javascript всё передаётся по значению! В твоём случае ты передаёшь ссылки (это и есть значение для объектных типов) на анонимные функции. Конструктор строит новую функцию, обратившись по ссылкам к "переменным" (и f0). При этом свойство window с именем onresize как хранило ссылку на свою анонимную функцию, так и хранит, чтобы что-то изменить надо сделать что-то вроде onresize = eve, тогда ты "забьёшь" предыдущую ссылку новой...
PM MAIL WWW   Вверх
12345c
Дата 22.12.2006, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Получается, что eval+имя - единственно верное направление.
PM WWW   Вверх
Nicholas_S
Дата 22.12.2006, 00:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 486
Регистрация: 12.10.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 19



12345c, постановка задачи ясна. Единственное, у меня твой второй пример не работает ни в 8, ни в 9ой версиях Оперы.
Есть одно решение, насколько оно тебя удовлетворит не знаю, но работает и в 8ой, и в 9ой Опере. За оптимальность не отвечаю, предлагаю только ход мыслей:
Код

...

Function.prototype.addFunc = function(selfName, func)
{
    eval(selfName + ' = function(){var f0='+this.toString() + '; var f1=' + func.toString() +'; f0(); f1();}');
}
onresize.addFunc('onresize', DebMonScrl);

Что неудобно, так это указание самого имени функции, к которой добавляем новую. Может быть сделаешь удобнее.


--------------------
...все в мире относительно
PM   Вверх
Zeroglif
Дата 22.12.2006, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



Цитата(12345c @  22.12.2006,  00:17 Найти цитируемый пост)
Получается, что eval+имя - единственно верное направление.

Зачем eval, если известно событие и его имя передаётся аргументом?
PM MAIL WWW   Вверх
12345c
Дата 22.12.2006, 02:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Да, можно addEventListener. Только покрасивее со сцеплением функций не придумывается.

Nicholas_S, я примерно так решил (функция в строке), только без прототипа, потому что получается тавтология с именами. (И важно, чтобы параметр у функции был.) Или придётся брать String.prototype.addFunc , чтобы не повторяться.
PM WWW   Вверх
Sardar
Дата 22.12.2006, 04:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Цитата(12345c @  21.12.2006,  21:14 Найти цитируемый пост)
Но понадобился добавитель к переменному обработчику. Проблемы началисть с того, что передать объект-обработчик как параметр не получилось - передаётся почему-то не объект, а его копия (потому что внутри функции присваивание работает, а по окончании значение объекта-обработчика остаётся старым.

Что то жуткое читаю и не врубаюсь в смысл слов... правильно ли я понял, что ты думал аргументы передаются по указателю (изменяемые)? Тогда вообще не понятно, в каждом учебнике же лежит, что всё передаётся (даже примитивы, помним что они immutable) по ссылке, присваивание которой просто изменяет ссылку, а не обьект, на который она ссылалась. Так и в Java и в C#... языки поддерживающие указатели по пальцам можно пересчитать (PHP, C/C++, ...? )

Термин указатель == ссылка, '=' оператор для которой определён как изменяющий значение обьекта, на который ссылка указывает (разыменование). Сишные указатели в сторону smile 
В современных языках только примитивы ещё могут по ссылке изменяться, и то не всегда. Для остальных типов меняется именно значение самой ссылки, а не обьект на который она указывает


Кстати вызов toString() на closure выложит его исходник, естественно контекст заменяется на тот, что в eval'е (от window/global). Что ты вообще хотел этим сделать не пойму...

Интересно кому в наше время ещё нужны традиционные события... А если не извращаться, то будет так:
Код
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">

function createDispatcher() {
    var handlers = [];
    //callable by event
    var eventDispatcher = function(ev) {
        for(var i=0; i < handlers.length; i++) handlers[i](ev);
    }
    
    //add new handler
    eventDispatcher.addHandler = function(handler) {
        handlers.push(handler);
    }
    return eventDispatcher;
}

function addEvent(obj, event_type, new_handler) {
    if(!obj[event_type] || !obj[event_type].addHandler) { //install new dispatcher
        var disp = createDispatcher();
        if(obj[event_type]) disp.addHandler(obj[event_type]);
        obj[event_type] = disp;
    }
    obj[event_type].addHandler(new_handler);
}


window.onresize = function() {
    document.getElementById("dbg").innerHTML = "Original handler: " + document.documentElement.offsetWidth + ", " + document.documentElement.offsetHeight;
}

var another = function() {
    document.getElementById("dbg1").innerHTML = "Added handler: " + document.documentElement.offsetWidth + ", " + document.documentElement.offsetHeight;
}

var third = function() {
    document.getElementById("dbg2").innerHTML = "Added handler: " + arguments.callee.test++;
}
third.test = 0;

addEvent(window, 'onresize', another);
addEvent(window, 'onresize', third);
</script>
</head>
<body>
    <div id="dbg"></div>
    <div id="dbg1"></div>
    <div id="dbg2"></div>
</body>
</html>



P.S. код отвратителен по читабельности, неужели нельзя давать нормальные имена и разбивать по строкам? попытка "закодировать" тривиальный код не одно и тоже с попыткой написать код гениальный, но мало кому понятный smile

Добавлено @ 04:33 
Цитата(Zeroglif @  21.12.2006,  22:56 Найти цитируемый пост)
В javascript всё передаётся по значению! 

Zeroglif, больше такого никому не говори smile
Если желаешь поспорить, то в начале в личку, флейм тут не нужен.

Цитата(12345c @  21.12.2006,  23:17 Найти цитируемый пост)
Получается, что eval+имя - единственно верное направление. 

А зачем тебе нужна возможность изменять "по указателю"? Ведь можно без лишнего сексу передать обьект и мя поля, благо всё в JS (да и в любом другом ECMA) навигируеться так (глобальные помним через window[name], по стандарту global[name]).

Nicholas_S, зачем доставать код closure/функции? Вдруг она привязана контекстом к какому нибудь окружению, а обратив всё в текст мы теряем контекст, т.е. теряем вообще смысл и мощь closure.

P.S. парни, я понимаю что праздники, но харе столько пить! smile 


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Nicholas_S
Дата 22.12.2006, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 486
Регистрация: 12.10.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 19



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


--------------------
...все в мире относительно
PM   Вверх
12345c
Дата 22.12.2006, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Круглый
****


Профиль
Группа: Vingrad developer
Сообщений: 2018
Регистрация: 26.12.2005
Где: наша не пропадала ?

Репутация: 57
Всего: 101



Я не думал, но надо было как-то передать указатель на обработчик события. Ничего, кроме имён, не получилось.

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

Про closure я думал, но непонятно, как его использовать. В общем, пока пользуюсь своим кодом (буду применять в соседней, ещё не созданной теме smile ).

Стиль письма - дело привычки. Мне, например "{", стоящие отдельно на строке, мешают. А по опросу, этот стиль даже более предпочтителен в обиходе, чем они же, прилепленные к оператору.
PM WWW   Вверх
Sardar
Дата 22.12.2006, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Цитата(12345c @  22.12.2006,  14:02 Найти цитируемый пост)
Про closure я думал, но непонятно, как его использовать

createDispatcher() в примере как работают closure. Там создаёться в контексте вызова переменная handlers, которая будет своей для каждого диспетчера. closure вообще вещь мощная. Это по сути некий код, привязываемый к разному контексту. Сам же контекст может содержать ссылки на что угодно.

Язык разрабатыва(л)(ю) (теорию только), для эффективности разделил концепцию closure на именнованные блоки и собственно closure. Вышло удобно smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Zeroglif
Дата 22.12.2006, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 644
Регистрация: 22.9.2005

Репутация: 28
Всего: 66



12345c

Возможно тебе пригодится вариант регистрации событий через свойства объекта. Просто ещё один самобытный пример.
PM MAIL WWW   Вверх
Sardar
Дата 22.12.2006, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Кстати в этой теме сразу видим, как в JS (любом скриптовом языке) не хватает getters/setters (которые реализованы в JS от мозиллы, а также в Rhino в Java6... да вообще везде, кроме JScript в ИЕ). А перегрузка операторов вообще была бы супер, представь как в C#:
Код

window.onclick += my_handler;
window.onclick += my_another_handler;
...
window.onclick -= my_handler;


function Test {
    this.event = new HandlersList(); //тут бы нужен интерфейс Callable, дабы быть как Function
    .....

    this.event(event_object); //вызывает все handlers
}

var a = new Test();
a.event += my_handler;



P.S. впрочем JS как язык вообще довольно сильно отстаёт от "современных течений" smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0912 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.