Робота з DOM-моделлю. Що таке DOM і навіщо він потрібен? файл dom

В даному уроці ми розберемо основи роботи з подіями, атрибутами і getElementById на мові JavaScript.

У попередніх уроках ми з вами вивчали базові можливості мови JavaScript. Починаючи з цього уроку ми займемося тим, для чого власне JavaScript і призначений - ми будемо змінювати елементи HTML сторінки і реагувати на дії користувача. Наші скрипти стануть більш видовищними і корисними.

Почнемо ми з того, що навчимо наш код реагувати на дії користувача сайту. Наприклад, користувач натисне куди-небудь мишкою, а наш код у відповідь повинен буде обробити це натискання і вивести на екран будь-яку інформацію.

Вирішення проблеми, які ми можемо відстежити через JavaScript, називаються подіями. Події можуть бути наступними: клік мишкою на елемент сторінки, наведення мишкою на елемент сторінки або навпаки - догляд курсору миші з елементу і так далі. Крім того, є події, які не залежать від дій користувача, наприклад, подія по завантаженню HTML сторінки в браузер.

В JavaScript існує кілька способів роботи з подіями. Ми почнемо з найпростішого з них.

Основи роботи з подіями

Найпростіший спосіб задати реакцію елемента на певну подію - вказати її за допомогою атрибута для певного тега. Наприклад, події "Натискання мишкою" відповідає атрибут onclick, події "Наведення мишкою" - атрибут onmouseover, А події "Догляд курсора з елемента" - атрибут onmouseout.

Значенням атрибута з подією служить JavaScript код. У наступному прикладі після натискання мишкою на кнопку виконається функція alert:

А зараз при натисканні на елемент виконається функція func:

function func () (alert ( "!");)

можна виконати не одну функцію, А кілька:

function func1 () (alert ( "1");) function func2 () (alert ( "2");)

Зверніть увагу на те, що якщо всередині атрибута вам потрібні подвійні лапки (наприклад, для рядка) і зовнішні лапки атрибута теж подвійні - onclick \u003d "alert ("! ")" - такий код не буде працювати.

З цим можна боротися декількома способами: можна змінити зовнішні лапки на одинарні onclick \u003d "alert ("! ")", Можна також заекранувати внутрішні лапки зворотним слешем onclick \u003d "alert (\\"! \\ ")" або ж просто перенести JavaScript код з атрибута в функцію, а в атрибуті залишити тільки ім'я функції onclick \u003d "func ()".

Те ж саме буде, якщо ви зовнішні лапки атрибута ставите одинарними і для рядка теж використовуєте одинарні: onclick \u003d "alert ("! ")" - тут також все вирішується аналогічними способами.

Таблиця атрибутів для подій

Робота з getElementById

Зараз ми з вами навчимося отримувати елементи HTML сторінки і проводити з ними різні маніпуляції (Ми зможемо змінювати, наприклад, їх текст і колір і багато інших корисних речей).

Нехай у нас на сторінці є тег з атрибутом id у значенні test. Запишемо посилання на цей тег в змінну elem. Для цього ми повинні скористатися методом getElementById, Який отримує елемент по його id.

Ця запис станеться при натисканні на кнопку, якою ми задали атрибут onclick. При натисканні на цю кнопку спрацює функція func, Яка знайде на HTML сторінці елемент з id рівним test і запише посилання на нього в змінну elem:

Тепер у змінній elem у нас лежить посилання на елемент з атрибутом id у значенні test. сама змінна elem є об'єктом.

Цей об'єкт і тег HTML сторінки пов'язані один з одним - ми можемо поміняти будь-які властивості об'єкта elem і при цьому побачимо зміни на HTML сторінці, які відбудуться з отриманим нами елементом.

Давайте подивимося, як це відбувається на практиці.

Основи роботи з атрибутами HTML через JavaScript

Зараз ми будемо зчитувати і змінювати атрибути тегів. Нехай у нас знову дано інпут з id рівним test і кнопка, При натисканні на яку буде запускатися функція func:

усередині функції func ми отримаємо наш інпут по його id і запишемо посилання на нього в змінну elem:

function func () (var elem \u003d document.getElementById ( "test");)

Давайте тепер виведемо на екран вміст атрибутів нашого інпут. Щоб отримати доступ, наприклад, до атрибуту value, слід написати наступне: elem.value, Де elem - це змінна, в яку ми з допомогою getElementById записали посилання на наш елемент, а value - це атрибут тега, який нас цікавить.

Ми можемо вивести вміст атрибута через alert таким чином - alert (elem.value) - або записати в якусь змінну. Давайте виконаємо це:

function func () (var elem \u003d document.getElementById ( "test"); alert (elem.value); // виведе "!")

Ми можемо таким же чином зчитувати значення і інших атрибутів, наприклад так - elem.id - ми вважаємо значення атрибута id, а так - elem.type - значення атрибута type. Дивіться приклад:

function func () (var elem \u003d document.getElementById ( "test"); alert (elem.value); // виведе "!" alert (elem.id); // виведе "test" alert (elem.type); // виведе "text")

Можна не тільки зчитувати значення атрибутів, а й змінювати їх. Щоб, наприклад, поміняти значення атрибута value, Потрібно просто привласнити його конструкції elem.value:

function func () (var elem \u003d document.getElementById ( "test"); elem.value \u003d "(! LANG: www"; //присвоим новое значение атрибуту value } !}

HTML код стане виглядати так (значення атрибута value стане www):

Ну, а тепер найскладніше - можна не вводити змінну elem, А будувати ланцюжок з точок таким чином:

function func () (alert (document.getElementById ( "test"). value); // виведе "!")

Таким же чином (ланцюжком) можна виробляти і перезапис атрибутів:

function func () (document.getElementById ( "test"). value \u003d "(! LANG: www"; }!}

Однак, в більшості випадків введення змінної зручніше. Порівняйте два приклади - зараз я ввів змінну elem і можу зчитувати будь-яку кількість атрибутів, при цьому getElementById викликається тільки один раз:

function func () (var elem \u003d document.getElementById ( "test"); elem.value \u003d "(! LANG: www"; elem.type = "submit"; }!}

А зараз я не ввожу нову змінну і тому мені доводиться викликати getElementById два рази:

function func () (document.getElementById ( "test"). value \u003d "(! LANG: www"; document.getElementById("test").type = "submit"; }!}

На мій погляд, цей код став складніше, Хоча і займає на одну сходинку менше. Крім того, якщо я захочу змінити значення id з test на, наприклад, www, мені доведеться робити це в багатьох місцях, що не дуже зручно.

на браузер. Пошук елементів по сторінці, який робить метод getElementById, Є досить повільної операцією ( і взагалі будь-яка робота з елементами сторінки - це повільна операція - запам'ятайте це).

У нашому випадку, якщо ми кожен раз використовуємо getElementById, То браузер кожен раз буде обробляти HTML сторінку і шукати елемент із заданим id кілька раз (не важливо, що id однакові - браузер виконає всі дії кілька разів), здійснюючи марні операції, які можуть сповільнити роботу браузера.

Якщо ж ми використовуємо змінну elem - ніякого пошуку по сторінці не відбувається (елемент вже знайдений і посилання на нього лежить в змінної elem).

Винятки: атрибути class і for

Ви вже навчилися працювати з атрибутами через JavaScript і тепер прийшов час розповісти вам про те, що не все так просто - при роботі з атрибутами існує виняток - це атрибут class.

Це слово є спеціальним в JavaScript і тому ми не можемо просто написати elem.class, Щоб вважати значення атрибута class. Замість цього слід писати elem.className.

У наступному прикладі на екран виводиться значення атрибута class:

function func () (var elem \u003d document.getElementById ( "test"); alert (elem.className);)

До речі, є й інші атрибути, які називаються інакше, ніж властивість. Наприклад, атрибуту for (

Робота з this

Зараз ми з вами будемо працювати зі спеціальним об'єктом this, Який вказує на поточний елемент (елемент в якому відбулася подія). Причому вказує так, ніби цей елемент уже отримано методом getElementById.

Давайте подивимося як працювати з this і в чому зручність такого підходу.

Нехай у нас є завдання після натискання на інпут вивести на екран вміст його value.

Поки ви вмієте робити тільки таке рішення:

function func () (var elem \u003d document.getElementById ( "test"); alert (elem.value);)

В принципі, це рішення хороше, але уявімо тепер, що у нас є багато інпут і після натискання на кожен нам потрібно виводити його value.

В цьому випадку у нас вийде щось в такому роді:

function func1 () (var elem \u003d document.getElementById ( "test1"); alert (elem.value);) function func2 () (var elem \u003d document.getElementById ( "test2"); alert (elem.value);) function func3 () (var elem \u003d document.getElementById ( "test3"); alert (elem.value);)

Тепер ясно видно недолік нашого підходу - для кожного інпут нам доводиться створювати свою функцію обробки кліка, причому роблять ці функції практично одне і теж.

Якщо у нас буде 10 інпут - то доведеться зробити 10 функцій, не зручно.

Давайте спростимо нашу задачу: будемо передавати параметром функції id поточного елемента. І замість великої кількості функцій все зведеться до однієї функції:

function func (id) (var elem \u003d document.getElementById (id); alert (elem.value);)

Однак, таке рішення все одно має недолік - кожному елементу доведеться вводити різні id, що теж трохи незручно.

Отже, давайте нарешті розглянемо варіант вирішення завдання через this.

Зробимо так, що кожен інпут буде виводити свій вміст після натискання. Для цього параметром функції передамо об'єкт this, ось так: func (this).

Наш this передається параметром функції і потрапляє в змінну elem. Цей elem поводиться так, ніби отриманий таким чином: var elem \u003d document.getElementById (...), Але отримувати його таким чином не треба, там вже все готово і можна користуватися. Наприклад, elem.value вказує на value нашого інпут і так далі.

Отже, ось саме просто рішення нашої задачі:

function func (elem) (alert (elem.value);)

Основи роботи з CSS

В JavaScript робота з CSS властивостями відбувається шляхом зміни значення атрибуту style для елемента. Наприклад, щоб поміняти колір потрібно побудувати наступний ланцюжок - elem.style.color - і присвоїти їй потрібне значення кольору:

function func () (var elem \u003d document.getElementById ( "test"); elem.style.color \u003d "red";)

Можна також і не вводити змінну elem, А побудувати дуже довгий ланцюжок.

innerHTML
var text \u003d element.innerHTML;
element.innerHTML \u003d "";
Присвоєння нового innerHTML здійснює перезапис коду, навіть якщо нове значення додано до поточного (+ \u003d). Скрипти, додані таким чином, не виконуються.

outerHTML
Містить елемент цілком, змінити його неможливо. Технічно при записі в це властивість створюється новий елемент, який замінює старий. Посилання на старий елемент в змінних не змінюються.

data
textNode.data - вміст текстових вузлів і коментарів

textContent
element.textContent - текст всередині елемента без тегів.
Існує також нестандартне властивість innerText, що має з textContent багато спільного.

видимість елемента

hidden
element.hidden \u003d true
Атрибут hidden не підтримуються в IE11.

атрибути

Більшість стандартних атрибутів в DOM стають властивостями об'єкта:
element.id \u003d "id"
Для нестандартних атрибутів властивість не створюється (undefined)

Можна створювати власні DOM-властивості:
element.myData \u003d (name: "John", lastName: "Smith");
і методи:
element.myFunc \u003d function () (alert this.nodeName);
Це працює, тому що вузли DOM є звичайними JavaScript-об'єктами. Такі нестандартні властивості і методи не впливають на відображення тега і видно тільки в JavaScript.

Доступ до атрибутів тегів:
element.hasAttribute (name)
element.getAttribute (name)
element.setAttribute (name, value)
element.removeAttribute (name)
element.attributes - псевдомассів атрибутів.

Атрибути нечутливі до регістру (html), а властивості чутливі (javaScript).
Значення атрибута - завжди рядок.

Атрибут: a.getAttribute ( "href") - відображає саме те, що в HTML
Властивість: a.href - може відрізняти від значення атрибута
Найчастіше властивість залежить від атрибута, але не навпаки. Зміна властивості не впливає на атрибут.

Робота з класами

Атрибуту class відповідають два властивості:
className - рядок
classList - об'єкт

методи об'єкта classList:
element.classList.contains ( "class") - перевірка, чи містить об'єкт даний клас
element.classList.add ( "class")
element.classList.remove ( "class")
element.classList.toggle ( "class")

classList є псевдомассівом, його можна перебирати через цикл for.

data-атрибути

Призначені для користувача data -атрібути доступні не тільки як атрибути, а й через властивість dataset
data-about \u003d "some value"
element.dataset.about

порядок вузлів

parent.contains (child) - true або false
перевіряє, чи є вузол child вкладеним в parent

nodeA.compareDocumentPosition (nodeB) - надає інформацію про зміст і відносному порядку елементів. Значення, що повертається - побітова маска:

Додавання і видалення вузлів

var div \u003d document.createElement ( "div")
document.createTextNode ( "text")

parent.appendChild (element) - елемент додається в кінець батька
parent.insertBefore (element, nextSibling) - елемент додається перед nextSibling
parent.insertBefore (element, parent.firstChild) - додається в початок
parent.insertBefore (element, null) - спрацює як appendChild
Всі методи вставки повертають вставлений вузол.
При переміщенні елемента не потрібно його попередньо видаляти зі старого місця, методу вставки роблять це автоматично.

element.insertAdjacentHTML (where, html) - вставка довільного HTML-коду в будь-яке місце документа. Where вказує куди слід вставити html по відношенню до element - beforeBegin, afterBegin, beforeEnd, afterEnd.
element.insertAdjacentElement (where, newElement)
element.insertAdjacentText (where, text)
два останніх методу не підтримуються в Firefox

node.append (... nodes) - вставляє nodes в кінець node,
node.prepend (... nodes) - вставляє nodes в початок node,
node.after (... nodes) - вставляє nodes після вузла node,
node.before (... nodes) - вставляє nodes перед вузлом node,
node.replaceWith (... nodes) - вставляє nodes замість node.
тут nodes - це вузли або рядки, в будь-яких кількостях і поєднаннях, перераховані через кому.

var fragment \u003d document.createDocumentFragment () - імітація DOM-вузла, який при вставці в документ зникає, залишаючи тільки своїх нащадків. В сучасних браузерах не рекомендується.

element.cloneNode (true) - глибока копія елемента
element.cloneNode (false) - копія без дочірніх елементів

parent.removeChild (element)
parent.replaceChild (newElement, element)
element.remove () - видаляє елемент безпосередньо, без посилання на батька.
Методи повертають віддалений вузол

Робота з DOM-моделлю

Кожен об'єкт Window має властивість document, Що посилається на об'єкт Document. Цей об'єкт Document не є автономним об'єктом. Він є центральним об'єктом великого API, відомого як об'єктна модель документа (DOM), який визначає порядок доступу до вмісту документа.

Огляд моделі DOM

Об'єктна модель документа (Document Object Model, DOM) - це фундаментальний прикладний програмний інтерфейс, що забезпечує можливість роботи з вмістом HTML і XML-документів. Прикладний програмний інтерфейс (API) моделі DOM не дуже складний, але в ньому існує безліч архітектурних особливостей, які ви повинні знати.

Перш за все, слід розуміти, що вкладені елементи HTML або XML-документів представлені у вигляді дерева об'єктів DOM. Деревоподібне уявлення HTML-документа містить вузли, що представляють елементи або теги, такі як і

І вузли, що представляють рядки тексту. HTML-документ також може містити вузли, що представляють HTML-коментарі. Розглянемо наступний простий HTML-документ:

приклад документа

Це HTML-документ

приклад простого тексту.

DOM-уявлення цього документа наводиться на наступній діаграмі:

Тим, хто ще не знайомий з деревоподібними структурами в комп'ютерному програмуванні, корисно дізнатися, що термінологія для їх опису була запозичена у генеалогічних дерев. Вузол, розташований безпосередньо над цим вузлом, називається батьківським по відношенню до даного вузла. Вузли, розташовані на один рівень нижче іншого вузла, є дочірніми по відношенню до даного вузла. Вузли, що знаходяться на тому ж рівні і мають того ж батька, називаються сестринськими. Вузли, розташовані на будь-яке число рівнів нижче іншого вузла, є його нащадками. Батьківські, прабатьківські і будь-які інші вузли, розташовані вище даного вузла, є його предками.

Кожен прямокутник на цій діаграмі є вузлом документа, який представлений об'єктом Node. Зверніть увагу, що на малюнку зображено три різних типи вузлів. Коренем дерева є вузол Document, який представляє документ цілком. Вузли, що представляють HTML-елементи, є вузлами типу Element, а вузли, що представляють текст, - вузлами типу Text. Document, Element і Text - це підкласи класу Node. Document і Element є двома найважливішими класами в моделі DOM.

Тип Node і його підтипи утворюють ієрархію типів, зображену на діаграмі нижче. Зверніть увагу на формальні відмінності між узагальненими типами Document і Element, і типами HTMLDocument і HTMLElement. Тип Document представляє HTML і XML-документ, а клас Element представляє елемент цього документа. Підкласи HTMLDocument і HTMLElement представляють конкретно HTML-документ і його елементи:

На цій діаграмі слід також відзначити наявність великої кількості підтипів класу HTMLElement, що представляють конкретні типи HTML-елементів. Кожен з них визначає JavaScript-властивості, що відображають HTML-атрибути конкретного елемента або групи елементів. Деякі з цих специфічних класів визначають додаткові властивості або методи, які не є відображенням синтаксису мови розмітки HTML.

Вибір елементів документа

Робота більшості клієнтських програм на мові JavaScript так чи інакше пов'язана з маніпулюванням елементами документа. В ході виконання ці програми можуть використовувати глобальну змінну document, що посилається на об'єкт Document. Однак, щоб виконати будь-які маніпуляції з елементами документа, програма повинна якимось чином отримати, або вибрати, об'єкти Element, що посилаються на ці елементи документа. Модель DOM визначає кілька способів вибірки елементів. Вибрати елемент або елементи документа можна:

    за значенням атрибута id;

    за значенням атрибута name;

    по імені тега;

    по імені класу або класів CSS;

    за випадковим збігом з певним селектором CSS.

Всі ці прийоми вибірки елементів описуються в наступних підрозділах.

Вибір елементів за значенням атрибута id

Всі HTML-елементи мають атрибути id. Значення цього атрибута повинно бути унікальним в межах документа - ніякі два елементи в одному і тому ж документі не повинні мати однакові значення атрибута id. Вибрати елемент за унікальним значенням атрибута id можна за допомогою методу getElementById () об'єкта Document:

Var section1 \u003d document.getElementById ( "section1");

Це найпростіший і найпоширеніший спосіб вибірки елементів. Якщо сценарієм необхідно мати можливість маніпулювати якимось певним безліччю елементів документа, надайте значення атрибутам id цих елементів і використовуйте можливість їх пошуку за цими значеннями.

У версіях Internet Explorer нижче IE8 метод getElementById () виконує пошук значень атрибутів id без урахування регістру символів і, крім того, повертає елементи, в яких буде знайдено збіг зі значенням атрибута name.

Вибір елементів за значенням атрибута name

HTML-атрибут name спочатку призначався для присвоювання імен елементам форм, і значення цього атрибута використовувалося, коли виконувалася відправка даних форми на сервер. Подібно атрибуту id, атрибут name привласнює ім'я елементу. Однак, на відміну від id, значення атрибута name повинно бути унікальним: одне і те ж ім'я можуть мати відразу кілька елементів, що цілком зазвичай при використанні в формах радіокнопок і прапорців. Крім того, на відміну від id, атрибут name допускається вказувати лише в деяких HTML-елементах, включаючи форми, елементи форм і елементи