Несколько обработчиков в document.onclick
Сразу прощу прощения, если написано сильно криво, с js сталкиваться особо не приходится :)
Всё началось с необходимости аналога onBlur для div'a - при нажатии появляется подобие календаря, при клике в любую область - календарь пропадает. Первым пришедшим в голову решением было: // Удаляется div с календарём // Очищается onclick function closeCalendar(calendar) { if (typeof(calendar) === 'string') calendar = document.getElementById(calendar); if (!calendar) return; calendar.parentNode.removeChild(calendar); document.onclick = null; } function openCalendar(clr) { if (!clr || !clr.id) return; var id = clr.id.split('_').slice(2).join('_'); // Сперва вызываем onclick, чтобы закрыть предыдущий календарь, // если он уже открывался if (document.onclick) document.onclick(); document.onclick = function(e) { var targ; if (!e) var e = window.event; if (e.target) targ = e.target; else if (e.srcElement) targ = e.srcElement; if (targ.nodeType == 3) targ = targ.parentNode; if (targ != document.getElementById('open_calendar_' + id)) closeCalendar('calendar_' + id); }; /* Создаётся div И в него вставляется таблица с календарём */ } Но при таком подходе document.onclick полностью занят логикой с календарём. Для возможности использовать onclick добавил следующую конструкцию: var docOnClickObj = function() { if (typeof arguments.callee.instance=='undefined') { arguments.callee.instance = new function() { var _f = {}; // Имя + функция = добавить // Имя = удалить this.Func = function(newFuncName, newFunc) { if (typeof newFuncName != 'undefined') { if (typeof newFunc != 'undefined') _f[newFuncName] = newFunc; else delete _f[newFuncName]; } return _f; } this.addFunc = function(f_name, f) {this.Func(f_name, f);}; this.delFunc = function(f_name) {this.Func(f_name);}; this.docOnClick = function() {var a = docOnClickObj().Func(); for (var f in a) {a[f]();}}; document.onclick = this.docOnClick; }; } return arguments.callee.instance; }; function closeCalendar(calendar) { ... docOnClickObj().delFunc('close_calendar'); } function openCalendar(clr) { ... if (docOnClickObj().Func()['close_calendar']) docOnClickObj().Func()['close_calendar'](); var f = function(e) {...} docOnClickObj().addFunc('close_calendar', f); } Хотелось бы узнать мнение понимающих людей: имеет ли смысл использовать синглтон для задания набора функций при document.onclick или же есть более простые способы? Заранее спасибо :) |
Цитата:
|
Цитата:
Но возник вопрос по логике работы removeEventListener/deatachEvent. Для добавления\удаления обработчиков использую две функции из админки django (core.js): function addEvent(obj, evType, fn) { if (obj.addEventListener) obj.addEventListener(evType, fn, false); else if (obj.attachEvent) var r = obj.attachEvent('on' + evType, fn); } function removeEvent(obj, evType, fn) { if (obj.removeEventListener) obj.removeEventListener(evType, fn, false); else if (obj.detachEvent) obj.detachEvent('on' + evType, fn); } В описании к removeEventListener говорится, что для отписки от события нужно передать сам обработчик Цитата:
// Вызывается при onload function init() { addEvent(document, 'click', function(){console.log('init');}); } function closeCalendar(calendar) { ... // вместо функции отдаю null/ function(){} removeEvent(document, 'click', null); calendar.parentNode.removeChild(calendar); } function openCalendar(clr) { if (!clr || !clr.id) return; var id = clr.id.split('_').slice(2).join('_'); var f = function(e) { var targ = getTarget(e); if (targ != document.getElementById('open_calendar_' + id)) closeCalendar('calendar_' + id); }; addEvent(document, 'click', function(){console.log('opencalendar0');}); addEvent(document, 'click', f); addEvent(document, 'click', function(){console.log('opencalendar1');}); В конечном итоге в лог попадают все сообщения init/opencalendarN, а удаляется событие для закрытия календаря, которое явно не указано. Пробовал в опере, фф и хроме - везде календарь открывается и закрывается правильно, а в лог падают три сообщения. Почему на удаление попадает именно var f = function(e)? |
Не совсем понял что там у вас, но может это будет полезным:
Элементу можно дать tabindex="0" и он сможет получать фокус, в том числе думаю и по клику. Соответсвенно и onblur событие должно происходить при потере фокуса. Вот только при вылазинии календаря наверное фокус будет теряться.. |
Цитата:
|
Часовой пояс GMT +3, время: 20:58. |