Создание скриптов с элементами и коллекциями
Каждый документ HTML состоит из комбинации HTML-тегов и их атрибутов. Эти элементы определяют структуру документа и способ представления контента. С помощью динамической объектной модели HTML (DHTML) можно исследовать и изменить эти элементы и их модифицирующие атрибуты. В следующих разделах разъясняется, как обращаться к элементам документа, используя коллекции элементов.
Коллекции all и children Документ HTML — это иерархическая структура тегов, определяющих содержимое документа. Коллекция all в объекте документа представляет все элементы в иерархии документа. Каждый элемент представлен как программируемый объект, отображающийся в коллекции в исходном порядке. К отдельным объектам элементов можно обращаться по индексу или идентификатору (уникальному имени), как показано в следующем примере. <HTML> <HEAD><TITLE>Элементы: Сбор</TITLE> <SCRIPT LANGUAGE="JScript"> function showElements() { var tag_names = ""; for (i=0; i<document.all.length; i++) tag_names = tag_names + document.all(i).tagName + " "; alert("Этот документ содержит: " + tag_names); } </SCRIPT> </HEAD> <BODY onload="showElements()"> <H1>Привет!</H1> <P>Этот документ <B>очень</B> короткий. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_01.htm При загрузке этого документа, скрипт (обработчик события onload) отображает список элементов в документе, перебирая коллекцию all. Он отображает следующее сообщение. Этот документ содержит: HTML HEAD TITLE SCRIPT BODY H1 P B В этом сообщении представлен каждый элемент HTML из предыдущего примера. В списке не отображаются закрывающие теги элементов, поскольку каждый объект элемента представляет как открывающий, так и закрывающий теги. Коллекция также не показывает полностью иерархию элементов, т. е. нельзя определить, какие элементы содержат другие элементы. Коллекция перечисляет элементы в том порядке, в котором они появляются в исходном HTML-коде документа. Во многих отношениях коллекция all похожа на массив. Она содержит один или более элементов, все элементы одного типа — в данном случае объекты элементов. К элементам обращаются с помощью значений индекса с нулевым основанием или по имени или идентификатору. Значение индекса первого элемента 0, второго — 1 и т. д. С помощью свойства length можно определить количество элементов в коллекции. Поскольку все элементы в коллекции all являются объектами элементов, к ним можно применять свойства и методы. Например, можно использовать свойство tagName, чтобы получить имя тега HTML элемента, как было сделано в предыдущем примере. Подобным образом можно получить доступ к свойствам и методам соответствующего элемента, обращаясь к нему через коллекцию document.all. Коллекция all всегда представляет текущее состояние документа и автоматически обновляется, чтобы отразить изменения, внесенные в документ. Например, если получить коллекцию и добавить или удалить содержимое документа, которое изменяет структуру HTML, коллекция автоматически отражает новый контент HTML в последовательности исходного кода. В некоторых случаях коллекция all может содержать больше элементов, чем фактически имеется в файле документа. В частности, коллекция всегда содержит элементы html, head, TITLE и BODY, даже если они не присутствуют в исходном коде. Аналогично, коллекция всегда содержит элемент tBody для каждого элемента table, независимо от того, указан ли элемент tBody в исходном HTML-коде. Коллекция all также включает комментарии (!) и неизвестные или недействительные теги. Целью является предоставление пользователю точной картины контента документа. Неизвестные или недействительные теги — это как правило теги с ошибками или расположенные не на своих местах. Знание того, что это за теги и где они расположены, дает возможность заменить их на правильные теги. Коллекция all перечисляет неизвестные и недействительные открывающие и закрывающие теги отдельно; она не пытается объединить их в один элемент. В следующем примере отображается сообщение "HTML HEAD TITLE SCRIPT BODY ! P ZZZ> /ZZZ> /B". <HTML> <HEAD><TITLE>Элементы: Сбор</TITLE> <SCRIPT LANGUAGE="JScript"> function showElements() { var tag_names = ""; for (i=0; i<document.all.length; i++) tag_names = tag_names + document.all(i).tagName + " "; alert("Этот документ содержит: " + tag_names); } </SCRIPT> </HEAD> <BODY onload="showElements()"> <!-- Комментарий --> <P>В этом документе имеются <ZZZ>неизвестный</ZZZ> и недействительный</B> теги. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_02.htm Помимо коллекции all в объекте document, каждый отдельный элемент также предоставляет коллекцию all. Вспомните иерархический стиль HTML — это поможет понять принцип коллекции all для каждого элемента. Коллекция all для элемента содержит все элементы, которые содержатся в данном элементе. Например, коллекция all для элемента HTMLбудет содержать весь исходный код, за исключением самого элемента HTML (это будет единственным отличием между коллекцией all для элемента HTML и коллекцией document.all). Каждый элемент также предоставляет коллекцию children, которая содержит только элементы, являющиеся прямыми потомками в иерархии HTML. Говоря иначе, коллекция children содержит только те элементы, свойство parentElement которых возвращает данный элемент. Для перекрывающихся элементов содержимое коллекции children не определено. В следующем примере возвращается длина и содержимое коллекций документа all и children. Следует отметить, что у тега html существует только два дочерних элемента — head и BODY. Элементы TITLE и script являются дочерними элементами тега head, а не тега html. <HTML id=theHTML> <HEAD> <TITLE> Взгляд на коллекции all и children</TITLE> <SCRIPT> function showme() { alert('all: ' + window.theHTML.all.length); for (i=0; i < theHTML.all.length;i++) { alert(theHTML.all[i].tagName); } alert('children: ' + window.theHTML.children.length); for (i=0; i < theHTML.children.length;i++) { alert(theHTML.children[i].tagName); } } </SCRIPT> </HEAD> <BODY onload=showme()> <DIV> Текст в элементе DIV. Этот элемент DIV будет в коллекции all элемента HTML.</DIV> </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_03.htm Использование коллекций Объектная модель DHTML предоставляет несколько коллекций, которые можно использовать для доступа к элементам документа. Коллекции в объектной модели DHTML похожи на массив переменных, созданный на языке программирования. Элемент можно извлечь из коллекции по его имени или идентификатору, либо по порядковому индексу, который указывает позицию элемента в коллекции. Индексы коллекций имеют нулевое основание, поэтому первый элемент всегда имеет нулевой индекс. В следующем примере Microsoft JScript отображается имя тега элемента p, шестого элемента в коллекции. <HTML> <HEAD><TITLE>Элементы: Извлечение элементов</TITLE> <SCRIPT LANGUAGE="JScript"> function showSixth() { var el = document.all(5); alert("Шестой элемент: " + el.tagName); } </SCRIPT> </HEAD> <BODY onload="showSixth()"> <P>Это очень простой документ. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_04.htm Поскольку значения индексов коллекций имеют нулевое основание, индекс последнего элемента в коллекции всегда на единицу меньше, чем длина коллекции. Поэтому можно быстро получить доступ к последнему элементу коллекции, если вычесть единицу из ее длины и использовать результат в качестве значения индекса, как показано в следующем примере. var elLast = document.all(document.all.length-1); alert("Последний элемент в этом документе: " + elLast.tagName); Также можно извлекать элементы из коллекции, указывая идентификатор. В этом случае элемент должен иметь допустимый идентификатор, заданный в атрибуте ID. В следующем примере JScript отображается имя тега элемента с идентификатором MyID. <HTML> <HEAD><TITLE>Элементы: Идентификаторы в качестве индексов</TITLE> <SCRIPT LANGUAGE="JScript"> function showElementWithID() { var el = document.all("MyID"); alert("Элемент с идентификатором MyID: " + el.tagName); } </SCRIPT> </HEAD> <BODY onload="showElementWithID()"> <P ID="MyID">Это очень простой документ. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_05.htm К элементам также можно обращаться по имени, но важно помнить, что атрибут name в основном применяется только к элементам, участвующим в отправке форм. Атрибут ID — это идентификатор, который применяется ко всем элементам. Будьте внимательны! Хотя в теории ID означает "уникальный идентификатор", в реальности уникальность не применяется. Если несколько элементов имеют одинаковый идентификатор, результатом будет коллекция элементов с одним идентификатором, а не отдельные элементы. К элементам результирующей коллекции можно получить доступ только по порядку. Если ни один элемент не имеет идентификатора, результатом будет null. Если использование идентификатора приводит к созданию другой коллекции, ее элементы будут иметь такой же порядок, какой они имеют в документе. Чтобы получить доступ к этим элементам, можно использовать метод item для применения индекса с нулевым основанием к коллекции, как показано в следующем примере. if (document.all("MyID").length != null) alert("Первый элемент с идентификатором MyID: " + document.all("MyID").item(0).tagName); Если заранее известно, что один и тот же идентификатор имеют несколько элементов, можно пропустить один шаг и использовать необязательный второй параметр метода item, чтобы извлечь элемент, не извлекая сначала коллекцию. В следующем примере JScript отображается то же сообщение, что и в предыдущем примере. var el = document.all.item("MyID",0); if (el != null) alert("Первый элемент с идентификатором MyID: " + el.tagName); При использовании языков скриптов, таких как JScript и Microsoft Visual Basic Scripting Edition (VBScript), к элементам в коллекциях также можно обращаться с помощью синтаксиса индексирования данного языка. JScript поддерживает три способа индексации массива: целочисленный индекс, заключенный в квадратные скобки, идентификатор, заданный как заключенная в квадратные скобки строка, и идентификатор, перед которым стоит точка. В следующих инструкциях JScript показано, как они применяются. var el = document.all[2]; // то же, что и document.all.item(2) var el = document.all["MyID"]; // то же, что и document.all.item("MyID") var el = document.all.MyID; // то же, что и document.all.item("MyID") И опять, будьте осторожны при использовании идентификаторов таким способом, поскольку коллекция возвращает другую коллекцию, если несколько элементов имеют данный идентификатор. Всегда проверяйте возвращенное значение перед его использованием. Нельзя использовать идентификаторы для обращения к элементам коллекции imports — эта коллекция состоит из импортированных таблиц стилей, а не из элементов HTML, поэтому идентификаторы недоступны. Вместо этого используйте целочисленные индексы. Хотя для доступа к элементам коллекции frames можно использовать имена, убедитесь, что имена окон уникальны. В противном случае будет доступно только первое окно с заданным именем. Создание новых коллекций: Метод tags Метод tags создает коллекцию элементов, имеющих заданное имя тега. Этот метод фильтрует существующую коллекцию и создает новую коллекцию заданного имени тега. Например, в следующем коде JScript метод tags применяется к коллекции all для получения новой коллекции, содержащей только элементы table в документе. Затем к каждой таблице применяется граница. var doc_tables = document.all.tags("TABLE"); for (i=0; i<doc_tables.length; i++) doc_tables(i).border = 1; Метод tags ищет любые имена тегов, даже недействительные с точки зрения HTML. Если он находит один или несколько элементов с данным именем, то возвращает коллекцию. Если он не может найти элемент с данным именем, то возвращает пустую коллекцию. Свойство length используется для определения количества элементов в коллекции. Коллекция является пустой, если ее длина равна нулю. Метод tags сохраняет порядок элементов при создании новой коллекции. Это значит, что первый элемент в новой коллекции также является первым экземпляром тега в документе. Поскольку возвращаемая методом tags коллекция является подмножеством коллекции all, порядковое значение, используемое для обращения к элементу этой коллекции, отличается от порядкового значения, используемого для обращения к этому же элементу коллекции all. Иногда полезно знать оба порядковых значения. Свойство sourceIndex для элемента возвращает порядковую позицию элемента в коллекции документа all. Обращение к свойствам элемента Многие свойства элемента — это пары имя-значение, соответствующие HTML-атрибутам элемента и другим значениям, связанным с элементом. Можно получить значение свойства, чтобы определить, как задан соответствующий атрибут, и во многих случаях — изменить значение этого свойства, чтобы динамически воздействовать на элемент. Это ключевая концепция, на которой основано управление динамическими стилями и динамическим контентом. Обращение к свойствам, которые позволяют изменять стили и контент, выполняется посредством обращения к объекту элемента через коллекции, предоставленные в объектной модели DHTML. Например, можно выровнять по центру элемент H1, обратившись к элементу H1 через коллекцию all в документе, а затем задав его свойству align значение "center"; то же значение будет использоваться с атрибутом ALIGN. var coll = document.all.tags("H1"); if (coll.length>0) coll(0).align="center"; Таким же образом можно изменить имя файла изображения для элемента img, задав его свойство src. var coll = document.all.tags("IMG"); if (coll.length>0) coll(0).src="newimage.gif"; Большинство свойств имеют такое же имя и принимают такие же значения, как и соответствующий атрибут. Это значит, что большинство свойств принимают строки, перечисляемые значения или числовые значения. Если имя свойства и отличается от соответствующего ему атрибута, оно обычно довольно близко к нему. Например, свойство className соответствует атрибуту CLASS. Имена изменены для избежания конфликтов с ключевыми словами в распространенных языках скриптов или чтобы гарантировать, что имена свойств не содержат недопустимых в этих языках символов. Несколько свойств представляют вложенные объекты. Например, объект style соответствует атрибуту STYLE и представляет вложенный объект, предоставляющий доступ ко всем атрибутам каскадных таблиц стилей (CSS), которые можно применить к элементу в качестве встроенного стиля. Объект style сам принимает свойства, которые можно задать, чтобы изменить внешний вид и форматирование элемента. В следующем примере объект style используется для изменения атрибута цвета CSS всех элементов H1 на зеленый. var coll = document.all.tags("H1"); for (i=0; i<coll.length; i++) coll[i].style.color = "green"; Некоторые свойства не соответствуют атрибутам элемента. Эти свойства обычно предоставляют дополнительные сведения об элементе, которые недоступны через атрибуты. Например, свойство tagName задает имя тега HTML элемента, а свойство sourceIndex задает положение элемента в коллекции документа all. Хотя значения многих свойств можно получать и задавать, некоторые свойства доступны только для чтения, т. е. их значения можно получать, но нельзя задавать или изменять. Например, свойство tagName доступно только для чтения — изменение имени тега элемента не допускается. Иногда в документе HTML присутствуют недействительные атрибуты или атрибутам присваиваются недопустимые значения. Если атрибуту присвоено недопустимое значение, для соответствующего свойства всегда задается значение по умолчанию. В следующем примере "middle" является недопустимым значением для атрибута ALIGN, поэтому документ отображает сообщение "слева", что является значением по умолчанию для свойства align. <HTML> <HEAD><TITLE>Элементы: Использование свойств</TITLE> <SCRIPT LANGUAGE="JScript"> function showAlignment() { var coll = document.all.tags("H1"); if (coll.length>0) alert("Выравнивание для первого заголовка " + coll(0).align); } </SCRIPT> </HEAD> <BODY onload="showAlignment()"> <H1 ALIGN="center">Привет!</H1> <P>Этот документ <B>очень</B> короткий. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_06.htm Методы getAttribute, setAttribute и removeAttribute предоставляют доступ к атрибутам элемента без использования свойств. В эти методы передается имя атрибута и каждый из них выполняет со значением этого атрибута соответствующее действие — возвращает, задает или удаляет. Например, можно получить и задать текущее значение атрибута ALIGN (вместо того, чтобы получить свойство align) с помощью методов getAttribute и setAttribute, как показано в следующем примере. Документ отображает текущее значение атрибута ("left"), а затем изменяет это значение на "center", выравнивая элемент H1 по центру. <HTML> <HEAD><TITLE>Элементы: Использование методов</TITLE> <SCRIPT LANGUAGE="JScript"> function showAndSetAlignment() { alert(MyHeading.getAttribute("align")); MyHeading.setAttribute("align","center"); } </SCRIPT> </HEAD> <BODY onload="showAndSetAlignment()"> <H1 ID=MyHeading ALIGN="left">Привет!</H1> <P>Это короткий документ. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_07.htm Методы атрибутов особенно полезны при работе с нераспознанными атрибутами и недопустимыми значениями. Например, если атрибут имеет недопустимое значение, метод getAttribute получит в точности это значение, а не значение атрибута по умолчанию. Это означает, что этот метод можно использовать для исследования реального содержимого документа HTML и принятия решений на этой основе. В следующем примере методы getAttribute и setAttribute используются для исправления выравнивания элемента H1 ("middle" является недопустимым значением). <HTML> <HEAD><TITLE>Элементы: Недопустимые значения</TITLE> <SCRIPT LANGUAGE="JScript"> function checkValues() { if (MyHeading.getAttribute("align")=="middle") MyHeading.setAttribute("align","center"); if (MyHeading.getAttribute("xyz")!="123") MyHeading.setAttribute("xyz","123"); } </SCRIPT> </HEAD> <BODY onload="checkValues()"> <H1 ID=MyHeading XyZ="123" ALIGN="middle">Привет!</H1> <P>Это короткий документ. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_08.htm По умолчанию методы атрибутов getAttribute и setAttribute не различают строчные и прописные буквы при поиске неизвестного атрибута. Поэтому в предыдущем примере, хотя строка "xyz" не идентична строке "XyZ," эти методы получают и задают атрибут в любом случае. Можно заставить эти методы искать точное совпадение, задав для необязательного параметра чувствительности к регистру значение true. Например, если в предыдущий пример поместить следующий код, он отобразит сообщение "Не найден", так как "xyz" не совпадает с "XyZ". if (document.all.MyHeading.getAttribute("xyz", true)==null) alert("Не найден"); Если при использовании этих методов в режиме чувствительности к регистру найдено несколько совпадений, фактически возвращаемый элемент может зависеть от платформы. Исследование иерархии элемента Элементы в документе HTML образуют иерархию, в которой одни элементы содержат другие. Элемент html на вершине иерархии содержит все остальные элементы в документе. Элемент BODY, содержащийся в элементе html, представляет документ. Блочные элементы, такие как p, содержат текст и встроенные элементы, которые сами могут содержать текст и встроенные элементы, и т. д. Эту структурную иерархию можно исследовать с помощью метода contains и свойства parentElement. Коллекции all и children для каждого элемента также могут помочь определить структуру документа. Метод contains возвращает значение trueили false, показывая, содержится ли один элемент в другом. Метод применяется к одному элементу, а другой элемент передается в него в качестве параметра. Например, в следующем примере отображается сообщение "True!", поскольку элемент BODY содержит элемент p. <HTML> <HEAD><TITLE>Элементы: Иерархия</TITLE> <SCRIPT LANGUAGE="JScript"> function showContains() { var el = document.all.tags("P").item(0); if (document.body.contains(el)) alert("True!"); else alert("False!"); } </SCRIPT> </HEAD> <BODY onload="showContains()"> <P>Это очень простой документ. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_09.htm Примечание. В предыдущем примере свойство body объекта document используется для получения объекта body. Свойство parentElement всегда идентифицирует следующий элемент в иерархии, который содержит данный элемент. Метод contains и свойство parentElement можно объединить в более сложный скрипт, чтобы определить иерархию элементов в документе. В следующем примере они используются для определения иерархии, а затем отображается сообщение, показывающее эту иерархию. <HTML> <HEAD><TITLE>Элементы: Иерархия</TITLE> <SCRIPT LANGUAGE="JScript"> function showHierarchy() { var depth = 0; var msg = document.all(0).tagName; for (i=1; i<document.all.length; i++) { if (document.all(i-1).contains(document.all(i))==true) { depth = depth + 1; } else { var elParent = document.all(i-1).parentElement; for ( ; depth>0; depth--) { if (elParent.contains(document.all(i))==true) break; elParent = elParent.parentElement; } } msg = msg + "\n"; for (j=1; j<=depth; j++) msg = msg + " "; msg = msg + document.all(i).tagName; } alert("Этот документ содержит:\n" + msg); } </SCRIPT> </HEAD> <BODY onload="showHierarchy()"> <H1>Привет!</H1> <P>Этот документ <B>очень</B> короткий. </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_10.htm Получение положения и размеров элемента Расположение, ширину и высоту элемента можно определить с помощью свойств offsetLeft, offsetTop, offsetHeight и offsetWidth. Эти числовые свойства задают физические координаты и размеры элемента относительно смещения его offsetParent. Ниже представлен пример простых часов, размер показаний которых подгоняется под текущую ширину и высоту основного текста документа. <HTML> <HEAD><TITLE>Простые часы</TITLE> <SCRIPT LANGUAGE="JScript"> function startClock() { window.setInterval("Clock_Tick()", 1000); Clock_Tick(); } var ratio = 4; function Clock_Tick() { var s = Date(); var t = s.substring(11,19); var doc_height = document.body.offsetHeight; var doc_width = document.body.offsetWidth; if ((doc_height*ratio)>doc_width) doc_height = doc_width / ratio; MyTime.innerText = t; MyTime.style.fontSize = doc_height; } </SCRIPT> </HEAD> <BODY onload="startClock()"> <P ID="MyTime"> </P> </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_11.htm Значения свойств offsetLeft и offsetTop задаются относительно элемента, заданного свойством offsetParent для элемента. Чаще всего это свойство возвращает body. В следующем примере, хотя элемент td и появляется в документе далеко справа, его позиция (0,0), так как его offsetParent — это элемент tr, а не основной текст документа. <HTML> <HEAD><TITLE>Элементы: Положения</TITLE> <SCRIPT LANGUAGE="JScript"> function showPosition() { var el = MyID; alert("Элемент TD в позиции (" + el.offsetLeft + "," + el.offsetTop + ")\n" + "offsetParent — это " + el.offsetParent.tagName ); } </SCRIPT> </HEAD> <BODY onload="showPosition()"> <P>Этот документ содержит таблицу, выровненную по правому краю. <TABLE BORDER=1 ALIGN=right> <TR><TD ID=MyID>Это маленькая таблица. </TABLE> </BODY> </HTML> Пример кода: http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/overview/elem_12.htm Прокрутка элементов в представлении Еще одним полезным методом является scrollIntoView. Этот метод прокручивает элемент в представлении в пределах окна, помещая его либо наверх, либо вниз окна. Этот метод полезен для моментального показа пользователю результата какого-то действия, чтобы пользователю не нужно было вручную прокручивать документ в поисках результата. В следующем примере содержимое пятого параграфа подчеркивается и прокручивается наверх окна. var coll = document.all.tags("P"); if (coll.length>=5) { coll(4).style.textDecoration = "underline"; coll(4).scrollIntoView(true); } |