Similar presentations:
Веб-разработка. DOM
1.
Веб-разработкаЛекция №5. DOM.
Шумилов Вадим Валерьевич
Тензор, 2016
2.
DOM2
3.
DOMDOM – Document Object Model
API для работы со страницей из JavaScript.
• Читать информацию
• Создавать новые элементы
• Манипулировать существующими
• Изменять свойства
• Перемещать
3
4.
DOMDOM – Document Object Model
Все элементы страницы (тэги, текст, комментарии) являются
элементами DOM.
Часто его называют DOM-дерево.
4
5.
Навигация5
6.
НавигацияКаждый DOM-элемент имеет следующие навигационные
свойства:
parentNode – родитель
previousSubling – предыдущий сосед
nextSibling – следующий сосед
firstChild, lastChild – первый и последний дочерний элементы
childNodes – коллекция дочерних элементов
6
7.
НавигацияВажные особенности:
1. Коллекция здесь – не настоящий массив.
2. Если какой-то элемент не определен, значение
навигационного свойства будет null.
7
8.
Навигация<html>
<body>
<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
8
9.
Навигация<html>
<body>
var body = document.body;
<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
9
10.
Навигация<html>
<body>
<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
body.firstChild
10
11.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
body.firstChild
11
12.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>[
]</body>
</html>
var body = document.body;
body.firstChild
body.lastChild
12
13.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
var first = body.firstChild;
first.nextSibling;
13
14.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
var first = body.firstChild;
first.nextSibling.nextSibling;
14
15.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
var first = body.firstChild;
first.nextSibling.firstChild
15
16.
Навигация<html>
<body>[
]<h1>Привет</h1>
<p>Текст...</p>
<p>Еще абзац</p>
</body>
</html>
var body = document.body;
var first = body.firstChild;
first.nextSibling.firstChild;
first.nextSibling.firstChild.parentNode
16
17.
НавигацияСуществуют дополнительные навигационные свойства,
не учитывающие текстовые ноды.
parentElementNode
firstElementChild, lastElementChild
previousElementSibling, lastElementSibling
children
17
18.
НавигацияКак работать с коллекциями (childNodes, children)?
Два способа обращения к элементу:
elt.childNodes[i];
elt.childNodes.item(i);
Перебор – по индексу от 0 до elt.childNodes.length
18
19.
Поиск элементов19
20.
Поиск элементовНесколько основных способов найти элемент(ы)
• getElementById()
• getElementsBy*()
• querySelector()/querySelectorAll()
20
21.
Поиск элементовdocument.getElementById(‘elt-id’);
1. Вызов – с объекта document
2. Возвращает один элемент с указанным id или null
21
22.
Поиск элементовanyElement.getElementsBy*(‘query’);
1. Вызов – с любого элемента. Это ограничивает область
поиска
2. Варианты:
• ByName
• ByClassName
• ByTagName
3. Возвращает «живую коллекцию» (возможно, пустую)
22
23.
Поиск элементовanyElement.querySelector(‘#css .selector’);
1. Вызов – с любого элемента. Это ограничивает область
поиска
2. Возвращает один первый элемент, подходящий под
указанный селектор или null, если не найден
3. Бросает исключение, если селектор некорректный
23
24.
Поиск элементовanyElement.querySelectorAll(‘#css .selector’);
1. Вызов – с любого элемента. Это ограничивает область
поиска
2. Возвращает коллекцию элементов (возможно, пустую),
подходящих под указанный селектор
3. Бросает исключение, если селектор некорректный
24
25.
Поиск элементовРазница между getElementsBy* и querySelectorAll
Оба метода возвращают коллекцию, но их действие не
равнозначно.
getElementsBy* возвращают «живую» коллекцию
25
26.
Поиск элементов<body>
<p>Первый</p>
<p>Второй</p>
</body>
liveCol = document.getElementsByTagName(‘p’);
col = document.querySelectorAll(‘p’);
26
27.
Поиск элементовliveCol = document.getElementsByTagName(‘p’);
col = document.querySelectorAll(‘p’);
liveCol.length; // 2
col.length; // 2
27
28.
Поиск элементовliveCol = document.getElementsByTagName(‘p’);
col = document.querySelectorAll(‘p’);
document.body.innerHTML = ‘’; // удалит все из body
liveCol.length; // ??
col.length; // ??
28
29.
Поиск элементовliveCol = document.getElementsByTagName(‘p’);
col = document.querySelectorAll(‘p’);
document.body.innerHTML = ‘’; // удалит все из body
liveCol.length; // 0
col.length; // 2
29
30.
Атрибуты30
31.
АтрибутыДля работы с атрибутами у каждого элемента есть
следующие методы:
getAttribute(‘name’);
setAttribute(‘name’, ‘value’);
hasAttribute(‘name’);
removeAttribute(‘name’);
31
32.
АтрибутыОсобенности:
• Значения атрибутов – строки. Все что не строки –
конвертируется в строку
• Имена атрибутов - регистронезависимы
• Изменение атрибутов приводит к изменению DOM и
HTML
32
33.
АтрибутыАтрибуты и свойства
• Элементы это объекты.
• Как и у любого объекта, у элементов есть свойства
• Некоторые свойства синхронизируются с атрибутами
• Некоторые – в обе стороны, некоторые – только в одну
33
34.
Атрибуты<div id=“some”></div>
var elt = document.getElementById(‘some’);
elt.id; // ‘some’
elt.getAttribute(‘id’); // ‘some’
34
35.
Атрибуты<div id=“some”></div>
var elt = document.getElementById(‘some’);
elt.id = “foo”;
elt.getAttribute(‘id’); // ‘foo’
elt.outerHTML; // ‘<div id=“foo”></div>’
35
36.
АтрибутыНе все атрибуты и свойства синхронизируются
<input type=“text” value=“foo” />
var elt = document.getElementsByTagName(‘input’)[0];
elt.value; // ‘foo’
elt.getAttribute(‘value’); // ‘foo’
36
37.
АтрибутыНе все атрибуты и свойства синхронизируются
<input type=“text” value=“foo” />
var elt = document.getElementsByTagName(‘input’)[0];
elt.value = ‘bar’;
elt.getAttribute(‘value’); // ‘foo’
elt.innerHTML; // ‘<input type=“text” value=“foo” />’
Но на экране в поле ввода будет “bar”...
37
38.
Модификация дерева38
39.
Модификация дереваМожно создавать ноды дерева
var div = document.createElement(‘div’);
var text = document.createTextNode(‘Это текстовая нода’);
39
40.
Модификация дереваМожно добавлять ноды в другие ноды
div.appendChild(text);
document.body.appendChild(div);
40
41.
Модификация дереваМожно читать что получилось в виде строки:
document.body.innerHTML;
<div>Это текстовая нода</div>
41
42.
Модификация дереваМожно читать что получилось в виде строки:
document.body.outerHTML;
<body><div>Это текстовая нода</div></body>
42
43.
Модификация дереваСоздавать содержимое документа можно с помощью
innerHTML.
document.body.innerHTML = “<p>Параграф текста</p>”;
«Перезапись» innerHTML приводит к удалению всего
содержимого, которое ранее было внутри.
43
44.
Модификация дереваМожно управлять местом вставки
parent.insertBefore(elem, nextSibling);
parent.replaceChild(newElem, elem);
44
45.
Модификация дереваinsertBefore
<body>
<div id=“ref”></div>
</body>
45
46.
Модификация дереваinsertBefore
<body>
<div id=“ref”></div>
</body>
var ref = document.getElementById(‘ref’);
var newDiv = document.createElement(‘div’);
document.body.insertBefore(newDiv, ref);
46
47.
Модификация дереваinsertBefore
var ref = document.getElementById(‘ref’);
var newDiv = document.createElement(‘div’);
document.body.insertBefore(newDiv, ref);
<body>
<div></div>
<div id=“ref”></div>
</body>
47
48.
Модификация дереваЕсли указать последний параметр null – вставка будет
эквивалентна appendChild.
insertBefore(newChild, null) == appendChild(newChild)
48
49.
Модификация дереваreplaceChild
<body>
<div id=“ref”></div>
</body>
var ref = document.getElementById(‘ref’);
var newDiv = document.createElement(‘div’);
document.body.replaceChild(newDiv, ref);
49
50.
Модификация дереваreplaceChild
var ref = document.getElementById(‘ref’);
var newP = document.createElement(‘p’);
document.body.replaceChild(newDiv, ref);
<body>
<p></p>
</body>
50
51.
Модификация дереваЭлементы можно удалять методом removeChild
<body>
<div id=“ref”></div>
</body>
var ref = document.getElementById(‘ref’);
document.body.removeChild(ref);
51
52.
Модификация дереваЭлементы можно удалять методом removeChild
var ref = document.getElementById(‘ref’);
document.body.removeChild(ref);
<body>
</body>
52
53.
Модификация дереваЭлементы можно клонировать методом cloneNode
<body>
<p>Абзац</p>
</body>
var p = document.body.firstElementChild;
var pClone = p.cloneNode();
document.body.appendChild(pClone);
53
54.
Модификация дереваЭлементы можно клонировать методом cloneNode
var p = document.body.firstElementChild;
var pClone = p.cloneNode();
document.body.appendChild(pClone);
<body>
<p>Абзац</p>
???
</body>
54
55.
Модификация дереваЭлементы можно клонировать методом cloneNode
var p = document.body.firstElementChild;
var pClone = p.cloneNode();
document.body.appendChild(pClone);
<body>
<p>Абзац</p>
<p></p>
</body>
55
56.
Модификация дереваЭлементы можно клонировать методом cloneNode
var p = document.body.firstElementChild;
var pClone = p.cloneNode(true);
document.body.appendChild(pClone);
<body>
<p>Абзац</p>
<p>Абзац</p>
</body>
56
57.
События57
58.
СобытияDOM Events. События. Какие они бывают?
58
59.
СобытияDOM Events. События. Какие они бывают?
Click
Mousedown, Mousemove
Focus
Keydown, Keyup
Sumbit
59
60.
СобытияКак добавить обработчик события.
<p onclick=“alert(‘Нажали на текст’)”>...</p>
p.onclick=function() {
alert(‘Нажали на текст’);
};
60
61.
СобытияКак добавить обработчик события.
function handleClick() { ... };
<p onclick=“handleClick()”>...</p>
p.onclick=handleClick;
61
62.
События<p onclick=“handleClick()”>...</p>
p.onclick=handleClick;
p.setAttribute(‘onclick’, handleClick);
62
63.
События<p onclick=“handleClick()”>...</p>
p.onclick=handleClick;
p.setAttribute(‘onclick’, handleClick);
63
64.
Событияp.onclick = f1;
p.onclick = f2;
64
65.
Событияp.onclick = f1;
p.onclick = f2;
Проблема. Второй обработчик «затрет» первый!
65
66.
СобытияaddEventListener!
p.addEventListener(‘click’, f1);
p.addEventListener(‘click’, f2);
66
67.
СобытияОбратите внимание!
p.onclick = ...
p.addEventListener(‘click’, ...);
При навешивании через атрибут нужно добавить on!
67
68.
Событияelt.addEventListener vs elt.on*
1. Позволяет добавить несколько обработчиков
2. Есть события, которые нельзя добавить через
свойство/разметку. Можно только через addEventListener
68
69.
СобытияКак удалить обработчик?
elt.onclick = null;
elt.removeEventListener(‘click’, f);
69
70.
Событияelt.addEventListener(‘click’, function() { doSmth(); });
elt.removeEventListener(‘click’, function() { doSmth();});
70
71.
Событияelt.addEventListener(‘click’, function() { doSmth(); });
elt.removeEventListener(‘click’, function() { doSmth();});
71
72.
СобытияВажно! Требуется указывать всегда одну и ту же функцию!
function handler() {
doSmth();
}
elt.addEventListener(‘click’, handler);
elt.removeEventListener(‘click’, handler);
72
73.
Объект события73
74.
Объект событияp.onclick = function(event) {
// event???
}
74
75.
Объект событияОбъект-дескриптор события. Содержит свойства и методы,
позволяющие получить дополнительную информацию о
событии, управлять им и т.п.
75
76.
Объект событияevent.type – тип события (click, mousedown, keyup, etc.)
event.target – объект, на котором случилось событие
Есть разные специфические свойства
event.clientX, event.clientY – координаты курсора в момент клика
76
77.
Объект событияКак получить доступ к событию, если обработчик навешивается
через атрибут?
77
78.
Объект событияКак получить доступ к событию, если обработчик навешивается
через атрибут?
<div onclick=“alert(event.clientX)”>...</div>
78
79.
Объект событияКак получить доступ к событию, если обработчик навешивается
через атрибут?
<div onclick=“alert(event.clientX)”>...</div>
Это эквивалентно ...
div.onclick = function(event) {
alert(event.clientX);
}
79
80.
Всплытие события80
81.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>Первый
<span>параграф</span>
</p>
</div>
81
82.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>Первый
<span>параграф</span>
</p>
</div>
82
83.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>Первый
<span>параграф</span>
</p>
</div>
83
84.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>Первый
<span>параграф</span>
</p>
</div>
84
85.
Всплытиеevent.target – элемент, на котором изначально случилось событие
event.currentTarget – элемент, на котором событие было поймано
85
86.
ВсплытиеВсплытие можно заблокировать
<div onclick=“alert(‘Click!’)”>
<p onclick=“event.stopPropagation()”>
<span>....</span>
</p>
</div>
86
87.
ВсплытиеВсплытие можно заблокировать
<div onclick=“alert(‘Click!’)”>
<p onclick=“event.stopPropagation()”>
<span>....</span>
</p>
</div>
В этом примере мы не увидим alert();
87
88.
ВсплытиеЧто если обработчиков несколько?
<div onclick=“alert(‘Click!’)”>
<p><span>....</span></p>
</div>
var p = document.getElementsByTagName(‘p’)[0];
p.addEventListener(‘click’, stopsPropagation);
p.addEventListener(‘click’, showsAlert);
88
89.
Всплытиеfunction stopsPropagation(event) {
event.stopPropagation();
}
function showAlert(event) {
alert(event.target.tagName); // SPAN
}
89
90.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>
<span>....</span>
</p>
</div>
90
91.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>
<span>....</span>
</p>
</div>
91
92.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>
<span>....</span>
</p>
</div>
92
93.
Всплытиеfunction stopsPropagation(event) {
event.stopImmediatePropagation();
}
function showAlert(event) {
alert(event.target.tagName); // SPAN
}
93
94.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>
<span>....</span>
</p>
</div>
94
95.
Всплытие<div onclick=“alert(‘Click!’)”>
<p>
<span>....</span>
</p>
</div>
95
96.
ВсплытиеНе все события всплывают!
Пример такого события – focus.
96
97.
ВсплытиеНа самом деле есть не только всплытие, но и погружение
событий!
97
98.
ВсплытиеФазой, на которой будет обрабатываться событие, управляет
третий, необязательный аргумент addEventListener
elt.addEventListener(‘click’, handler, true);
Для того, чтобы поймать событие на стадии «погружения», нужно
передать его == true
98
99.
ВсплытиеКстати, событие focus...
Оно не всплывает, но погружается.
99
100.
ВсплытиеКстати, событие focus...
Оно не всплывает, но погружается.
100
101.
Делегирование101
102.
ДелегированиеЗадача: хотим при нажатии на каждый абзац в документе считать
сколько в нем слов.
102
103.
ДелегированиеРешение 1 (плохое)
var pCol = document.getElementsByTagName(‘p’);
for(var i = 0, l = pCol.length; i < l; i++) {
pCol.addEventListener(‘click’, countWords);
}
103
104.
ДелегированиеЧем плохо это решение?
104
105.
ДелегированиеЧем плохо это решение?
1. Если элементов будет много их перебор может занять время
2. Навешивается обработчиков по количеству параграфов
3. Если в документ добавятся новые параграфы для них код
работать не будет, ведь они появились позже!
105
106.
ДелегированиеРешение 2 (почти правильное). Делегирование!
document.body.addEventListener(‘click’, function(event) {
if (event.target.nodeName == ‘P’) {
countWords(event.target);
}
});
106
107.
ДелегированиеРешение 2 (почти правильное). Делегирование!
1. Если элементов будет много их перебор может занять время
2. Навешивается обработчиков по количеству параграфов
3. Если в документ добавятся новые параграфы для них код
работать не будет, ведь они появились позже!
107
108.
ДелегированиеРешение 2 (почти правильное). Делегирование!
1. Если элементов будет много их перебор может занять время
2. Навешивается обработчиков по количеству параграфов
3. Если в документ добавятся новые параграфы для них код
работать не будет, ведь они появились позже!
108
109.
ДелегированиеРешение 2 (почти правильное). Делегирование!
1. Если элементов будет много их перебор может занять время
2. Навешивается обработчиков по количеству параграфов
3. Если в документ добавятся новые параграфы для них код
работать не будет, ведь они появились позже!
109
110.
ДелегированиеРешение 2 (почти правильное). Делегирование!
110
111.
ДелегированиеРешение 2 (почти правильное). Делегирование!
<p>
Текст, часть которого
<strong>выделена жирным</strong>
</p>
111
112.
ДелегированиеРешение 3 (правильное)
function (event) {
var target = event.target;
while (target) {
if (target.nodeName == ‘P’) break;
target = target.parentNode
}
if (target) countWords(target);
}
112
113.
Действие по умолчанию113
114.
Действие по умолчаниюУ многих событий есть действия по умолчанию:
• Click по ссылке – переход
• Mousedown на поле ввода – фокусировка
• Keydown – при нажатии клавиши в поле ввода там
появляется символ
114
115.
Действие по умолчаниюДействие по умолчанию можно отменить
elt.addEventListener(‘click’, function(event) {
event.preventDefault();
});
115
116.
Действие по умолчаниюДействие по умолчанию можно отменить
Если событие навешено через атрибут, можно короче
elt.onclick = function() {
return false;
};
ВНИМАНИЕ! Это не работает, если обработчик навешен через
addEventListener!
116
117.
Действие по умолчаниюДля чего это может применяться?
• Для отмены перехода по ссылке и выполнения вместо этого
какого-либо другого действия.
• Для отмены ввода в <input ...>, например, с целью коррекции
ввода
117
118.
Полезные ссылки118
119.
Учебник• http://javascript.ru/
• http://learn.javascript.ru/
• http://learn.javascript.ru/document
• http://learn.javascript.ru/events-and-interfaces
119
120.
Вопросы есть?120