Skip to content

Week 3 #448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
174 changes: 174 additions & 0 deletions projects/dom/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/* ДЗ 4 - работа с DOM */

/*
Задание 1:

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

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

Пример:
createDivWithText('loftschool') // создаст элемент div, поместит в него 'loftschool' и вернет созданный элемент
*/
function createDivWithText(text) {
const div = document.createElement('div');
div.textContent = 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>
</body>

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

for (const el of where.children) {
if (el.nextElementSibling && el.nextElementSibling.tagName === 'P') {
nextP.push(el);
}
}

return nextP;
}

/*
Задание 4:

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

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

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

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

for (const child of where.children) {
result.push(child.textContent);
}

return result;
}

/*
Задание 5:

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

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

Пример:
После выполнения функции, дерево <div></div>привет<p></p>loftchool!!!
должно быть преобразовано в <div></div><p></p>
*/
function deleteTextNodes(where) {
for (let i = 0; i < where.childNodes.length; i++) {
const el = where.childNodes[i];

if (el.nodeType === Element.TEXT_NODE) {
where.removeChild(el);
i--;
}
}
}

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

Необходимо собрать статистику по всем узлам внутри элемента переданного в параметре 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) {
const stat = {
tags: {},
classes: {},
texts: 0,
};

function scan(root) {
for (const child of root.childNodes) {
if (child.nodeType === Node.TEXT_NODE) {
stat.texts++;
} else if (child.nodeType === Node.ELEMENT_NODE) {
if (child.tagName in stat.tags) {
stat.tags[child.tagName]++;
} else {
stat.tags[child.tagName] = 1;
}

for (const className of child.classList) {
if (className in stat.classes) {
stat.classes[className]++;
} else {
stat.classes[className] = 1;
}
}
scan(child);
}
}
}

scan(root);

return stat;
}

export {
createDivWithText,
prepend,
findAllPSiblings,
findError,
deleteTextNodes,
collectDOMStat,
};
112 changes: 112 additions & 0 deletions projects/dom/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { randomValue } from '../../scripts/helper';
import {
collectDOMStat,
createDivWithText,
deleteTextNodes,
findAllPSiblings,
findError,
prepend,
} from './index';

function random(type) {
const result = randomValue(type);

if (type === 'string') {
return encodeURIComponent(result);
}

return result;
}

describe('ДЗ 4 - Работа с DOM', () => {
describe('createDivWithText', () => {
it('должна возвращать элемент с тегом DIV', () => {
const text = random('string');
const result = createDivWithText(text);

expect(result).toBeInstanceOf(Element);
expect(result.tagName).toBe('DIV');
});

it('должна добавлять текст в элемент', () => {
const text = random('string');
const result = createDivWithText(text);

expect(result.textContent).toBe(text);
});
});

describe('prepend', () => {
it('должна добавлять элемент в начало', () => {
const where = document.createElement('div');
const what = document.createElement('p');
const whereText = random('string');
const whatText = random('string');

where.innerHTML = `, <b>${whereText}</b>!`;
what.textContent = whatText;

prepend(what, where);

expect(where.firstChild).toBe(what);
expect(where.innerHTML).toBe(`<p>${whatText}</p>, <b>${whereText}</b>!`);
});
});

describe('findAllPSiblings', () => {
it('должна возвращать массив с элементами, соседями которых являются P', () => {
const where = document.createElement('div');

where.innerHTML = '<div></div><p></p><span></span><span></span><p></p>';
const result = findAllPSiblings(where);

expect(Array.isArray(result));
expect(result).toEqual([where.children[0], where.children[3]]);
});
});

describe('findError', () => {
it('должна возвращать массив из текстового содержимого элементов', () => {
const where = document.createElement('div');
const text1 = random('string');
const text2 = random('string');

where.innerHTML = ` <div>${text1}</div>, <div>${text2}</div>!!!`;
const result = findError(where);

expect(Array.isArray(result));
expect(result).toEqual([text1, text2]);
});
});

describe('deleteTextNodes', () => {
it('должна удалить все текстовые узлы', () => {
const where = document.createElement('div');

where.innerHTML = ` <div></div>${random('string')}<p></p>${random('string')}`;
deleteTextNodes(where);

expect(where.innerHTML).toBe('<div></div><p></p>');
});
});

describe('collectDOMStat', () => {
it('должна вернуть статистику по переданному дереву', () => {
const where = document.createElement('div');
const class1 = `class-${random('number')}`;
const class2 = `class-${random('number')}-${random('number')}`;
const text1 = random('string');
const text2 = random('string');
const stat = {
tags: { P: 1, B: 2 },
classes: { [class1]: 2, [class2]: 1 },
texts: 3,
};

where.innerHTML = `<p class="${class1}"><b>${text1}</b> <b class="${class1} ${class2}">${text2}</b></p>`;
const result = collectDOMStat(where);

expect(result).toEqual(stat);
});
});
});