У меня есть функция, похожая на jquery:
function(elem) {
return $('> someselector', elem);
};
Вопрос в том, как я могу сделать то же самое с querySelector()
?
Проблема в том, что >
селектор querySelector()
требует явного указания родителя. Есть ли обходной путь?
javascript
css-selectors
selectors-api
обескураженный
источник
источник
Ответы:
Хотя это не полный ответ, вам следует следить за W3C Selector API v.2, который уже доступен в большинстве браузеров, как настольных, так и мобильных, за исключением IE (Edge, похоже, поддерживает): см. Полный список поддержки .
function(elem) { return elem.querySelectorAll(':scope > someselector'); };
источник
:scope
это все еще указано на drafts.csswg.org/selectors-4/#the-scope-pseudo . Пока что удален только<style scoped>
атрибут; неясно, приведет ли это к:scope
удалению (поскольку это<style scoped>
был важный вариант использования:scope
).Вы не можете. Нет селектора, который имитировал бы вашу отправную точку.
Способ, которым jQuery делает это (в большей степени из-за
qsa
поведения, которое им не нравится), заключается в том, что они проверяют,elem
есть ли идентификатор, а если нет, они временно добавляют идентификатор, а затем создают полную строку селектора.В основном вы бы сделали:
var sel = '> someselector'; var hadId = true; if( !elem.id ) { hadID = false; elem.id = 'some_unique_value'; } sel = '#' + elem.id + sel; var result = document.querySelectorAll( sel ); if( !hadId ) { elem.id = ''; }
Это, конечно, не код jQuery, но, насколько я помню, это в основном то, что они делают. Не только в этой ситуации, но и в любой ситуации, когда вы запускаете селектор из контекста вложенного элемента.
Исходный код для Sizzle
источник
Завершено: полифил прицела
Как упоминал avetisk , Selectors API 2 использует псевдоселектор. Чтобы это работало во всех браузерах (которые поддерживают ), вот полифилл
:scope
querySelector
(function(doc, proto) { try { // check if browser supports :scope natively doc.querySelector(':scope body'); } catch (err) { // polyfill native methods if it doesn't ['querySelector', 'querySelectorAll'].forEach(function(method) { var nativ = proto[method]; proto[method] = function(selectors) { if (/(^|,)\s*:scope/.test(selectors)) { // only if selectors contains :scope var id = this.id; // remember current element id this.id = 'ID_' + Date.now(); // assign new unique id selectors = selectors.replace(/((^|,)\s*):scope/g, '$1#' + this.id); // replace :scope with #ID var result = doc[method](selectors); this.id = id; // restore previous id return result; } else { return nativ.call(this, selectors); // use native code for other selectors } } }); } })(window.document, Element.prototype);
Применение
node.querySelector(':scope > someselector'); node.querySelectorAll(':scope > someselector');
По историческим причинам мое предыдущее решение
На основе всех ответов
// Caution! Prototype extending Node.prototype.find = function(selector) { if (/(^\s*|,\s*)>/.test(selector)) { if (!this.id) { this.id = 'ID_' + new Date().getTime(); var removeId = true; } selector = selector.replace(/(^\s*|,\s*)>/g, '$1#' + this.id + ' >'); var result = document.querySelectorAll(selector); if (removeId) { this.id = null; } return result; } else { return this.querySelectorAll(selector); } };
Применение
elem.find('> a');
источник
Date.now()
не поддерживается старыми браузерами и может быть заменен наnew Date().getTime()
Если вы хотите в конечном итоге найти прямых потомков (а не например
> div > span
), вы можете попробовать Element.matches () :const elem = document.body const elems = [...elem.children].filter(e => e.matches('b')) console.log(elems)
<a>1</a> <b>2</b> <b>3</b> <b>4</b> <s>5</s>
источник
ЗАПРОС
Лично я бы взял ответ Патрика Ду и +1 его ответ, мой ответ - поиск альтернативного решения. Я не думаю, что он заслуживает отрицательного голоса.
Вот моя попытка:
function q(elem){ var nodes = elem.querySelectorAll('someSeletor'); console.log(nodes); for(var i = 0; i < nodes.length; i++){ if(nodes[i].parentNode === elem) return nodes[i]; } }
см. http://jsfiddle.net/Lgaw5/8/
источник
querySelector
, а это значит, что:eq()
его нельзя использовать. Даже если бы это было возможно, ваш селектор вернул бы элемент:eq()
в соответствии с его внешним видом на странице, а не:eq()
в индекс его родительского элемента (откуда вы и получаетеidx
).elem
индекс находится под индексом 4, но есть предыдущий брат, который имеет другойtagName
, но в него вложен элемент с сопоставлениемtagName
, этот вложенный элемент будет включен в результаты до того, на который вы нацеливаетесь, снова отбрасывая индекс. Вот пример$('> someselector', elem);
; o)Если вам известно имя тега элемента, который вы изучаете, вы можете использовать его в селекторе для достижения желаемого.
Например, если у вас есть a
<select>
, у которого есть<option>
s и<optgroups>
, и вам нужны только<option>
s, которые являются его непосредственными дочерними элементами, а не те, которые находятся внутри<optgoups>
:<select> <option>iPhone</option> <optgroup> <option>Nokia</option> <option>Blackberry</option> </optgroup> </select>
Итак, имея ссылку на элемент select, вы можете - что удивительно - получить его непосредственных дочерних элементов следующим образом:
selectElement.querySelectorAll('select > option')
Кажется, он работает в Chrome, Safari и Firefox, но не тестировался в IE. знак равно
источник
<ul id="start"> <li>A</li> <li> <ul> <li>b</li> <li>c</li> </ul> </li> </ul> var result = document.getElementById('start').querySelectorAll('ul>li');
-> Все 4 элемента li будут выбраны!<select>
элемента в одном родителе.Ниже приводится упрощенный общий метод выполнения любого запроса селектора CSS только для прямых дочерних элементов - он также учитывает комбинированные запросы, например
"foo[bar], baz.boo"
:var count = 0; function queryChildren(element, selector) { var id = element.id, guid = element.id = id || 'query_children_' + count++, attr = '#' + guid + ' > ', selector = attr + (selector + '').replace(',', ',' + attr, 'g'); var result = element.parentNode.querySelectorAll(selector); if (!id) element.removeAttribute('id'); return result; } *** Example Use *** queryChildren(someElement, '.foo, .bar[xyz="123"]');
источник
Там в запросе-относительный Lib, что очень удобно для замены запроса-селектор . Он полифицирует дочерний селектор
'> *'
и:scope
(включая IE8), а также нормализует:root
селектор. Кроме того, она обеспечивает некоторый специальный относительный pseudos как:closest
,:parent
,:prev
,:next
, на всяком случае.источник
Это сработало для меня:
Node.prototype.search = function(selector) { if (selector.indexOf('@this') != -1) { if (!this.id) this.id = "ID" + new Date().getTime(); while (selector.indexOf('@this') != -1) selector = selector.replace('@this', '#' + this.id); return document.querySelectorAll(selector); } else return this.querySelectorAll(selector); };
вам нужно будет передать @this keywork перед>, если вы хотите найти непосредственных дочерних элементов.
источник
проверьте, есть ли у элемента идентификатор, еще добавьте случайный идентификатор и выполните поиск на его основе
function(elem) { if(!elem.id) elem.id = Math.random().toString(36).substr(2, 10); return elem.querySelectorAll(elem.id + ' > someselector'); };
будет делать то же самое, что и
$("> someselector",$(elem))
источник