Этот документ является неофициальным переводом исходной английской версии Selectors API Level 1. Обратите внимание на то, что оригинальная версия документа существует только на английском языке. Данный перевод может содержать неточности и ошибки. Перевод выполнил Кирилл Топольян, 2016.

W3C

Selectors API Level 1

Рекомендация W3C от 21 февраля 2013

Эта версия:
http://www.w3.org/TR/2013/REC-selectors-api-20130221/
Последняя версия:
http://www.w3.org/TR/selectors-api/
Предыдущие версии:
http://www.w3.org/TR/2012/PR-selectors-api-20121213/
http://www.w3.org/TR/2012/WD-selectors-api-20120628/
http://www.w3.org/TR/2009/CR-selectors-api-20091222/
http://www.w3.org/TR/2008/WD-selectors-api-20081114/
http://www.w3.org/TR/2007/WD-selectors-api-20071221/
http://www.w3.org/TR/2007/WD-selectors-api-20071019/
http://www.w3.org/TR/2006/WD-selectors-api-20060926/
http://www.w3.org/TR/2006/WD-selectors-api-20060525/
Редакторы:
Anne van Kesteren (Mozilla) <annevk@annevk.nl>
Lachlan Hunt <lachlan.hunt@lachy.id.au>

Смотрите страницу исправлений для этого документа, которая может содержать некоторые нормативные изменения.

Также смотрите переводы.


Аннотация

Селекторы, которые широко используются в CSS, являются паттернами которые соответствуют элементам в древовидной структуре [SELECT][CSS21]. Спецификация Selectors API определяет методы получения нод Element из DOM сопоставлением группы селекторов. Часто бывает желательным выполнять операции DOM на определенном наборе элементов в документе. Эти методы упрощают процесс приобретения определенных элементов, особенно по сравнению с более многословными техниками, определенными и используемыми в прошлом.

Статус этого документа

Этот раздел описывает статус данного документа на момент его публикации. Другие документы могут заменять этот документ. Со списком текущих публикаций W3C и последней ревизией этого технического доклада можно ознакомиться в индексе технических отчетов W3C, http://www.w3.org/TR/.

Рабочая группа веб-приложений (WebApps) разработала комплексный набор тестов Selectors API и показала интероперабельность возможностей среди реализаций. Пожалуйста, посмотрите отчет о реализации Рабочей группы.

Пожалуйста, отправляйте комментарии об этом документе на public-webapps@w3.org (публичный архив) с пометкой [selectors-api] в теме. (Заметьте, что до середины 2008 использовался другой архивный лист, так что некоторые старые сообщения архивированы здесь).

Этот документ был разработан Рабочей группой веб-приложений. Полный список изменений этого документа доступен.

Этот документ был рассмотрен членами W3C, разработчиками программного обеспечения, а также другими группами W3C и заинтересованными лицами, и одобрен Директором в качестве Рекомендации W3C. Это стабильный документ и может быть использован в качестве справочного материала или цитироваться из другого документа. Цель W3C в создании Рекомендации заключается в привлечении внимания к спецификации и способствовании ее широкому распространению. Это повышает функциональность и совместимость Сети.

Этот документ был подготовлен группой, работающей под Патентной Политикой W3C от 5 февраля 2004. W3C поддерживает публичный список открытых патентов, сделанных в связи с результатами деятельности группы; эта страница также включает в себя инструкции по раскрытию патента. Человек, который имеет фактическое знание патента, который удовлетворяет основным требованиям, должен раскрывать информацию в соответствии c разделом 6 патентной политики W3C.

Содержание

1. Введение

Этот раздел не является нормативным.

Эта спецификация предоставляет методы для выбора и тестирования элементов в зависимости от того соответствуют ли они заданному селектору. С этими методами проще сопоставлять сет нод Element основываясь на специальном критерии, чем в дальнейшем фильтровать результат вызова других методов, таких как getElementsByTagName().

1.1. Примеры

Этот раздел не является нормативным.

Некоторые примеры на ECMAScript [ECMA-262-5.1]:

Этот пример таблицы написан на HTML 4.01.

<table id="score">
  <thead>
    <tr>
      <th>Test
      <th>Result
  <tfoot>
    <tr>
      <th>Average
      <td>82%
  <tbody>
    <tr>
      <td>A
      <td>87%
    <tr>
      <td>B
      <td>78%
    <tr>
      <td>C
      <td>81%
</table>

Для того чтобы получить ячейки, содержащие результаты таблицы, что может быть сделано, к примеру, чтобы построить график значений, есть как минимум два подхода, которые можно использовать. Использование только API для DOM Level 2, это требует скрипт вроде следующего, который перебирает каждый tr внутри каждого tbody в table, чтобы найти вторую ячейку каждой строки.

var table = document.getElementById("score");
var groups = table.tBodies;
var rows = null;
var cells = [];

for (var i = 0; i < groups.length; i++) {
  rows = groups[i].rows;
  for (var j = 0; j < rows.length; j++) {
    cells.push(rows[j].cells[1]);
  }
}

Второй метод это использование метода querySelectorAll(), с которым скрипт становится намного более кратким.

var cells = document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)");

Заметьте, что скрипт работает на DOM, и работает независимо от синтаксиса используемого при создании документа. Таким образом, этот скрипт также будет правильно работать для такой же таблицы созданной в правильном XHTML вместо HTML, или динамически созданным и вставленным в документ с помощью DOM API.

2. Требования к соответствию

Все диаграммы, примеры и заметки в данной спецификации не являются нормативными, также как все разделы помеченные не-нормативными. Все остальное в данном спецификации является нормативным.

Ключевые слова must, must not, should, may и recommended в нормативных частях этого документа должны интерпретироваться как описано в RFC 2119 [RFC2119].

Следующие классы соответствия определены (и рассматриваются) данной спецификацией:

соответствующий агент пользователя
Агент пользователя реализующий интерфейсы описанные данной спецификацией и соответствует всем must-level критериям, которые применяются к реализациям.
соответствующее приложение
Приложение использующее интерфейсы описанные данной спецификацией и соответствующие всем must-level критериям, которые применяются к приложениям.

2.1. Терминология и соглашения

Терминология используемая в данной спецификации та же, что и в Селекторах [SELECT].

Следующие функции определены в спецификации DOM Level 3 Core [DOM-LEVEL-3-CORE]:

Требования соответствия выраженные в виде алгоритмов или конкретных шагов могут (may) быть реализованы любым способом, до тех пор пока конечный результат эквивалентен.

IDL используемый в этой спецификации использует синтаксис определенный в Web IDL [DOM-BINDINGS].

Конструкция "Foo объект", где Foo является интерфейсом, иногда используется вместо более точного "объект реализующий Foo интерфейс".

3. Вопросы интероперабельности

Этот раздел не является нормативным.

Некоторые реализации могут иметь разные уровни поддержки Селекторов. Если некоторым реализациям не хватает поддержки некоторых селекторов, то использование этих селекторов выдаст ошибку при возвращении ожидаемых результатов. Авторы советуют проверять исключения DOM выданные этими API и обеспечивать запасной вариант для плавной деградации.

3.1. Расширяемость

Этот раздел не является нормативным.

Расширения для API определены в этой спецификации настоятельно нерекомендуемыми. Реализаторы, Рабочие группы и прочие заинтересованные стороны должны обсуждать расширения на соответствующем публичном форуме, таком как public-webapps@w3.org.

4. Вопросы безопасности

Ожидается, что реализация данной спецификации не вводит новых рисков безопасности для пользователей.

Если, в любое время, реализация обнаруживает ситуацию которая может нарушить политику безопасности, реализация может (may) прервать действие и выдать ошибку безопасности. Если возникает любое другое условие ошибки, которое не покрывается напрямую этой или другой релевантной спецификацией, реализация может (may) прервать действие и выдать соответствующее исключение, основанное на особенностях языка или реализатора.

5. Вопросы приватности

Кража истории это потенциальная проблема приватности, потому что псевдо-класс :visited в Селекторах [SELECT] позволяет авторам запрашивать какие ссылки были посещены.

Это не новая проблема, это уже может использоваться с помощью существующих CSS и DOM API, таких как getComputedStyle() [DOM-LEVEL-2-STYLE].

В этом примере, vlinks получит список ссылок которые пользователь посетил. Затем автор может получить список URI и потенциально использовать это знание.

var vlinks = document.querySelectorAll(":visited");
for (var i = 0; i < vlinks.length; i++) {
  doSomethingEvil(vlinks[i].href);
}

Как определено в Селекторах ([SELECT], раздел 6.6.1), пользовательские агенты могут (may) обработать все ссылки как непосещенные ссылки. Рекомендуется (recommended), чтобы реализации вели себя стабильно с другими использованиями Селекторов поддерживаемыми агентом пользователя.

6. API

Термин первый используемый в определениях методов описанных этой спецификацией, означает первый в порядке документа. Термин порядок документа означает поиск в глубину прямого порядка обхода дерева DOM или поддерева в вопросе. Термин контекстная нода относится к ноде на которой метод был вызван. Термин поддеревья относится к набору элементов, которые являются потомками контекстной ноды. Термин соответствующая Element нода относится к Element ноде которая соответствует строке селектора (selectors) которая была передана методу, в соответствии с правилами соответствия элементов определенных Селекторами [SELECT].

6.1. Определение интерфейсов

partial interface Document {
  Element?  querySelector(DOMString selectors);
  NodeList  querySelectorAll(DOMString selectors);
};

partial interface DocumentFragment {
  Element?  querySelector(DOMString selectors);
  NodeList  querySelectorAll(DOMString selectors);
};

partial interface Element {
  Element?  querySelector(DOMString selectors);
  NodeList  querySelectorAll(DOMString selectors);
};

6.2. Поиск элементов

Аргумент selectors для методов querySelector и querySelectorAll принимает строку селекторов.

Методы querySelector() на интерфейсах Document, DocumentFragment и Element должны (must) возвратить первую соответствующую Element ноду в пределах поддеревьев контекстной ноды. Если нет соответствующего Element, метод должен (must) возвратить null.

Методы querySelectorAll() на интерфейсах Document, DocumentFragment и Element должны (must) возвратить NodeList содержащий все соответствующие Element ноды в пределах поддеревьев контекстной ноды, в порядке документа. Если нет соответствующих нод, метод должен (must) вернуть пустой NodeList.

Когда вызван querySelector или querySelectorAll, реализация должна (must) следовать этим шагам:

  1. Сделать parsed selector результатом работы алгоритма обработки селектора с selectors в качестве входного.

  2. Реализация должна затем запустить алгоритм оценки селектора к нодам элемента в заданном дереве или поддеревьях, используя parsed selector как селектор для возвращения необходимого результата вызванного метода.

Объект NodeList возвращенный методом querySelectorAll(), должен (must) быть статичным, а не живым ([DOM-LEVEL-3-CORE], раздел 1.1.1). Последующие изменения в структуре базового документа не должны (must not) затрагиваться в объекте NodeList. Это означает, что объект будет содержать список соответствующих Element нод, которые были в документе на момент создания списка.

6.3. Грамматика

Строка селектора это список из одной или более групп селекторов ([SELECT], раздел 5), которые могут (may) быть окружены пробелами и соответствовать dom_selectors_group.

dom_selectors_group
  : S* [ selectors_group ] S*
  ;

Грамматика для selectors_group определена в Selectors Level 3 ([SELECT], раздел 10.1). Эти группы селекторов не должны (should not) использовать префиксы пространств имен которые должны быть разрешены.

Реализаторам советуется, что если значение null или undefined передано как значение параметра selectors, оно должно быть обработано как описано в WebIDL [DOM-BINDINGS]. Авторы советуют избегать передачи этих значений.

В то время как использование псевдо-элементов в селекторах допускается, они не будут соответствовать каким-либо элементам в документе, и поэтому не приводят в возвращению элементов. Поэтому авторы советуют избегать использования псевдо-элементов в селекторах которые передаются к методам описанным в этой спецификации.

6.4. Обработка селекторов

Шаги для обработки селектора являются следующими:

  1. Сделать selectors строкой селектора введенной в этот алгоритм.

  2. Сделать result группой селекторов возвращенных как результат обработки selectors согласно грамматике для dom_selectors_group описанной выше.

  3. Если result является не валидным ([SELECT], раздел 12), выдать исключение SYNTAX_ERR ([DOM-LEVEL-3-CORE], раздел 1.4) и прервать этот алгоритм.

  4. Возвратить result.

Шаги для оценки селектора являются следующими:

  1. Сделать element оцениваемым элементом.

  2. Сделать selector group входящим значением селекторов в этот алгоритм.

  3. Если любой селектор в selector group соответствует element, возвратить true. В другом случае, возвратить false.

Селекторы оцениваются к заданному элементу в контексте всего дерева DOM в котором элемент находится.

Если пользовательский агент также поддерживает какой-то уровень CSS, реализация должна (should) поддерживать тот же набор селекторов вместе с этими API и CSS.

6.5. Решение пространств имен

Если группа селекторов включает префиксы пространств имен которые должны быть решены, реализация должна (must) выдать исключение SYNTAX_ERR ([DOM-LEVEL-3-CORE], раздел 1.4).

Эта спецификация не предоставляет поддержки для решения произвольных префиксов пространств имен. Однако, поддержка механизма разрешения префиксов пространств имен может быть рассмотрена для включения в будущую версию этой спецификации.

Префиксы пространств имен должны быть разрешены если компонент пространства имен не является ни пустым (например |div), представляющим null пространство имен, либо звездочку (например *|div), представляющую любое пространство имен. Так как звездочка или пустой префикс пространств имен не требует разрешения, реализации которые поддерживают синтаксис пространства имен в Селекторах, должны (must) поддерживать их. [SELECT]

7. Примеры

Следующие примеры используют образец этого XHTML документа.

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Selectors API Example</title>
  </head>
  <body>
    <div id="foo">
      <p class="warning">This is a sample warning</p>
      <p class="error">This is a sample error</p>
    </div>
    <div id="bar">
      <p>...</p>
    </div>
  </body>
</html>

Методы принимают группы селекторов (разделенные запятой) в качестве аргумента. Следующий пример выберет все элементы p в документе, которые имеют класс "error" или "warning".

var alerts = document.querySelectorAll("p.warning, p.error");

Методы querySelector() также принимают группу селекторов и они вернут первый элемент (если есть), который соответствует любому селектору в группе.

var x = document.querySelector("#foo, #bar");

x будет содержать первый элемент в документе с ID foo или bar, или null если нет такого элемента. В простом документе выше, он выберет элемент div с ID foo, потому что он первый в порядке документа. Порядок селекторов используемый в параметрах не имеет эффекта и будет давать тот же результат при перестановке порядка, как в:

var x = document.querySelector("#bar, #foo");

Методы также могут быть вызваны на элементах. В следующем примере, предположим, обработчик события регистрируется на элементе, и таким образом метод вызывается на целевом элементе события.

function handle(evt) {
  var x = evt.target.querySelector("span");
  ...
  // Сделать что-то с x
}

Даже при том что метод вызван на элементе, селекторы все еще оцениваются в контексте всего документа. В следующем примере, метод будет по-прежнему соответствовать потомку div элемента, элементу p, хотя элемент body не является потомком элемента div.

var div = document.getElementById("bar");
var p = div.querySelector("body p");

Возьмем в качестве примера этот фрагмент, который содержит список как меню навигации:

<ul class="nav">
  <li><a href="/">Home</a></li>
  <li><a href="/products">Products</a></li>
  <li><a href="/about">About</a></li>
</ul>

Следующий пример выберет все элементы li и покажет как перебираются наборы в NodeList.

var lis = document.querySelectorAll("ul.nav>li");
for (var i = 0; i < lis.length; i++) {
  process(lis.item(i));
}

В ECMAScript связывание языка также позволяет NodeList-ам рассматриваться с помощью обозначения массива, так что цикл может быть переписан таким образом:

for (var i = 0; i < lis.length; i++) {
  process(lis[i]);
}

Так как объекты NodeList возвращаемые этими методами не живые, изменения в DOM не затрагивают содержание списка. Рассмотрим функцию process(), названную в предыдущих примерах, определенную как:

function process(elmt) {
  elmt.parentNode.removeChild(elmt);
}

Это вызовет удаление каждого выбранного элемента из DOM, но каждый элемент будет оставаться в NodeList. Если бы список был живым NodeList, удаление элемента из DOM также бы удалило элемент из списка и скорректировало бы показатели последующих элементов. Это бы негативно повлияло на цикл, потому что не все выбранные элементы были бы обработаны.

В документах содержащих элементы с многими пространствами имен, некоторые элементы с разными пространствами имен могут разделять одно локальное имя. Так как этот API изначально не поддерживает механизм разрешения пространств имен для селекторов, получение списка таких элементов из определенного пространства имен, исключая все остальные, требует дополнительной обработки для фильтрации результата. Следующий пример иллюстрирует документ содержащий элементы video с пространствами имен SVG и XHTML.

<svg id="svg1" xmlns="http://www.w3.org/2000/svg"
               xmlns:xlink="http://www.w3.org/1999/xlink">
  <video id="svgvideo1" xlink:href="myvideo.ogg" width="320" height="240"/>
  <foreignObject width="100" height="100">
    <video id="htmlvideo1" src="myvideo.ogg" xmlns="http://www.w3.org/1999/xhtml">No video1</video>
  </foreignObject>
</svg>

Следующий скрипт демонстрирует как выбрать элементы video и затем отфильтровать нежелательные элементы, основываясь на их пространстве имен.

var elms = document.querySelectorAll("svg video");
var result = new Array();
var svgns = "http://www.w3.org/2000/svg"

for(var i = 0; i < elms.length; i++) {
  if(elms[i].namespaceURI == svgns) {
    result.push(elms[i]);
  }
}

Ссылки

Нормативные ссылки

[DOM-BINDINGS]
Cameron McCormack. Web IDL. 19 апреля 2012. Кандидат в Рекомендации W3C. (Работа в процессе). URL: http://www.w3.org/TR/2012/CR-WebIDL-20120419/
[DOM-LEVEL-3-CORE]
Gavin Nicol; и соавторы. Document Object Model (DOM) Level 3 Core Specification. 7 апреля 2004. Рекомендация W3C. URL: http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
[SELECT]
Tantek Çelik; и соавторы. Selectors Level 3. 29 сентября 2011. Рекомендация W3C. URL: http://www.w3.org/TR/2011/REC-css3-selectors-20110929/

Информативные ссылки

[CSS21]
Bert Bos; и соавторы. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 июня 2011. Рекомендация W3C. URL: http://www.w3.org/TR/2011/REC-CSS2-20110607/
[DOM-LEVEL-2-STYLE]
Chris Wilson; Philippe Le Hégaret; Vidur Apparao. Document Object Model (DOM) Level 2 Style Specification. 13 ноября 2000. Рекомендация W3C. URL: http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/
[ECMA-262-5.1]
ECMAScript Language Specification, Edition 5.1. Июнь 2011. ISO/IEC 16262:2011. URL: http://www.ecma-international.org/publications/standards/Ecma-262.htm

Благодарности

Редакторы хотели бы поблагодарить следующих людей, которые внесли свой вклад в эту спецификацию (упорядочены по имени):

Adam van den Hoven, Alan Gresley, Alex Russell, Arthur Barstow, Aryeh Gregor, Björn Höhrmann, Boris Zbarsky, Cameron McCormack, Charles McCathieNevile, Chris Wilson, Christophe Jolif, Daniel Glazman, Daniel Schierbeck, Dave Massy, David "liorean" Andersson, David Greenspan, David Håsäther, Dean Jackson, Doug Schepers, Erik Dahlström, Francois Remy, Hallvord R. M. Steen, Henri Sivonen, Ian Hickson, Ivan Enderlin, Jean-Yves Bitterlich, Jim Ley, João Eiras, John Resig, Jon Ferraiolo, Jonas Sicking, Jorgen Horstink, Kang-Hao (Kenny) Lu, Karl Dubost, Kartikaya Gupta, L. David Baron, Maciej Stachowiak, Magnus Kristiansen, Marat Tanalin, Martijn, Masataka Yakura, Mihai Sucan, Mohamed Zergaoui, Nicholas C. Zakas, Nicolas Mendoza, Norbert Lindenberg, Philip Taylor, Robert Sayre, Robin Berjon, Sander, Sergey Ilinsky, Simon Pieters, Steven Pemberton, Stewart Brodie Tab Atkins Jr., Tarquin Wilton-Jones, Travis Leithead, и William J. Edney

Особое спасибо John Resig и Øyvind Stenhaug за их значительный вклад в серии тестов.

Спасибо всем тем, кто помог улучшить эту спецификацию, присылая предложения и исправления.