Обновлен заголовок, чтобы лучше отражать то, что я пытаюсь сделать.
Короче говоря, для разных элементов dom существуют разные конструкторы, и не все они имеют общий прототип. Я ищу способ добавить свойство функции к каждому элементу DOM, изменив эти прототипы, но я не уверен, как их найти.
Например, я мог бы сделать что-то вроде этого:
function enhanceDom (tagNames, methods) {
var i=-1, tagName;
while (tagName=tagNames[++i]) {
var tag=document.createElement(tagName);
if (!(tag && tag.constructor)) continue;
for (var methodName in methods) {
tag.constructor.prototype[methodName]=methods[methodName];
}
}
}
var thingsToEnhance = ['a','abbr','acronym','address'/* on and on... */];
enhance(thingsToEnhance, {
doStuff : function(){
/* ... */
},
doOtherStuff : function(){
/* ... */
}
/* ... */
});
Конечно, я хотел бы сделать это, не перечисляя каждый элемент html. Может ли кто-нибудь придумать лучший способ?
(исходный вопрос следует)
Цель – заставить getElementsByClassName
работать на любом узле DOM в любом браузере.
Это было сделано раньше (вроде), но вот мой шанс.
У меня есть вопрос: есть ли хороший способ заставить это работать с динамически создаваемыми элементами? Кажется, что элементы HTML DOM не имеют общего предсказуемого прототипа, куда можно было бы добавить getElementsByClassName
... Или я что-то упустил?
Вот что у меня есть на данный момент (редактировать — обновляется по мере обсуждения).
(function(){
var fn = 'getElementsByClassName';
// var fn = 'gEBCN'; // test
if (typeof document[fn] != 'undefined') return;
// This is the part I want to get rid of...
// Can I add getByClass to a single prototype
// somewhere below Object and be done with it?
document[fn]=getByClass;
withDescendants(document, function (node) {
node[fn]=getByClass;
});
function withDescendants (node, callback, userdata) {
var nodes = node.getElementsByTagName('*'), i=-1;
while (node=nodes[++i]) {
callback(node, userdata);
}
return userdata;
}
function getByClass (className) {
return withDescendants(this, getMatches, {
query:new RegExp('(^|\\s+)' + className + '($|\\s+)'),
found:[]
}).found;
}
function getMatches (node, data) {
if (node.className && node.className.match(data.query)) {
data.found.push(node);
}
}
}());
Он хорошо работает с контентом, загруженным до загрузки скрипта, но новые динамически созданные элементы не получат метод getElementsByClassName
. Любые предложения (кроме setInterval, пожалуйста)?
getElementsByTagName('*')
, я никогда не думал об этом... на самом деле я мог бы использоватьe.getElementsByTagName('*')||e.all
и поддерживать все до IE4, я думаю :) - person Dagg Nabbit   schedule 07.09.2010getElementById
. - person Dagg Nabbit   schedule 07.09.2010className
, не знал, что он так широко поддерживается. - person Dagg Nabbit   schedule 07.09.2010