Делегирование события
Приветсвую всех, уважаемые пользователи форума! :)
Написал такой скрипт для делегирования событий: (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, время: 23:50. |