Я пытаюсь написать javascript для поиска элементов страницы относительно данного элемента, используя parentNode, firstChild, nextSibling, childNodes [] и так далее. Firefox портит это, вставляя текстовые узлы между каждым элементом html. Я читал, что могу победить это, удалив все пробелы между элементами, но я пробовал это, и это не работает. Есть ли способ написать код, который работает во всех современных браузерах?
Например:
<div id = "parent"><p id = "child">Hello world</p></div>
В IE parent.firstChild является дочерним элементом, но в Firefix - это фантомный текстовый элемент.
но если я вставлю текст между тегами, то это произойдет
Я видел это раньше, но не могу вспомнить марку / версию браузера.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


вы можете использовать tagName, чтобы проверить имя тега. Если не определено, то это ваш «фантомный» текстовый узел.
например
function getFirstTag(node) {
return ((node.firstChild.tagName) ? node.firstChild : node.firstChild.nextSibling);
}
У меня есть обходной путь. Вы можете вставить два метода ниже:
Element.prototype.fChild = function(){
var firstChild = this.firstChild;
while(firstChild != null && firstChild.nodeType === 3){
firstChild = firstChild.nextSibling;
}
return firstChild;
}
Element.prototype.nSibling = function(){
var nextSibling = this.nextSibling;
while(nextSibling != null && nextSibling.nodeType === 3){
nextSibling = nextSibling.nextSibling;
}
return nextSibling;
}
и теперь вы можете использовать:
document.getElementById("parent").fChild();
document.getElementById("parent").nSibling();
вместо:
document.getElementById("parent").firstChild;
document.getElementById("parent").nextSibling;
К сожалению, в IE это развалится, разрушив всякую надежду на кроссплатформенное решение. Конечно, методы можно использовать как автономные функции.
Приложив немного усилий, мы можем заставить эти функции работать в любом браузере.
Тип узла должен быть 1, а не 3. 1 - для элемента, 2 или undefined - для атрибута, а 3 - для текстового узла.
@David Brockman - Вы правы насчет значений чисел, но код правильный, потому что он избегает нежелательного nodeType (3).
Проверьте Ссылка на ядро DOM уровня 2, чтобы увидеть различные возможные типы узлов, чтобы вы могли отфильтровать нежелательные с помощью простого фрагмента JavaScript. Одним из решений является исправление объекта обезьяной (см. Ответ Вернихта) или, если вам не нравится исправление обезьяны, вы можете добавить эти методы в свою собственную библиотеку, или еще лучшим решением может быть использование причудливой библиотеки, такой как jQuery или опытный образец.
Вы должны проверить, что nodeType == 1.
if (el.nodeType === 1) {
return el;
}
Я написал для тебя небольшой класс обхода DOM (в основном скопированный с MooTools). Скачать здесь: http://gist.github.com/41440
DOM = function () {
function get(id) {
if (id && typeof id === 'string') {
id = document.getElementById(id);
}
return id || null;
}
function walk(element, tag, walk, start, all) {
var el = get(element)[start || walk], elements = all ? [] : null;
while (el) {
if (el.nodeType === 1 && (!tag || el.tagName.toLowerCase() === tag)) {
if (!all) {
return el;
}
elements.push(el);
}
el = el[walk];
}
return elements;
}
return {
// Get the element by its id
get: get,
walk: walk,
// Returns the previousSibling of the Element (excluding text nodes).
getPrevious: function (el, tag) {
return walk(el, tag, 'previousSibling');
},
// Like getPrevious, but returns a collection of all the matched previousSiblings.
getAllPrevious: function (el, tag) {
return walk(el, tag, 'previousSibling', null, true);
},
// As getPrevious, but tries to find the nextSibling (excluding text nodes).
getNext: function (el, tag) {
return walk(el, tag, 'nextSibling');
},
// Like getNext, but returns a collection of all the matched nextSiblings.
getAllNext: function (el, tag) {
return walk(el, tag, 'nextSibling', null, true);
},
// Works as getPrevious, but tries to find the firstChild (excluding text nodes).
getFirst: function (el, tag) {
return walk(el, tag, 'nextSibling', 'firstChild');
},
// Works as getPrevious, but tries to find the lastChild.
getLast: function (el, tag) {
return walk(el, tag, 'previousSibling', 'lastChild');
},
// Works as getPrevious, but tries to find the parentNode.
getParent: function (el, tag) {
return walk(el, tag, 'parentNode');
},
// Like getParent, but returns a collection of all the matched parentNodes up the tree.
getParents: function (el, tag) {
return walk(el, tag, 'parentNode', null, true);
},
// Returns all the Element's children (excluding text nodes).
getChildren: function (el, tag) {
return walk(el, tag, 'nextSibling', 'firstChild', true);
},
// Removes the Element from the DOM.
dispose: function (el) {
el = get(el);
return (el.parentNode) ? el.parentNode.removeChild(el) : el;
}
};
}();
// Now you can do:
DOM.getFirst("parent") // first child
// or
DOM.getFirst("parent", "p") // first p tag child
// or
var el = DOM.get("parent") // get element by id
DOM.getFirst(el) // first child
Я тестирую его на своем firefox 3.0.5 с firebug 1.2.1, и этого не происходит. какую версию вы используете?