Объектная модель документа DOM является программным интерфейсом для доступа и манипулирования документом (документ в терминологии SGML/HTML/XML). Координирующая роль в DOM принадлежит консорциуму W3C - http://www.w3.org/DoM/.
Напомним, что HTML-страница является документом со строгой разметкой. Модель DOM позволяет получить доступ, как к элементам разметки, так и свойствам, позволяющими управлять браузером (получить доступ к текущему документу, открыть окно с новым документом, получить данные из другого документа), а также установить обработчики событий на определенные действия мыши, клавиатуры, таймера и пр. Отдельно обрабатываются формы.
За прошедшие годы работы консорциума W3C выпустил следующие
рекомендации группы
The Document Object Model Working Group:
· Document Object Model Level 1
· Document Object Model Level 2 Core
· Document Object Model Level 2 Views
· Document Object Model Level 2 Events
· Document Object Model Level 2 Style
· Document Object Model Level 2 Traversal and Range
· Document Object Model Level 2 HTML
· Document Object Model Level 3 Core
· Document Object Model Level 3 Load and Save
· Document Object Model Level 3 Validation.
Каждый следующий уровень (по номеру) заменяет предыдущий. При этом, браузер обязан поддерживать все предыдущие для обеспечения совместимости.
Основной принцип программирования с использованием JavaScript заключается в управлении свойствами браузера и манипулировании элементами документа, согласно модели DOM.
Базовый уровень функциональности документа обеспечивается объектами, поддерживаемыми даже самыми старыми браузерами. Эта иерархия объектов представляет объектную модель документов уровня 0 (Document Object Model level0 - DOM0), которая исторически появилась до официальных спецификаций W3C. Приведем в пример схему
Применительно к клиентскому Javascript, основным объектом является Window, который ссылается на текущее окно браузера. Остальные объекты, иерархия которых здесь представлена, являются свойствами корневого объекта Window. Почти все эти объекты имеют много полезных свойств, с ними связаны события и методы, использование которых позволяет создавать сценарии, обеспечивающие необходимую функциональность. Коротко отметим объекты верхнего уровня иерархии.
Объект Screen (свойство screen) позволяет прочитать разрешение клиентского экрана и глубину цвета. Определив разрешение экрана, можно предусмотреть разные варианты компоновки страницы, устанавливать размеры и положение новых окон, открывающихся из сценария. Методы для этого объекта не определены, но определен ряд свойств, среди которых:
· width - текущая ширина экрана в пикселах;
· height - текущая высота экрана в пикселах;
· availWidth - доступная ширина экрана в пикселах;
· availHeight - доступная высота экрана в пикселах.
·
Объект Navigator (свойство navigator) предоставляет информацию о версии браузера.
Объект Location (свойство location) предоставляет доступ к URL документа, отображаемого в окне браузера. Позволяет определить полный URL, а также его части: протокол, доменное имя и т.д. В отличие от двух предыдущих объектов, его свойства доступны не только для чтения, но и для изменения. То есть, в зависимости от выполнения условий, определенных в сценарии, можно
загрузить нужный документ как в текущее окно или его фрейм, так и в любое из окон, открытых из сценария. Этот объект имеет и два метода:
· reload() перезагружает указанный в качестве аргумента документ;
· replace() загружает указанный документ, который замещает текущий в списке истории просмотра.
Объект History (свойство history) имеет единственное свойство length (количество просмотренных в данном сеансе документов), и три метода, позволяющих перемещаться по истории просмотра:
· back() - на один шаг назад по истории просмотра;
· forward() - на один шаг вперед по истории просмотра;
· go(n) - на n шагов по истории просмотра (если n >0, то вперед, если n <0, то назад).
Объект Document (свойство document), его свойства и методы предоставляют наиболее богатые возможности для разработчика. Приведенная выше схема иерархии объектов включает только основные свойства этого объекта, определенные в базовой объектной модели документа (Document Object Model Level 0 - DOM0). Эти свойства также поддерживаются современными браузерами в рамках более новых моделей DOM.
Массив frames[] предоставляет доступ к документам, загруженным в фреймы.
Следует отметить, что разные браузеры, поддерживая рассматриваемую иерархию, предлагают и дополнительные свойства почти для каждого объекта. Однако использовать не рекомендуется использовать то, что не задекларировано в моделях DOM согласно спецификациям W3C, поскольку это потенциально приведет к проблемам совместимости с браузерами.
В качестве примера приведём фрагмент кода JavaScript из Wikipedia, позволяющий проверить заявленную поддержку различных расширений DOM в конкретном браузере.
function domImplementationTest(){ var featureArray = ['HTML', 'XML', 'Core', 'Views',
'StyleSheets', 'CSS', 'CSS2', 'Events',
'UIEvents', 'MouseEvents', 'HTMLEvents', 'MutationEvents', 'Range', 'Traversal']; var versionArray = ['1.0', '2.0', '3.0'];
var i; var j;
if(document.implementation && document.implementation.hasFeature){ for(i=0; i < featureArray.length; i++){ for(j=0; j < versionArray.length; j++){ document.write(
'Поддержка расширения '+ featureArray[i] + ' версии ' + versionArray[j] + ': ' +
(document.implementation.hasFeature(featureArray[i], versionArray[j])?
'<font style="color:green">true</font>': '<font style="color:red">false</font>') + '<br/>'
);
}
document.write('<br/>');
}
}
}
Документацию по DOM-моделям и использованию в JavaScript следует смотреть по ссылкам: http://www.w3.org/standards/techs/dom#w3c all и https://developer.mozilla.org/en/DOM Levels.
Работа с документами
Работа с документами описывается в спецификациях DOM Core и является основой для динамического изменения отображаемых страниц.
Приведем пример:
<html>
<head>
<title>Sample Document</title>
</head>
<body>
<h1>An HTML Document</h1>
<p>This is a <i>simple</i> document.
</body>
</html>
В соответствии с DOM-моделью, эта страница будет представлена деревом узлов, изображенном на рисунке 3.
Рисунок 3 Дерево разора HTML
Каждый узел может иметь дочерние узлы. Для доступа к этим узлам существует интерфейс Node, который предоставляет свойства childNodes, firstChild, lastChild, nextSibling, previousSibling и parentNode, а также методы
appendChild(), removeChild(), replaceChild() и insertBefore(). Однако также возможно обратиться через свойство, имеющее имя узла. Например document.body.h1.
Каждый элемент этого дерева (т.е. объект Node) имеет определенный тип, который хранится в свойстве nodeType. Для справки некоторые из них приводятся в таблице 2.
Интерфейс | Константа nodeType | Значение nodeType |
Element | Node.ELEMENT NODE | 1 |
Text | Node.TEXT NODE | 3 |
Document | Node.DOCUMENT NODE | 9 |
Comment | Node.COMMENT NODE | 8 |
DocumentFragment | Node.DOCUMENT FRAGMENT NODE | 11 |
Attr | Node.ATTRIBUTE NODE | 2 |
Таблица2 Основные типы узлов
Рисунок 4 Иерархия типов узлов модели DO M
Иерархия типов приводится на рисунке 4.
В коде JavaScript программы предоставляется возможность поиска элементов по имени.
var tables = document.getElementsByTagName("table"); а!егМ"Количество таблиц в документе: " + tables.length);
Если же нужен конкретный элемент, то либо необходимо знать его порядковый номер в массиве найденных элементов, либо иметь возможность идентифицировать по классу, либо идентификатору.
В следующем примере будет найден 4-й параграф
var myParagraph = document.getElementsByTagName("p");
В этом примере будет найден параграф, имеющий уникальный идентификатор specialParagraph. Обратите внимание на то, что одинаковых идентификаторов в одном документе быть не может.
<p id="specialParagraph">
…
var myParagraph = document.getElementById("specialParagraph");
Более сложный пример манипулирования элементами списка:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Cop™poBKa списка. Дэвид Флэнаган. JavaScript.</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script>
function sortkids(e) {
// Это элемент, потомки которого должны быть отсортированы if (typeof e == "string") e = document.getElementById(e);
// Скопировать дочерние элементы (не текстовые узлы) в массив var kids = [];
for(var x = e.firstChild; x!= null; x = x.nextSibling)
if (x.nodeType == 1 /* Node.ELEMENT NODE */) kids.push(x);
// Выполнить сортировку массива на основе текстового содержимого // каждого дочернего элемента. Здесь предполагается, что каждый // потомок имеет единственный вложенный элемент - узел Text kids.sort(function(n, m) { // Функция сравнения для сортировки var s = n.firstChild.data; // Текстовое содержимое узла n var t = m.firstChild.data; // Текстовое содержимое узла m if (s < t) return -1; // Узел n должен быть выше узла m else if (s > t) return 1; // Узел n должен быть ниже узла m else return 0; // Узлы n и m эквивалентны
});
// Теперь нужно перенести узлыпотомки обратно в родительский элемент // в отсортированном порядке. Когда в документ вставляется уже // существующий элемент, он автоматически удаляется из текущей позиции,
// в результате операция добавления этих копий элементов автоматически
// перемещает их из старой позиции. Примечательно, что все текстовые узлы,
// которые были пропущены, останутся на месте.
for(var i = 0; i < kids.length; i++) e.appendChild(kids[i]);
}
</script>
</head>
<body>
<ul id="list"> <!-Этот список будет отсортирован >
<^>один<^>два<^>три<^>четыре<^>пять
<!-- элементы не в алфавитном порядке -->
</ul>
<!-- кнопка, щелчок на которой запускает сортировку списка -->
<button onclick="sortkids('list')">Сортировать по алфавиту</button> </body>
</html>
Часто бывает полезно вставить элементы не как объекты, а как HTML текст. Для этого существует свойство innerHTML. Однако помните, что использование этого свойства полностью удалит все дочерние элементы, если они были у владельца innerHTML.
Пример заполнения заголовка в таблице у созданного элемента table:
var table = document.createElement("table"); // Создать элемент <table>
table.border = 1; // Установить атрибут
// Добавить в таблицу заголовок Имя|Тип|Значение
table.innerHTML = "<tr><th>Имя</th><th>Тип</th><th>Значение</th></tr>";
Обработка событий
Рассмотрим следующий код
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Вывод структуры страницы.</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
#result {font-style: italic;}
div.text p { margin: 0 5px 5px 5px; background-color:yellow}
</style>
<script type="text/javascript">
function print(el)
{
// По идентификатору находим элемент,
// в который надо поместить результат
var result = document.getElementById('result');
result.innerHTML = "<hr/><p>"+Date()+"</p>" +
"<" + el.nodeName + ">" + el.textContent +
"<p>Вывод завершен!</p><hr/>";
}
function mouseOver(el)
{
el.style.backgroundColor = "green";
}
function mouseOut(el)
{
el.style.backgroundColor = "yellow";
}
</script>
</head>
<body>
<div>
<h1>События HTML</h1>
<p>Нажмите на текст любого параграфа</p>
</div>
<div class="text">
<p onclick="print(this)">1. Параграф внутри div!</p>
<p onclick="print(this)">2. Параграф внутри div!!</p>
</div>
<div class="text">
<p onclick="print(this)"
onMouseOut="mouseOut(this)" onMouseOver="mouseOver(this)">
3. Параграф внутри интересующего нас div!!!</p>
<p onclick="print(this)"
onMouseOut="mouseOut(this)" onMouseOver="mouseOver(this)">
4. Параграф внутри интересующего нас div!!!!</p>
</div>
<!-- Сюда поместим результат -->
<div id="result"></div>
</body>
</html>
Элементы HTML имеют атрибуты, позволяющие назначить обработчики. В представленном примере для элементов <p> назначаются обработчики onclick (щелчок мышью по элементы), onMouseOver (появление указателя мыши над элементом), onMouseOut (выход указателя мыши за пределы элемента). Значение this, передаваемое обработчикам, содержит указатель на элемент, вызывающий этот обработчик.
В коде обработчиков для изменения цвета фона используются свойства, предоставленные DOM-моделью.
function mouseOver(el)
{
el.style.backgroundColor = "green";
}
В обработчике щелчка мышью производится поиск элемента для вставки, а также извлекается содержимое инициировавшего его элемента:
function print(el)
{
var result = document.getElementById('result'); result.innerHTML = "<hr/><p>"+Date()+"</p>" +
"<" + el.nodeName + ">" + el.textContent + "^^ывод завершен!</p><hr/>";
}
Объект, созданный вызовом Date(), содержит текущие дату и время.
Библиотека jQuery
jQuery - библиотека для упрощения манипулирования объектами. Позволяет существенно сократить объем кода за счет специальных объектом и методов. Основная документация доступна по адресу http://docs.iquery.com.
Библиотека не претендует на покрытие всех возможных функций, которые могут потребоваться программисту. В комплекте jQuery содержится лишь минимально необходимый набор для манипулирования с объектами и обеспечения AJAX-взаимодействия. Расширения, такие как дополнительные графические управляющие элементы, могут быть реализованы как плагины.
Основная идея в jQuery заключается в том, что выборка элементов осуществляется с помощью селекторов, аналогичных CSS с похожим, но расширенным синтаксисом. Отбор при помощи селектора осуществляется с помощью функций $() или jQuery().
Помимо доступа при помощи селекторов, предоставляется большое количество сервисных функций.
Пример. Необходимо выделить все четные строки таблицы:
<!DOCTYPE html>
<html>
<head>
<style> table {
background:#f3f7f5;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<table border="1">
<tr><td>Row with Index #0</td></tr>
<tr><td>Row with Index #1</td></tr>
<tr><td>Row with Index #2</td></tr>
<tr><td>Row with Index #3</td></tr>
</table>
<script>$("tr:odd").css("background-color", "#bbbbff");</script>
</body>
</html>
Обратите внимание, что подключается версия jQuery непосредственно с сайта авторов библиотеки.
Результат представлен на рисунке 5.
Пример таблицы с программно изменёным стилем строк.
В виду того, что концепция jQuery заключается в простоте замены свойств элементов существующей разметки, разработано большое количество графических плагинов. С некоторыми примерами можно ознакомиться по ссылке http://iquervui.com/demos/.
Следующий пример (http://jqueryui.com/demos/sortable/) демонстрирует возможности переопределения стандартного списка, обеспечивая возможность перемещения элементов мышью.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery UI Sortable - Default functionality</title>
<script src="js/jquery.js"></script>
<script src="js/ui/jquery-ui.js"></script>
<link rel="stylesheet" href="js/demos.css">
<style>
#sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
#sortable li {
margin: 0 5px 5px 5px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 18px; background-color:cyan }
#sortable li span { position: absolute; margin-left: -1.3em; }
</style>
<script>
$(function() {
$("#sortable").sortable();
$("#sortable").disableSelection();
});
</script>
</head>
<body>
<div class="demo">
<ul id="sortable">
<li class="ui-state-default">Item 1</li>
<li class="ui-state-default">Item 2</li>
<li class="ui-state-default">Item 3</li>
<li class="ui-state-default">Item 4</li>
<li class="ui-state-default">Item 5</li>
<li class="ui-state-default">Item 6</li>
<li class="ui-state-default">Item 7</li>
</ul>
</div><!-- End demo -->
</body>
</html>
Обратите внимание на то, что для того, чтобы список ul стал управляемым, необходимо лишь присвоить ему идентификатор (id-'sortable"), который будет использован для переопределения элемента в специальной функции $().
$(function() {
$("#sortable").sortable();
$("#sortable").disableSelection();
});
Отметим, что в данном случае, функция $() получает в качестве аргумента функциональный литерал, а её назначение - гарантировать, что выполнение этого кода произойдёт после полной загрузки кода библиотеки jQuery.
Рассмотрим внедрение обработчиков. Для примера возьмем ту же задачу подсветки параграфов и реакции на нажатие на параграф, которая была рассмотрена с использованием «чистого» Javascript.
<!DOCTYPE html>
<html>
<head>
<^^е>Вывод структуры страницы.</^^е>
<meta charset="utf-8" />
<style>
#result {font-style: italic;}
div.text p { margin: 0 5px 5px 5px; background-color:yellow}
</style>
<script src="js/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("div.text p").mouseover(function(){ this.style.backgroundColor = "green";
}).mouseout(function(){
this.style.backgroundColor = "yellow";
}).click(function () {
// По идентификатору находим элемент, в который надо поместить результат $("#result").html("<hr/><p>"+Date()+"</p>" +
"<" + this.nodeName + ">" + this.textContent +
"^^ывод завершен!</pXhr/>");
})
})
</script>
</head>
<body>
<div>
<h1>События HTML</h1>
<p>Нажмите на текст любого параграфа<^>
</div>
<div class="text">
<p>1. Параграф внутри интересующего нас div!</p>
<p>2. Параграф внутри интересующего нас div!!</p>
</div>
<div class="text">
<p>3. Параграф внутри интересующего нас div!!!</p>
<p>4. Параграф внутри интересующего нас div!!!!</p>
</div>
<!-- Сюда поместим результат -->
<div id="result"></div>
</body>
</html>
Следует обратить внимание на то, что в этом случае HTML-разметка не содержит декларации обработчиков. Назначение обработчиков происходит из библиотеки jQuery при помощи соответствующих свойств DOM-модели, однако доступ к ним осуществляется через методы самой библиотеки.
Обратите внимание на то, что метод $(document).ready вызывается только после того, как браузером загружен весь код страницы и всех подключаемых js-файлов. Только после этого можно безопасно назначить обработчики. В соответствии с принципами jQuery их назначение производится через селектор
$("div.text p").mouseover(function (){…}
Задание лабораторной работы №2
Реализовать 2-3 функции для уже реализованного сайта.(в шапке написано какие именно должны быть функции)
Не важно JS или jQuery.
Можно использовать фреймворки, главное чтобы было понимание.
В отчете привести код страницы с программой формирования таблицы, формы, отображаемые на экране и пример работы программ