Делегирование события
Приветсвую всех, уважаемые пользователи форума! :)
Написал такой скрипт для делегирования событий:
(function() {
var d = document.documentElement,
m = d.matchesSelector || d.webkitMatchesSelector || d.oMatchesSelector || d.mozMatchesSelector || d.msMatchesSelector;
Element.prototype.addEventDelegate = function(type, selector, fn) {
this.addEventListener(type, function(e) {
e = e && e.target || window.event.srcElement;
if(m.call(e, selector)) {
fn.call(e);
}
}, false);
}
})();
window.onload = function() {
document.body.addEventDelegate('click', 'p', function() {
alert('Вы кликнули по тэгу "p"!');
});
}
Всё работает, но... когда кликаешь по более вложенному элементу, то событие для родительского элемента не срабатывает. Нужно, чтобы всё работало как в jQuery. Кто-нибудь знает, как более грамотно так сделать? Спасибо. |
Цитата:
|
while (e != this) {
//работаем
e = e.parentNode;
}
BallsShaped, правильно ответил |
К слову в черновик метод попал под именем matches(), так что исправь. Пока что все браузеры используют старые префикснутые matchesSelector()
Вобще странно. Тогда и document.querySelector() надо было переименовать в document.query() |
(function() {
var d = document.documentElement,
m = d.matchesSelector || d.webkitMatchesSelector || d.oMatchesSelector || d.mozMatchesSelector || d.msMatchesSelector || d.matches;
Element.prototype.addEventDelegate = function(type, selector, fn) {
this.addEventListener(type, function(e) {
e = e && e.target || window.event.srcElement;
if(m.call(e, selector + ', ' + selector + ' *')) {
fn.call(e);
}
}, false);
}
})();
Вот так пока сделал, но думаю, что сделаю по другому как время будет. :) |
Poznakomlus, спасибо, суть уловил. :)
|
Цитата:
|
danik.js, понял. :)
Доделал. :)
(function() {
var d = document.documentElement,
m = d.matches || d.webkitMatchesSelector || d.oMatchesSelector || d.mozMatchesSelector || d.msMatchesSelector;
Element.prototype.addEventDelegate = function(type, selector, fn) {
this.addEventListener(type, function(e) {
var t = e && e.target || window.event.srcElement;
while(t != this) {
if(m.call(t, selector)) {
fn.call(t, e);
break;
}
t = t.parentNode;
}
}, false);
}
})();
|
Ruslan_xDD, хотя фиг его знает)) Мож до релиза еще раз пять сменят название ))
|
danik.js, только вот хрен знает как будет работать, если браузер вообще не поддерживает matches. :) Может как-нибудь через querySelector запилить?
|
Посмотри как это сделано в jQuery
|
Цитата:
Цитата:
W3C модель: addEventListener + event.target old IE модель: attachEvent + window.event.srcElement |
danik.js, это я сюда тестовый пример кинул, я сам там для себя пишу мини-библиотеку, там всё это предусмотрено, а сюда просто написал понятный код, так как код из библы написан в стиле ниндзя и может быть не понятен. :D
.......
_e = 'addEventListener' in w ? 'addEventListener' : 'attachEvent';
_eD = dE.matches || dE.matchesSelector || dE.webkitMatchesSelector || dE.oMatchesSelector || dE.mozMatchesSelector || dE.msMatchesSelector;
.......
.......
.......
e: function(a, b) { //event
this[_e](a, b, false);
return this;
},
eD: function(a, b, c) { //event delegate
this.e(a, function(e) {
var t = e && e.target || w.event.srcElement;
while(t != this) {
if(_eD.call(t, b)) {
c.call(t, e);
break;
}
t = t.parentNode;
}
});
return this;
},
.......
|
Ну мог бы хотя бы необфусцированный код показать. Или ты так и пишешь ? :D
Цитата:
|
danik.js, я сразу так и пишу, a,b,c и т.д., так как для себя пишу, мне лично всё понятно будет. :D
Цитата:
|
Цитата:
|
Цитата:
|
danik.js, да, бывает такое, когда смотрю старые исходники, которые писал около месяца назад и вообще ничего не понимаю. Но сейчас я стараюсь оставлять комментарии, чтобы не запутаться. :) Только вот когда уже буду ставить скрипт на сайт, то все комментики потру и всё сделаю в одну строку. :D Я конечно понимаю, что код мой нафиг никому не нужен будет, но сделаю так из принципа. :D
|
Цитата:
|
danik.js, ну это то понятно, я оставляю комментарии около самих ф-ций, чтобы не вспоминать, что она означатает. Например: cA - это classAdd, eD - eventDelegate и т.д.
Цитата:
|
Цитата:
А вот за a, b, c сразу на хлеб да воду сажать. :) |
Цитата:
|
Цитата:
ужас зачем так мало? Цитата:
|
Цитата:
Цитата:
|
Цитата:
http://closure-compiler.appspot.com/home http://compressorrater.thruhere.net/ ................................................. |
Цитата:
/**
* Sets a new editsession to use. This method also emits the `'changeSession'` event.
* @param {EditSession} session The new session to use
*
*
**/
this.setSession = function(session) {
|
Ладно, уговорили. :)
delegate: function(type, selector, callback) {
this.event(type, function(event) {
var target = event && event.target || w.event.srcElement;
while(target != this) {
if(matches.call(target, selector)) {
callback.call(target, event);
break;
}
target = target.parentNode;
}
});
return this;
},
event: function(type, callback) {
var self = this;
if('addEventListener' in self) self.addEventListener(type, callback, false);
else self.attachEvent('on' + type, function(event) {
callback.call(self, event);
});
return this;
},
|
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
var d = document,
h = d.documentElement,
i, mk,
w = window;
(function() {
mk = function(selector) {
if('mk' in this) return mk.call(typeof selector == 'object' ? selector : d.querySelector(selector));
for(i in _mk) this[i] = _mk[i];
return this;
};
var XMLRequest = XMLHttpRequest || w.ActiveXObject && function() {
return new ActiveXObject('Msxml2.XMLHTTP');
},
reqTimeout,
classList = 'classList' in h,
matches = h.matches || h.matchesSelector || h.webkitMatchesSelector || h.oMatchesSelector || h.mozMatchesSelector || h.msMatchesSelector || function(selector) {
var elems = this.parentNode.querySelectorAll(selector);
for(i=0; i<elems.length; i++) if(elems[i] === this) return true;
},
_mk = {
append: function() {
var childs = arguments;
for(i=0; i<childs.length; i++) this.appendChild(childs[i]);
return this;
},
classAdd: function(name) {
if(classList) this.classList.add(name);
else this.className += this.classHas(name) ? '' : (this.className ? ' ' + name : name);
return this;
},
classHas: function(name) {
return classList ? this.classList.contains(name) : !!~(' ' + this.className + ' ').indexOf(' ' + name + ' ');
},
classRemove: function(name) {
if(classList) this.classList.remove(name);
else if(this.classHas(name)) this.className = this.className.replace(new RegExp(' ?' + name + ' ?'), '');
return this;
},
classToggle: function(name) {
if(classList) this.classList.toggle(name);
else this.classHas(name) ? this.classRemove(name) : this.classAdd(name);
return this;
},
delegate: function(type, selector, callback) {
this.event(type, function(event) {
var target = event && event.target || w.event.srcElement;
while(target != this) {
if(matches.call(target, selector)) {
callback.call(target, event);
break;
}
target = target.parentNode;
}
});
return this;
},
effect: function(name, remove) {
var self = this;
self.classToggle('mk-' + name);
if(remove) setTimeout(function() {
self.remove();
}, 500);
return self;
},
event: function(type, callback) {
var self = this;
if('addEventListener' in self) self.addEventListener(type, callback, false);
else self.attachEvent('on' + type, function(event) {
callback.call(self, event);
});
return this;
},
props: function(props) {
for(i in props) this[i] = props[i];
return this;
},
query: function(selector) {
return this.querySelector(selector);
},
remove: function() {
this.parentNode.removeChild(this);
},
};
mk.create = function(tagName, props) {
var elem = d.createElement(tagName);
mk(elem).props(props);
return elem;
};
mk.message = function(icon, title, message, clicked) {
var elem = mk.create('div', {className: 'mk-msg mk-show'}),
img = mk.create('img', {align: 'left', alt: '', src: icon}),
div = mk(mk.create('div')).append(mk.create('b', {textContent: title}), mk.create('span', {textContent: message})),
params = arguments.callee;
elem = mk(elem).append(img, div);
mk('#mk-msgs').insertBefore(elem, params.len === 0 ? null : params.tmp);
params.len = params.len + 1 || 1;
params.tmp = elem;
var timeout = setTimeout(elem.onclick = function() {
elem.effect('show', true);
params.len--;
clearTimeout(timeout);
if(clicked) clicked();
}, 4E3);
elem.clientWidth;
elem.effect('show');
};
mk.request = function(url, params, callback, error) {
var keys = [],
req = new XMLRequest(),
self = this;
req.open('POST', url, true);
req.onreadystatechange = function() {
if(req.readyState != 4) return;
clearTimeout(reqTimeout);
if(req.status == 200) callback.call(self, req.responseText);
else if(error) error(req.statusText);
};
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
for(i in params) keys.push(i + '=' + params[i]);
req.send(keys.join('&') || null);
reqTimeout = setTimeout(function() {
req.abort();
if(error) error();
}, 5E3);
};
})();
ТЕСТ! :) На class* не знаю, ставить регулярку или оставить такой костыль? И ещё вопрос: насколько кроссбраузерен будет XMLHttp запрос (mk.request)? Ничего не упустил? |
Цитата:
как хаки пояснять без комментариев? это хороший код ... плохие браузеры\стандарты и плохое API :) |
| Часовой пояс GMT +3, время: 04:43. |