§20. Что вы ещё должны знать. Заключение.

Учимся программировать вместе с JavaScript
Глава III. Клиентский JavaScript. Заключение.

§20. Что вы ещё должны знать. Заключение.

Модель DOM. Доступ к некоторым элементам через свойства объекта document. Значение null. Исключения. Продвинутый способ обработки событий. Всплытие событий. Остановка всплытия события. Погружение и всплытие события. Целевой элемент. Использование слова this при написании обработчиков событий. Работа с фреймами. Имитация графики за счёт изменения свойств CSS. Заключение.

Модель DOM. 

DOM - Document Object Model, модель построения html документа организующая доступ ко всем элементам. Данная модель рассматривает структуру html документа в виде дерева очень похожего на родовое дерево. 

Примечание: отличием является то, что в родовом дереве родители находятся внизу, а в дереве DOM родительские элементы находятся вверху. 

В связи с этим сходством от родового дерева заимствована следующая терминология: 

Родительский элемент - элемент, в который вложены другие дочерние элементы; 

Узел - объект-элемент, который имеет потомков. 

На практике модель DOM реализована виде ряда свойств, организующих доступ к элементам. Они представлены далее в таблицах:  

 

Свойства объекта document: 

Свойство 

Описание 

documentElement 

Элемент html 

Body 

Элемент body 

 

Свойства элементов: 

Свойство 

Описание 

childNodes 

Массив всех дочерних элементов. 

firstChild 

Первый потомок узла. Равен null если детей нет. 

lastChild 

Последний потомок узла. Равен null если детей нет. 

parentNode 

Родительский элемент. 

previousSibling 

Предыдущий брат элемент. 

nextSibling 

Следующий брат элемент. 

nodeType 

Тип элемента. Всего 12 типов. Значение 1 - html тэги. 3 - текстовый элемент. 8 - комментарий. Более подробно см. в Интернете. 

 

Доступ к некоторым элементам через свойства объекта document. 

Помимо уже изученных нами способов доступа к элементам есть ещё один через свойства объекта document. Они представлены далее в таблице: 

  

Свойство 

Описание 

anchors[] 

Массив объектов якорных элементов. 

applets[] 

Массив Java-апплетов. 

forms[] 

Массив объектов элементов form. 

images[] 

Массив объектов элементов img. 

links[] 

Массив объектов элементов a. 

 

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

Примечание: данные свойства появились вместе с JavaScript. В дальнейшем возможности языка для доступа к элементам были расширены. Тем не менее, этими свойства удобно пользоваться и сейчас. 

 

Значение null. 

Если вы просматривали строение элементов с помощью конструкции fo/in, то вы должны были видеть, что некоторые свойства имеют значение null. null в JavaScript говорит об отсутствии объекта. Для примера выведем строение объекта div: 

 

<body> 

<div id = "d">Привет всем!</div> 

<script> 

var ob = d; 

for (prop in ob 

  document.write(prop,' - ',typeof ob[prop],' = ',ob[prop],'<br>'); 

</script> 

</body> 

 

 

Исключения. 

Исключение или исключительная ситуация - это возникновение ошибки во время выполнения кода. Для того, что бы компьютер не зависал, и программа смогла работать дальше при возникновении исключения, существует конструкция try/catch/finally. В коде программы она выглядит следующим образом: 

 

try { 

  //Код, при выполнении которого  

  //может возникнуть исключение 

} 

cath (e) { 

  //Код, который выполняется в случае 

  //возникновения исключения 

  //e - объект созданный конструктором Error 

  //в момент возникновения ошибки, 

  //и который содержит информацию о ней. 

} 

Finally { 

  //Код, который выполняется в любом случае 

} 

 

В блоке кода catch вы можете пользоваться переменной указанной в скобках. Она в свою очередь является объектом созданным конструктором Error в момент возникновения ошибки, и содержит в себе информацию об этой ошибке. 

Здесь надо сказать, что эта переменная просто так не создаётся. Для её создания необходимо использовать инструкцию throw в функции, которая вызывается в блоке кода try. Пример: 

 

  throw new Error(str); 

 

Здесь строка str будет содержать сообщение об ошибке. 

Опишем весь процесс создания и использования исключений. Когда программист создаёт функцию, например функцию производящую деление, он  предусматривает все возможные исключительные ситуации. В случае с делением исключительной будет ситуация, когда будет произведено деление на ноль. В этом случае и необходимо создать объект Error с помощью инструкции throw: 

 

function div(x,y) { 

  if (y == 0) 

    throw new Error('Делить на ноль нельзя!'); 

  else 

    return x/y; 

} 

 

В коде программы «перехват» данного исключения будет выглядеть следующим образом: 

 

try {var r = div(3,0)} 

catch (e) {alert(e)} 

finally {document.write(r)}; 

 

 

 

Здесь необходимо добавить, что многие изученные нами методы имеют исключения. В рамки данного учебника их перечисление не входит. Для того, что бы узнать какие исключения имеет тот или иной метод обратитесь к Интернету. 

Примечание: создание исключений, как правило, необходимо в случаях, когда программист пишет код, который в дальнейшем будет использован другими программистами. 

 

Продвинутый способ обработки событий. 

Существует ещё один способ установки обработчика события с помощью метода элемента addEventListener(E,F), где E – строка с именем события. Имена событий такие же, как и атрбуты-события элементов, только без приставки on; Fфункция, которая должна быть вызвана при наступлении события. 

Пример: 

 

<body> 

<div id = "div_1" style = "border:red solid;">div_1</div> 

<script> 

div_1.addEventListener('click',function(e) {alert('Вы нажали на div_1.')}); 

</script> 

</body> 

 

 

 

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

 

<body> 

 

<div id = "div_1" style = "border:red solid;">div_1</div> 

 

<script> 

div_1.addEventListener('click',function(e) {alert('Вы нажали на div_1.')}); 

</script> 

 

<script> 

function changeColor(e) {div_1.style.borderColor = 'brown';}; 

 

div_1.addEventListener('click',changeColor); 

</script> 

</body> 

 

Теперь помимо всплывающего окна рамка после нажатия будет становиться коричневого цвета. 

Примечание: обратите внимание, что в качестве аргумента методу addEventListener передана уже описанная выше функция, а её идентификатор употреблён без скобок. Такой способ предпочтительней. 

Так же существует возможность удаления обработчика события с помощью метода removeEventListener(E,F), где E и Fстрока события и функция, установленные методом addEventListener. Здесь есть два нюанса: удалить можно только тот обработчик, который был добавлен методом addEventListener; второй нюанс - если функция переданная методу addEventListener была описана непосредственно при передаче, то удалить её тоже нельзя. Пример: 

 

<script> 

div_1.removeEventListener('click',changeColor); 

</script> 

 

Теперь рамка после нажатия останется красной. 

 

 

 

Всплытие событий. 

Как вы уже знаете, существуют родительские элементы и дочерние. Если родительский и дочерний элементы имеют обработчики нажатия кнопки мыши, то при щелчке на дочернем элементе вначале запуститься его обработчик, а затем обработчик родительского элемента. Данное утверждение демонстрирует следующий пример: 

 

<body> 

<div style = "border:red solid;" onclick = "alert('div_1')">div_1 

  <div style = "border:brown solid;" onclick = "alert('div_2')">div_2 

    <div style = "border:green solid;" onclick = "alert('div_3')">div_3 

    </div> 

  </div> 

</div> 

</body> 

 

 

Если нажать на элемент div_1, то сработает обработчик только элемента div_1: 

 

 

Если нажать на элемент div_2, то вначале сработает обработчик элемента div_2, а затем элемента div_1: 

 

 

 

Если нажать на элемент div_3, то вначале сработает обработчик элемента div_3, затем div_2 и div_1. Этот процесс срабатывания обработчиков от дочерних элементов к родительским называется всплытием события. Всплытие потому, что в дереве элементов родительские элементы находятся выше дочерних. Поэтому событие как будто шарик «всплывает» снизу вверх. 

 

Остановка всплытия события. 

В некоторых ситуациях, если мы создали обработчик нажатия на один элемент, то нам не нужно, что бы при этом срабатывали обработчики родительских элементов. Для этого существует метод event.stopPropagation(), который останавливает всплытие. Следующий пример является изменённой версией предыдущего. Все изменения выделены жирным шрифтом. В результате его работы при нажатии на div_3 событие всплывать не будет. 

 

<body> 

<div style = "border:red solid;" onclick = "alert('div_1')">div_1 

  <div style = "border:brown solid;" onclick = "alert('div_2')">div_2 

    <div style = "border:green solid;" onclick = "fDiv_3()">div_3 

    </div> 

  </div> 

</div> 

 

<script> 

function fDiv_3() 

{ 

  alert('div_3'); 

  event.stopPropagation(); 

} 

</script> 

</body> 

 

Примечание: остановка всплытия не останавливает выполнение остальных обработчиков данного события данного элемента. 

 

Погружение и всплытие события. 

Существует ещё один способ распространения события – от родительского элемента к дочернему и обратно. 

Процесс распространения от родительского элемента к  дочернему называется погружением события (как будто шарик погружается с верху вниз). 

Для того, что бы этот способ начал работать необходимо методу addEventListener(E,F,B) передать третий аргумент B, который представляет собой логическое значение. Если оно равно true, то обработчик будет вызван при погружении, и наоборот. Следующий пример наглядно демонстрирует вышесказанное: 

 

<body> 

<div id = "div_1" style = "border:red solid;">div_1 

  <div id = "div_2" style = "border:brown solid;">div_2 

    <div id = "div_3" style = "border:green solid;">div_3 

    </div> 

  </div> 

</div> 

 

<script> 

function fDiv_1Float() {alert('div_1 всплытие')}; 

function fDiv_1Dive() {alert('div_1 погружение')}; 

function fDiv_2Float() {alert('div_2 всплытие')}; 

function fDiv_2Dive() {alert('div_2 погружение')}; 

function fDiv_3Float() {alert('div_3 всплытие')}; 

function fDiv_3Dive() {alert('div_3 погружение')}; 

 

div_1.addEventListener('click',fDiv_1Float,false); 

div_1.addEventListener('click',fDiv_1Dive,true); 

div_2.addEventListener('click',fDiv_2Float,false); 

div_2.addEventListener('click',fDiv_2Dive,true); 

div_3.addEventListener('click',fDiv_3Float,false); 

div_3.addEventListener('click',fDiv_3Dive,true); 

 

</script> 

 

Здесь есть один нюанс: когда событие доходит до элемента на котором оно произошло, то вначале вызывается его обработчик всплытия, а затем погружения. После чего событие начинает всплытие к родительскому элементу. Следующий рисунок наглядно демонстрирует данный нюанс: 

 

 

 

На рисунке цифрами обозначен порядок вызова обработчиков, если щелчок произошёл на элементе div_3. 

Примечание: При удалении обработчика методом removeEventListener(E,F,B) значение третьего аргумента B должно быть таким же, как и при установке обработчика методом addEventListener. 

Так же необходимо сказать, что метод event.stopPopagation() остановит распространение события и на стадии погружения. 

 

Целевой элемент. 

Целевой элемент – элемент, в котором непосредственно произошло событие. В нашем предыдущем случае целевым элементом называется элемент, на котором произошёл щелчок мыши. Для того, что бы обратиться непосредственно к этому элементу в процессе всплытия или погружения события существует объект event.target, который является ссылкой на целевой элемент. Для примера добавим к предыдущему примеру следующий код: 

 

function fDiv_1()  

  { 

    alert('Щелчок произошёл на '+event.target.id) 

  }; 

div_1.addEventListener('click',fDiv_1); 

 

Плюсом ко всем сообщениям добавиться ещё одно с информацией о том, на каком элементе произошёл щелчок: 

 

 

 

Использование слова this при написании обработчиков событий. 

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

Здесь стоит заострить внимание на разнице объекта event.target и слова this. event.targetцелевой элемент, именно в данном объекте и произошло событие, thisявляется ссылкой на элемент, обработчик которого был вызван при погружении или всплытии события. 

 

Работа с фреймами. 

Если документ состоит из фреймов, то с помощью JavaScript можно загружать и изменять содержимое документов в каждом фрейме. Данная тема не освящается в данном учебнике. При необходимости может изучить её самостоятельно. 

 

Имитация графики за счёт изменения свойств CSS. 

Ещё одна тема, которая не была освящена в данном учебнике - это имитация графики за счёт изменения свойств css. Для того, что бы вставить рисунок вместо тэга img можно использовать свойство background-image элемента span. Для рисования линий можно воспользоваться свойством border, для рисования окружностей - border-radius. Для размещения элементов на экране в нужной позиции используется свойство position со значением absolute. И т.д.  

Данный способ создания графических изображений имеет преимущество в том плане, что любой браузер должен отобразить подобный рисунок. А так же это хорошая практика в обучении программированию. 

 

Заключение. 

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

Если что-то не получится, то следующая глава как раз посвящена решению данных задач. Даже если вы решили задачи, то будет полезно с ней ознакомиться для того, что бы понять, что именно имелось в виду в задании. 

Так же можете придумать свои задания. Наилучшим способом дальнейшего обучения может стать копирование готовых страниц из Интернета. Для этого откройте любую понравившеюся страницу и попробуйте написать её с нуля. Создавать заново рисунки конечно не обязательно, сохранить их можно с помощью комбинации клавиш ctr+S. При этом они вместе с другими файлами сохранятся в отдельную папку. 

 

Задачи. 

1. Вывести дерево элементов html документа. 

2. Создать какой-либо график за счёт изменения свойств css. 

3. Создать меню. 

4. Создать страницу с онлайн клавиатурой, нажимать на которую необходимо мышкой. 

5. Создать онлайн калькулятор для вычисления интегралов, нахождения корней линейных уравнений с несколькими неизвестными, для работы с матрицами и т.д. 

6. Создать онлайн painter, программу для рисования простейших изображений. 

7. Создать онлайн клавиатурный тренажёр. Программу для тренировки набора текста не глядя в клавиатуру. 

8. Создать какую-либо онлайн игру за счёт изменения свойств CSS. 

9. Создать какую-либо онлайн игру в тэге canvas. 

10. Создать страницу с базой данных фильмов (или чего либо другого). 

11. Используя уже имеющиеся у вас знания, создать страницу копию любой страницы из Интернета.