JavaScript: Выбор по селектору

Обновлено: 03 авг., 23:20
727
Студентов
54%
Завершения

Частой задачей при работе с деревьями (особенно HTML), является необходимость выбрать список узлов по определенному критерию.

Пара примеров из реальной жизни:

XPath

/bookstore/book/price[text()]
price/@exchange/total
book[excerpt]/author[degree]

JQuery

$("ul > li:first-child")
$("p.class1, #p1")

solution.js

Реализуйте и экспортируйте по умолчанию функцию, которая возвращает список нод в соответствии с запросом. Запрос это список из имен тегов, в котором каждый следующий тег это тег, вложенный в предыдущий. Порядок, в котором ноды возвращаются - не важен.

У нас есть такой HTML:

<h1>scheme</h1>
<p>is a lisp</p>
<p>
  <ul>
    <li>item 2</li>
    <li>item 1</li>
  </ul>
</p>
<ol>
  <li>item 2</li>
  <li>item 1</li>
</ol>
<p>is a functional language</p>
<ul>
  <li>item</li>
</ul>
<div>
  <p>another text</p>
</div>
<div>
  <div>
    <p>
      <span>text</span>
    </p>
  </div>
</div>
<div>
  <a>
    <div>
      <p>
        <span>text</span>
      </p>
    </div>
  </a>
</div>
<h1>prolog</h1>
<p>is about logic</p>

Строим HTML следующим образом:

const dom1 = make();
const dom2 = append(dom1, node('h1', 'scheme'));
const dom3 = append(dom2, node('p', 'is a lisp'));
const children1 = l(node('li', 'item 1'), node('li', 'item 2'));
const dom4 = append(dom3, node('p', l(node('ul', children1))));
const children2 = l(node('li', 'item 1'), node('li', 'item 2'));
const dom5 = append(dom4, node('ol', children2));
const dom6 = append(dom5, node('p', 'is a functional language'));
const children3 = l(node('li', 'item'));
const dom7 = append(dom6, node('ul', children3));
const dom8 = append(dom7, node('div', l(node('p', 'another text'))));
const dom9 = append(dom8, node('div', l(node('div', l(node('p', l(node('span', 'text'))))))));
const dom10 = append(dom9, node('div', l(node('a', l(node('div', l(node('p', l(node('span', 'text'))))))))));
const dom11 = append(dom10, node('h1', 'prolog'));
dom = append(dom11, node('p', 'is about logic'));

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

select(l('p', 'ul', 'li'), dom);
// <li>item 1</li><li>item 2</li>

select(l('div', 'div', 'p'), dom);
// <p><span>text</span></p>

select(l('div', 'p'), dom);
// <p>another text</p><p><span>text</span></p><p><span>text</span></p>

select(l('div'), dom));
// <div><a><div><p><span>text</span></p></div></a></div><div><p><span>text</span></p></div><div><div><p><span>text</span></p></div></div><div><p><span>text</span></p></div><div><p>another text</p></div>

Алгоритм работы функции

  • Список тегов для поиска будем называть словом query.
  • query ищется с любого уровня дерева, а не только с верхнего. Например, если наш query это p, то будут найдены все p на всех уровнях.
  • Производится поиск только подряд идущих тегов, например, если запрос l('ul', 'li'), то будут найдены только те li, которые идут сразу за ul.

Подсказки

  • hasChildren() - функция, которая проверяет, есть ли потомки у элемента
  • children() - функция, которая возвращает список потомков

P.S. В целом, эта функция достаточно сложна и, если вы сможете решить эту задачу самостоятельно, то вас смело можно брать на работу).

Для полного доступа к испытанию нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Отзывы

Аватар пользователя Дмитрий Хребтов
Дмитрий Хребтов 30 августа 2019

Создание абстракции в решении учителя - уровень БОГ!

Код, не требующий комментариев, одним словом!

Принцип "разделяй и властвуй" во всей его красе, браво!

Я еще никогда не писал так много ифов :D

Кто не смог решить, не отчаивайтесь, обязательно загляните сюда снова после второго проекта!

За примером, где нет ни одной абстракции - сюда :)


Аватар пользователя Александр Чупахин
Александр Чупахин 26 апреля 2018

https://ru.hexlet.io/code_reviews/46960 Ох, ну теперь меня, старого коня, точно на работу возьмут! )) Полтора часа делов.