Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 239 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/* ДЗ 4 - работа с DOM */

/*
Задание 1:

1.1: Функция должна создать элемент с тегом DIV

1.2: В созданный элемент необходимо поместить текст, переданный в параметр text

Пример:
createDivWithText('loftschool') // создаст элемент div, поместит в него 'loftschool' и вернет созданный элемент
*/
function createDivWithText(text) {
let div = document.createElement('div');

div.innerText = text;

return div;
}

/*
Задание 2:

Функция должна вставлять элемент, переданный в переметре what в начало элемента, переданного в параметре where

Пример:
prepend(document.querySelector('#one'), document.querySelector('#two')) // добавит элемент переданный первым аргументом в начало элемента переданного вторым аргументом
*/
function prepend(what, where) {
where.insertBefore(what, where.firstChild)
}

/*
Задание 3:

3.1: Функция должна перебрать все дочерние элементы узла, переданного в параметре where

3.2: Функция должна вернуть массив, состоящий из тех дочерних элементов следующим соседом которых является элемент с тегом P

Пример:
Представим, что есть разметка:
<body>
<div></div>
<p></p>
<a></a>
<span></span>
<p></p>
</dody>

findAllPSiblings(document.body) // функция должна вернуть массив с элементами div и span т.к. следующим соседом этих элементов является элемент с тегом P
*/
function findAllPSiblings(where) {
let arr = [];
let pp = where.querySelectorAll('P');

for (let i = 0; i < pp.length; i++) {
arr.push(pp[i].previousElementSibling);
}

return arr;
}

/*
Задание 4:

Функция представленная ниже, перебирает все дочерние узлы типа "элемент" внутри узла переданного в параметре where и возвращает массив из текстового содержимого найденных элементов
Но похоже, что в код функции закралась ошибка и она работает не так, как описано.

Необходимо найти и исправить ошибку в коде так, чтобы функция работала так, как описано выше.

Пример:
Представим, что есть разметка:
<body>
<div>привет</div>
<div>loftschool</div>
</dody>

findError(document.body) // функция должна вернуть массив с элементами 'привет' и 'loftschool'
*/
function findError(where) {
let arr = [];

for (let child of where.children) {
arr.push(child.innerText);
}

return arr;
}

/*
Задание 5:

Функция должна перебрать все дочерние узлы элемента переданного в параметре where и удалить из него все текстовые узлы

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

Пример:
После выполнения функции, дерево <div></div>привет<p></p>loftchool!!!
должно быть преобразовано в <div></div><p></p>
*/
function deleteTextNodes(where) {
for (let textNode of where.childNodes) {
if (textNode.nodeType === Node.TEXT_NODE) {
where.removeChild(textNode);
}
}
}

/*
Задание 6:

Выполнить предудыщее задание с использование рекурсии - то есть необходимо заходить внутрь каждого дочернего элемента (углубляться в дерево)

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

Пример:
После выполнения функции, дерево <span> <div> <b>привет</b> </div> <p>loftchool</p> !!!</span>
должно быть преобразовано в <span><div><b></b></div><p></p></span>
*/
function deleteTextNodesRecursive(where) {
let itemsNode = [...where.childNodes];

for (let item of itemsNode) {
switch (item.nodeType) {
case Node.TEXT_NODE:
item.remove();
break;
case Node.ELEMENT_NODE:
deleteTextNodesRecursive(item);
break;
}
}
}

/*
Задание 7 *:

Необходимо собрать статистику по всем узлам внутри элемента переданного в параметре root и вернуть ее в виде объекта
Статистика должна содержать:
- количество текстовых узлов
- количество элементов каждого класса
- количество элементов каждого тега
Для работы с классами рекомендуется использовать classList
Постарайтесь не создавать глобальных переменных

Пример:
Для дерева <div class="some-class-1"><b>привет!</b> <b class="some-class-1 some-class-2">loftschool</b></div>
должен быть возвращен такой объект:
{
tags: { DIV: 1, B: 2},
classes: { "some-class-1": 2, "some-class-2": 1 },
texts: 3
}
*/
function collectDOMStat(root) {
let fn = (node, obj) => {
obj = obj || { tags: {}, classes: {}, texts: 0 };

for (let i of node.childNodes) {
if (i.nodeType === Node.TEXT_NODE) {
obj.texts++;
}

if (i.childNodes.length) {
obj.tags[i.tagName] = ~~obj.tags[i.tagName] + 1;
for (let cl of i.classList) {
obj.classes[cl] = ~~obj.classes[cl] + 1;
}
obj = fn(i, obj);
}
}

return obj;
};

return fn(root);

}

/*
Задание 8 *:

8.1: Функция должна отслеживать добавление и удаление элементов внутри элемента переданного в параметре where
Как только в where добавляются или удаляются элементы,
необходимо сообщать об этом при помощи вызова функции переданной в параметре fn

8.2: При вызове fn необходимо передавать ей в качестве аргумента объект с двумя свойствами:
- type: типа события (insert или remove)
- nodes: массив из удаленных или добавленных элементов (в зависимости от события)

8.3: Отслеживание должно работать вне зависимости от глубины создаваемых/удаляемых элементов

Рекомендуется использовать MutationObserver

Пример:
Если в where или в одного из его детей добавляется элемент div
то fn должна быть вызвана с аргументом:
{
type: 'insert',
nodes: [div]
}

------

Если из where или из одного из его детей удаляется элемент div
то fn должна быть вызвана с аргументом:
{
type: 'remove',
nodes: [div]
}
*/
function observeChildNodes(where, fn) {
let obs = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
fn({ 'type': 'insert', 'nodes': Array.from(mutation.addedNodes) });
} else if (mutation.removedNodes.length) {
fn({ 'type': 'remove', 'nodes': Array.from(mutation.removedNodes) });
}
});
});

let config = { childList: true };

obs.observe(where, config);
}

export {
createDivWithText,
prepend,
findAllPSiblings,
findError,
deleteTextNodes,
deleteTextNodesRecursive,
collectDOMStat,
observeChildNodes
};
Loading