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

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

< Лекция 8 || Лекция 9: 123 || Лекция 10 >
Регулярные выражения

Регулярные выражения являются разновидностью мини-языка-программирования, созданного для решения проблемы "синтаксического анализа" текста - например, ответить на вопросы типа "появляется ли данная строка внутри другой строки?" и "в строке 'abc123def' какие имеются цифры между 'c' и 'd'?" Они являются очень мощным инструментом, но также достаточно сложным. Ниже находится описание, для чего предназначены регулярные выражения; пока, однако, можете принять это на веру, и вернуться к описанию позже.

Используемое в этом примере регулярное выражение имеет вид /#(.*)$/. Каждый символ регулярного выражения создан для представления последовательности символов в некоторой целевой строке, идея состоит в том, чтобы выразить по частям, как составлена целевая строка.

  • / … / - косая черта указывает начало и конец регулярного выражения, также как двойные или одиночные кавычки используются для "строки"
  • # - хэш-символ (#) фактически означает "совпадает с хэш-символом"
  • ( … ) - скобки означают "здесь находится часть строки, которая понадобится позже"
  • .* - означает "любые символы"; на самом деле это точка (.), означающая "один любой символ", за которой следует звездочка (*), означающая "повторить любое количество раз"
  • $ - знак доллара означает "конец строки"

Поэтому наше регулярное выражение описывает "подходящий шаблон" строки, состоящей из "хэша, за которым следуют любые символы". link.href является местом назначения рассматриваемой ссылки (например, #tab1, и так как эта строка подходит под описание "хэш, за которым следуют любые символы"), то "подходящий шаблон" применим к этой строке.

link.href.match(our_regexp), вернет, поэтому, результат true, а не false ; в действительности будет возвращен массив из двух элементов ["#tab1", "tab1"]. Первый является текстом, который соответствует всему регулярному выражению, а второй является текстом, соответствующим символам в кавычках, поэтому скобки здесь и присутствуют - чтобы пометить эту часть строки как "этот фрагмент нас интересует". tab1 является строкой, которая нам требуется, поэтому мы можем извлечь ее из возвращаемого массива (это второй элемент, поэтому его извлекает индекс [1] - массивы начинают нумерацию с нуля.)

Соединение работающего кода со страницей

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

Выполнение кода в ответ на событие делается в большинстве браузеров с помощью функции addEventListener, и с помощью функции attachEvent в Internet Explorer. Здесь мы создаем функцию "оболочку", которая делает правильный выбор, в зависимости от того, что поддерживается:

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 );
  }
}

(Не беспокойтесь слишком много о том, как это работает; примите пока просто на веру - вы поймете код лучше, когда станете более опытным пользователем JavaScript.) Эта функция получает три параметра, obj, type, и fn, которые являются соответственно "объектом, порождающим событие ", "интересующим нас событием ", и "функцией, которая выполняется при возникновении события ". При загрузке страницы необходимо выполнить нашу функцию tabify.init ; функция tabify.init затем позаботится о присоединении события click для каждой вкладки.

addEvent(window, "load", tabify.init);

Как можно видеть из структуры кода HTML выше, множество вкладок в действительности представляется как упорядоченный список с class="tablinks". Поэтому функция tabify.init должна сделать следующее:

  1. Найти все элементы <ol> на странице с классом tablinks
  2. Соединить с событием click каждого элемента <ol> некоторый код, который делает следующее:
    1. Точно определяет, на какой ссылке вкладки щелкнул пользователь
    2. Определяет, какая реальная вкладка соответствует этой ссылке вкладки
    3. Показывает эту одну вкладку
    4. Скрывает все остальные вкладки

Функция init, которая все это делает, выглядит следующим образом:

init: function() {
  var ols = document.getElementsByTagName("ol");
  for (var i=0; i<ols.length; i++) {
    var ol = ols[i];
    if (!/(^|\s)tablinks(\s|$)/.test(ol.className)) { continue; }
    tabify.addEvent(ol, "click", function(e) {
      var target = window.event ? window.event.srcElement : e.target;
      if (target.nodeName.toLowerCase() === "a") {
        tabify.hideAllTabs(e.target.parentNode.parentNode);
        tabify.setTabFromLink(e.target, "block");
        if (e) e.preventDefault();
        if (window.event) window.event.returnValue = false;
        return false;
      }
    }, true);
    tabify.hideAllTabs(ol);
    tabify.setTabFromLink(ol.getElementsByTagName("a")[0], "block");
  }
}

Давайте пройдем по этой функции шаг за шагом, просматривая по очереди, что делает каждая часть:

var ols = document.getElementsByTagName("ol");
  for (var i=0; i<ols.length; i++) {
    var ol = ols[i];
    if (!/(^|\s)tablinks(\s|$)/.test(ol.className)) { continue; }
  }

Этот фрагмент находит все элементы <ol> на странице с классом tablinks - и затем извлекает список всех <ol> и для каждого проверяет "если этот элемент не имеет класс 'tablinks', пропустить его". (Проверка класса делается с помощью регулярного выражения; continue означает "пропустить этот элемент и перейти к следующему".)

tabify.addEvent(ol, "click", function(e) {
  ...
});

Этот фрагмент присоединяет некоторый код к событию click каждого <ol>.

var target = window.event ? window.event.srcElement : e.target;

Этот фрагмент точно определяет, на какой ссылке вкладки щелкнул пользователь …

tabify.setTabFromLink(e.target, "block");

…затем этот фрагмент, показывает эту единственную вкладку …

tabify.hideAllTabs(e.target.parentNode.parentNode);

… и наконец, эта строка скрывает все другие вкладки.

Функции setTabFromLink и hideAllTabs также присутствуют в коде; они используют показанные выше методы для скрытия или отображения вкладки. Посмотрите на то, как они работают - они являются отдельными функциями, так как часто полезно иметь блок кода, который вызывается более чем из одного места, и поместить его в отдельную функцию. (Это облегчает понимание кода и позволяет повторно использовать его в нескольких местах. Этот подход часто называют "разбиением" или "факторизацией" кода в функцию.)

В ней выполняется также небольшая "дополнительная" работа, которая демонстрирует добавление и удаление атрибутов. Функция setTabFromLink не только отображает соответствующую вкладку, но задает также class="active" на активной вкладке. Она делает это с помощью трех вспомогательных функций: hasClass, removeClass, и addClass. Таким же образом, как мы скрыли все вкладки, а затем показали активную, мы используем removeClass для удаления "active" из className всех ссылок на вкладки, а затем addClass, чтобы добавить "active" в одну ссылку на вкладку, которая действительно активна. Простое добавление класса в ссылку может показаться бессмысленным - в конечном счете классы невидимы - но это зацепка для стилевого оформления. Мы можем (и должны) делать так, чтобы ссылки с class="active" появлялись с другим оформлением, добавляя код CSS:

ol.tablinks li a {
  background-color: red;
}

ol.tablinks li a.active {
  background-color: white;
}

Поэтому теперь "активная" вкладка выводится белой, в то время как другие вкладки будут красными. Использование JavaScript для добавления и удаления классов является очень распространенной техникой, которую вы должны использовать, где возможно; CSS хорошо подходит для управления компоновкой, расположением и внешним видом элементов HTML, и поэтому использование JavaScript для изменения классов этих элементов означает, что они могут приобретать различные стили CSS. Это будет идеальным объединением; JavaScript делает элементы динамическими, но фактически сам изменяет очень немного. Добавьте просто класс и предоставьте CSS возможность выполнить остальную работу.

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

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

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

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

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

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