Опубликован: 01.07.2011 | Доступ: свободный | Студентов: 6431 / 1052 | Оценка: 4.07 / 3.64 | Длительность: 10:34:00
Лекция 9:

Создание и изменение HTML

< Лекция 8 || Лекция 9: 123 || Лекция 10 >

Создание HTML

Однако сценарии для DOM значительно более мощный инструмент, чем просто средство для изменения свойств CSS существующего HTML. Можно также динамически создавать новый код HTML, который никогда не присутствовал на странице с самого начала. Например, на сайте новостей технологии Slashdot, ссылка в комментариях выводит место назначения ссылки в квадратных скобках, поэтому ссылка вида <a href="http://opera.com"> A web browser </a> будет выводиться как <a href="http://opera.com">A web browser</a> [opera.com]. (Это было сделано, чтобы исключить использование фальшивых ссылок, направляющих пользователя в нежелательное место.) Добавление этого небольшого кода HTML, выводящего домен места назначения каждой ссылки на странице, легко делается с помощью JavaScript.

Создание новых элементов HTML делается с помощью функции document.createElement. Для этого примера нужно добавить только одну вещь: после каждой ссылки мы добавляем span, содержащий текст, указывающий домен ссылки (посмотрите страницу linkify.html (http://dev.opera.com/articles/view/creating-and-modifying-html/linkify.html) содержащую действующий пример). Код HTML примера выглядит следующим образом:

<p id="start">This is some text that has 
<a href="http://www.w3.org/TR/html4/struct/links.html">links</a> in it
to various places, including <a href="http://www.opera.com">Opera</a>,
<a href="http://www.bbc.co.uk/">the BBC</a> and an internal link to
<a href="#start">the beginning of this section</a>. All the external links
should have <span>[domain]</span> after them.</p>

Код JavaScript выглядит следующим образом:

<script type="text/javascript">
var linksuffix = {
  addEvent: function(obj, type, fn) {
    if ( obj.attachEvent ) {
      obj['e'+type+fn] = fn;
      obj[type+fn] = function(){obj['e'+type+fn]( window.event );};
      obj.attachEvent('on'+type, obj[type+fn] );
    } else {
      obj.addEventListener( type, fn, false );
    }
  },  
  init: function() {
    var links = document.getElementById("linksuffixtext").getElementsByTagName("a");
    for (var i=0; i<links.length; i++) {
      var matches = links[i].href.match(/^http:\/\/(.*?)\//);
      if (matches) {
        var linkdomain = matches[1];
        var span = document.createElement("span");
        var spantext = document.createTextNode(" ["+linkdomain+"]");
        span.appendChild(spantext);
        links[i].parentNode.insertBefore(span, links[i].nextSibling);
      }
    }
  }
};
linksuffix.addEvent(window, "load", linksuffix.init);
</script>

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

var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
  var matches = links[i].href.match(/^http:\/\/(.*?)\//);
  if (matches) {
    var linkdomain = matches[1];
    var span = document.createElement("span");
    var spantext = document.createTextNode(" ["+linkdomain+"]");
    span.appendChild(spantext);
    links[i].parentNode.insertBefore(span, links[i].nextSibling);
  }
}

Этот код разбивается следующим образом:

var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
  ...
}

Сначала он находит все ссылки ( getElementsByTagName("a") ) в документе

var matches = links[i].href.match(/^http:\/\/(.*?)\//);
if (matches) {
  ...
}

Эта строка использует регулярное выражение на каждой ссылке, чтобы определить, что место назначение начинается с http://что-то/. Если это так …

var linkdomain = matches[1];
var span = document.createElement("span");
var spantext = document.createTextNode(" ["+linkdomain+"]");
span.appendChild(spantext);

… следующая часть сначала получает "домен ссылки", часть www.opera.com ссылки. Затем с помощью document.createElement создается элемент <span>. Затем создается "textNode" ("текстовыйУзел"). В то время как сами элементы HTML создаются с помощью document.createElement, весь текст в документе HTML фактически содержится в "textNode", и их необходимо создать отдельно. Нет необходимости беспокоиться об этом (или даже знать об этом) при написании реального HTML, но нужно знать об этом при создании элементов с помощью сценария DOM. Текст в textNode является фактически " [домен]", созданный конкатенацией (соединением вместе) строк. Наконец, эта часть использует метод appendChild элемента <span>, чтобы поместить textNode внутрь span.

links[i].parentNode.insertBefore(span, links[i].nextSibling);

Эта строка добавляет span в документ. В этом месте span является ссылкой на элемент HTML, который выглядит следующим образом:

<span> [example.com]</span>

Этот элемент, однако, не является частью документа. Он не является пока частью никакого документа, он просто находится в некоторой неопределенности. Добавление элемента в документ можно сделать одним из двух способов: используя appendChild как выше, или используя insertBefore. Функция appendChild добавляет наш элемент в конце существующего элемента (именно поэтому она называет append ). Так как мы хотим добавить ее в середине существующего элемента, нам нужно использовать insertBefore. Вспомните, что наш текущий фрагмент кода HTML выглядит примерно следующим образом:

<p>... text that has 
<a href="http://www.w3.org/TR/html4/struct/links.html">links</a> in it
to ...

Это приводит к дереву DOM, показанному на рисунке 9.1:

Дерево DOM tree перед добавлением элемента span после ссылки

Рис. 9.1. Дерево DOM tree перед добавлением элемента span после ссылки

Мы хотим вставить новый span между <a> и textNode "in it to", чтобы он появлялся после <a>. Это приведет к дереву DOM как на рисунке 9.2.

Дерево DOM после добавления элемента span

увеличить изображение
Рис. 9.2. Дерево DOM после добавления элемента span

или, более просто, коду HTML следующего вида

<p>... text which has 
<a href="http://www.w3.org/TR/html4/struct/links.html">links</a>
<span> [domain]</span> in it to ...

Здесь было бы удобно иметь возможность сказать: "вставьте новый span после ссылки". К сожалению функции insertAfter нет. Вместо этого мы должны вставлять его перед элементом после ссылки (несколько запутано, но подумайте об этом, и все встанет на место). Краткая запись для выражения "вещь после элемента помеченного el " будет el.nextSibling. Функция insertBefore должна вызываться на элементе, в который происходит вставка, т.е. на предке <p> ссылки, легко доступной с помощью link.parentNode. Поэтому весь вызов, как выше, будет

links[i].parentNode.insertBefore(span, links[i].nextSibling);

То есть, находим предка ( <p> ) ссылки, которая обрабатывается ( links[i] ) в данный момент, и вставляем созданный элемент span перед элементом после ссылки ( links[i].nextSibling ). Использование HTML в виде дерева DOM таким образом и вставка новых элементов в него, может вначале вызывать непонимание, но скоро все становится понятным при достаточной практике.

Заключение

HTML предоставляет структуру страниц, а CSS предоставляет описание внешнего вида. А JavaScript приносит гибкость; структура HTML и стили CSS становятся динамическими.

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

Контрольные вопросы

  • Как задать свойство display CSS элемента, чтобы скрыть элемент?
  • В чем разница между элементом и текстовым узлом?
  • Укажите две причины, почему важно постепенное улучшение.
  • В чем разница между appendChild и insertBefore?
  • Почему мы используем функцию addClass, а не просто соединяем имя нового класса с атрибутом className существующего элемента?
  • В следующей структуре HTML что такое будет document.getElementById("marker").nextSibling?
<p>This is a <strong>block of HTML with 
  <span id="marker">various markup</span> in it</strong>.</p>

Об авторе


Стюарт Лэнгридж вполне возможно единственный человек в мире, который имеет степень бакалавра по программированию и философии. Когда он не занят с компьютерами, он программист на JavaScript, Django, и Python в компании Canonical (http://www.canonical.com/), автор книги DHTML Utopia (http://www.sitepoint.com/books/dhtml1/) издательства SitePoint, или пьет приличное пиво. Он также составляет одну четвертую команды LugRadio (http://lugradio.org/presenters/), первого в мире радио-шоу, посвященного Free and Open Source Software. Результаты его разносторонних интересов в web, программировании сценариев, создании программного обеспечения с открытым кодом, и всего остального, что проплывает за окном, можно найти по адресу kryogenix.org (http://kryogenix.org/); Стюарта можно встретить на улице в поисках места для курения.

< Лекция 8 || Лекция 9: 123 || Лекция 10 >
Александр Мельников
Александр Мельников

В лекции №7 результат работы ни одного скрипта кроме первого не выводит результат на странице браузера, ни одного. Почему. Автор, разъясните пожалуйста. Сокурсники, можете помочь понять?

Юлия Максимова
Юлия Максимова

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

Это задание после первой лекции,  в чем его выполнить, чтобы увидеть результат или как?

Наталья Алмаева
Наталья Алмаева
Россия
Роман Паранин
Роман Паранин
Россия, Ярославль