Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.10.2012, 19:51
at- at- вне форума
Новичок на форуме
Отправить личное сообщение для at- Посмотреть профиль Найти все сообщения от at-
 
Регистрация: 07.10.2012
Сообщений: 5

Несколько обработчиков в 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 или же есть более простые способы? Заранее спасибо
Ответить с цитированием
  #2 (permalink)  
Старый 07.10.2012, 21:35
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от at-
Несколько обработчиков в document.onclick
читайте об addEventListener и attachEvent
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #3 (permalink)  
Старый 08.10.2012, 16:07
at- at- вне форума
Новичок на форуме
Отправить личное сообщение для at- Посмотреть профиль Найти все сообщения от at-
 
Регистрация: 07.10.2012
Сообщений: 5

Сообщение от devote Посмотреть сообщение
читайте об addEventListener и attachEvent
Спасибо за наводку, по собственной дурости посчитал, что подобный функционал в фреймворках реализован.

Но возник вопрос по логике работы 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 говорится, что для отписки от события нужно передать сам обработчик

Цитата:
element.removeEventListener(type, listener, useCapture)
Parameters
listener
The listener parameter indicates the EventListener function to be removed.
Для тестов в document.onclick ввожу 3 события

// Вызывается при 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)?
Ответить с цитированием
  #4 (permalink)  
Старый 08.10.2012, 18:38
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Не совсем понял что там у вас, но может это будет полезным:

Элементу можно дать tabindex="0" и он сможет получать фокус, в том числе думаю и по клику. Соответсвенно и onblur событие должно происходить при потере фокуса.

Вот только при вылазинии календаря наверное фокус будет теряться..
Ответить с цитированием
  #5 (permalink)  
Старый 08.10.2012, 19:26
at- at- вне форума
Новичок на форуме
Отправить личное сообщение для at- Посмотреть профиль Найти все сообщения от at-
 
Регистрация: 07.10.2012
Сообщений: 5

Сообщение от danik.js Посмотреть сообщение
Не совсем понял что там у вас, но может это будет полезным:

Элементу можно дать tabindex="0" и он сможет получать фокус, в том числе думаю и по клику. Соответсвенно и onblur событие должно происходить при потере фокуса.

Вот только при вылазинии календаря наверное фокус будет теряться..
Спасибо за подсказку, но onblur сработает только после onclick в таком случае, а пользователю не всегда захочется нажать на календарь, чтобы закрыть его же по клику в другой области.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как c функцией .ajax() передать несколько значений в php? Faab jQuery 11 19.11.2013 12:03
Несколько простых скриптов JS koshsh Работа 1 08.05.2012 20:58
Обработчик click вызывается несколько раз или не всегда вызывается OlegJquery jQuery 2 21.07.2011 20:37
Несколько созданных элементов располагаются в одной строке. Как этого избежать? Hold Events/DOM/Window 1 21.01.2011 23:52
Несколько одинаковых таблиц. Обращение к отдельным элементам в них. zaytsewa Элементы интерфейса 7 11.11.2010 09:08