Как создать все возможные комбинации селекторов CSS 2? - PullRequest
3 голосов
/ 27 февраля 2011

Каков наилучший способ создания всех возможных комбинаций селекторов CSS 2 для элемента DOM в контексте с текущим состоянием document?

Например: Для следующей наценки

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
  <title></title>
</head>
<body>
  <div id="content">
    <ul>
      <li>a</li>
      <li>b</li>
      <li class="last-li">c</li> <!--ARGUMENT ELEMENT-->
    </ul>
  </div>
</body>
</html>

Метод JS / jQuery, такой, что <!--ARGUMENT ELEMENT--> в приведенной выше разметке задается в качестве аргумента метода, он возвращает все возможные комбинации селекторов CSS 2 для аргумента в виде массива. Необязательный параметр может быть добавлен к методу, который будет определять максимальную глубину вложенности селектора CSS 2. Если для этого параметра задано значение false, он должен возвращать все возможные комбинации (если производительность задана как false), будет производительный скачок *

Пример вывода:

[
 ".last-li",
 "li.last-li",
 "ul .last-li",
 "ul li.last-li",
 "div ul .last-li",
 "div ul li.last-li",
 "#content ul .last-li",
 "#content ul li.last-li",
 "div#content ul .last-li",
 "div#content ul li.last-li",
 "body div ul li.last-li",
 "body div ul .last-li",
 "body #content ul li.last-li",
 "body div#content ul .last-li",
 "body div#content ul li.last-li",
]

Любые указатели в этом отношении будут чрезвычайно полезны.

1 Ответ

4 голосов
/ 27 февраля 2011

Во-первых, давайте придерживаться узкого класса селекторов, включающего имена тегов, имена классов и идентификаторы, ничего необычного, например, E > F или E + F. Давайте также запретим комбинации имен классов (.class1.class2.class3), иначе один элемент с 10 именами классов сгенерирует только 4 миллиона селекторов.

Каждый из наших полных селекторов состоит из простых селекторов, разделенных пробелами. Каждый простой селектор представляет собой комбинацию tag{0,1}id{0,1}class{0,n}, то есть каждый элемент имеет ровно один тег, максимум один идентификатор, и может иметь произвольное количество имен классов. Это дает нам верхний предел 2 * 2 * (n + 1) простых селекторов для одного элемента.

Учитывая ссылку на элемент DOM, захватите его имя тега, ID и имена классов. Рассчитайте все возможные простые селекторы, как описано выше. Давайте назовем это множество A1. Переместите один шаг вверх по иерархии к его родителю, вычислите все простые селекторы для этого родительского элемента - это будет набор A2. Продолжайте, пока не дойдете до элемента html - набора Am. Теперь у вас будет список, состоящий из m элементов, каждый из которых представляет собой набор простых селекторов.

Теперь выберите некоторые из этих наборов и найдите их декартово произведение. Скажем, m = 5. Сколько комплектов вы можете выбрать? Набор A1 всегда присутствует, но другие являются необязательными. Для каждого из них вы либо выбираете, либо нет. Это похоже на двоичные числа:

0000 // 0, A1
0001 // 1, A1 x A2
0010 // 2, A1 x A3
0011 // 3, A1 x A2 x A3
0100 // 4, A1 x A4
...

Это означает, что у вас будет 2 ^ (м-1) декартовых произведений. Теперь вы можете конвертировать их в строки. Последний шаг - удаление дубликатов, рассмотрим этот пример:

<div>
  <div>
    <span></span>
  </div>
</div>

Наши расчеты приведут к следующему списку:

  span
  div span // inner div
  div span // outer div
  div div span

Эти два div приводят к дублированию селекторов. Удалить те, и работа сделана. Все шаги очень просты алгоритмически. Я уверен, что вы можете их выяснить, но если вы застряли где-то или вам нужны дополнительные разъяснения, не стесняйтесь спрашивать меня в комментариях.


UPDATE

Итак, я решил немного поиграть с ним и написал программу, вот список селекторов, которые генерирует ваш пример: http://pastie.org/1616164

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...