Главная страница   /   7.3. Использование скриптовых элементов (Руководство по HTML5

Руководство по HTML5

Руководство по HTML5

Адам Фриман

7.3. Использование скриптовых элементов

Есть два скриптовых элемента. Первый, script, позволяет определять скрипты и контролировать их выполнение. Второй, noscript, позволяет определить, что произойдет, если браузер не поддерживает скрипты или они отключены.

Совет

Вы обычно используете элемент script внутри элемента head, но вы можете использовать его в любом месте HTML документа. Я рекомендую размещать все ваши элементы script вместе в части head документа, поскольку в таком случае их легче отслеживать и потому что большинство людей ожидают, чтобы найдут определения скриптов именно там.

Элемент script

Элемент script позволяет включать скрипты в ваши страницы: эти скрипты могут быть либо определены внутри документа или находиться во внешних файлах. Наиболее часто используемый тип скриптов – это скрипты JavaScript; и этому типу я уделю основное внимание, но браузеры поддерживают и другие скриптовые языки, в том числе те, что остались от браузерных войн, которые я описал в главе 1. В таблице 7-17 описан элемент script. Вы можете использовать один элемент script для каждого скрипта, который необходимо определить или импортировать.

Таблица 7-17: Элемент script
Элемент script
Тип элемента Метаданные/фразовый
Разрешенные родительские элементы Любой элемент, который может содержать метаданные или фразовые элементы
Локальные атрибуты type, src, defer, async, charset
Содержание Выражения скриптового языка или пусто, если указана внешняя библиотека JavaScript
Стиль тегов Требуются открывающий и закрывающий теги; теги пустых элементов не допускаются даже при подключении внешней библиотеки JavaScript
Новый в HTML5 Нет
Изменения в HTML5 Атрибут type является необязательным в HTML5; были добавлены атрибуты async и defer; атрибут HTML4 language является устаревшим в HTML5
Соглашение по стилям Нет

Тип этого элемента меняется в зависимости от того, где он используется. Элементы script, определенные в элементе head, являются метаданными, но элементы script, определенные в других элементах (таких как body или section) являются фразовыми элементами.

В следующих разделах я покажу вам, как использовать элемент script для достижения различных эффектов. В таблице 7-18 описаны атрибуты, которые определяет элемент script.

Таблица 7-18: Локальные атрибуты элемента script
Атрибут Определение
type Указывается тип скрипта, на который ссылаются или который определен. Этот атрибут может быть опущен для скриптов JavaScript.
src Задает URL-адрес для внешнего скриптового файла. См. следующие примеры.
defer
async
Определяет, как будет выполнен скрипт. См. следующие примеры. Эти атрибуты могут быть использованы только в сочетании с атрибутом src.
charset Задает кодировку внешнего скриптового файла. Этот атрибут может быть использован только в сочетании с атрибутом src.

Определение внутреннего скрипта

Самый простой способ определить скрипт – это сделать это внутри документа. Это обозначает, что вы включаете JavaScript выражения в HTML страницу. В листинге 7-17 представлен пример.

Листинг 7-17: Определение внутреннего скрипта
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script>
		document.write("This is from the script");
	</script>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Если вы не используете атрибут type, браузер будет считать, что вы используете JavaScript. Этот простой скрипт добавляет текст в HTML документ. По умолчанию скрипты выполняются сразу же, как только они встречаются на странице. Вы можете увидеть результат выполнения этого скрипта на рисунке 7-8, где текст из скрипта отображается в окне браузера до элемента р, содержащегося в body.

Рисунок 7-8: Результат выполнения простого скрипта

Загрузка внешней скриптовой библиотеки

Вы можете разделить скрипты по отдельным файлам и загружать их, используя элемент script. Эти файлы могут быть как простыми (как предыдущий пример) или сложными (например, мощные библиотеки, такие как jQuery). Чтобы продемонстрировать внешний скрипт, я создал файл с именем simple.js, содержание которого показано в листинге 7-18.

Листинг 7-18: Содержание скриптового файла simple.js
document.write("This is from the external script");

В этом файле содержится одно выражение, похожее на то, которое я использовал во внутреннем скрипте. В листинге 7-19 показано, как можно использовать атрибут src в элементе script для ссылки на этот файл.

Совет

Элемент script должен быть пустым, если он использует атрибут src. Вы не можете использовать один и тот же элемент script для определения внутреннего и внешнего скриптов.

Листинг 7-19: Загрузка внешнего скрипта с использованием атрибута src
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script src="simple.js"></script>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Значение атрибута src – это URL файла скрипта, который вы хотите загрузить. Я создал файл simple.js в том же каталоге, что и HTML файл, так что я могу использовать в этом примере относительный URL. Вы можете увидеть результат выполнения скрипта на рисунке 7-9.

Рисунок 7-9: Результат выполнения внешнего скрипта

Совет

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

Отсрочка выполнения скрипта

Вы можете в определенной степени управлять выполнением скрипта при помощи атрибутов async и defer. Атрибут defer сообщает браузеру, что он не должен выполнять скрипт, пока страница не загрузится и не обработается. Чтобы понять, какую пользу может принести атрибут defer, можно взглянуть на проблему, которую он решает. В листинге 7-20 показано содержание скриптового файла simple2.js, в котором содержится одно выражение.

Листинг 7-20: Содержание скриптового файла simple2.js
document.getElementById("applecode").innerText = "cherries";

Я разберу различные части этого выражения в части IV данной книги, а сейчас достаточно знать то, что когда этот скрипт запустится, он найдет элемент со значением атрибута id равным applecode и изменит внутренний текст этого элемента на cherries. В листинге 7-21 показан HTML документ, который ссылается на скриптовый файл при помощи элемента script.

Листинг 7-21: Ссылка на скриптовый файл
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script src="simple2.js"></script>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

При загрузке предыдущей HTML страницы, вы не получите желаемого результата, как показано на рисунке 7-10.

Рисунок 7-10: Проблема со временем выполнения скрипта

По умолчанию браузер, когда сталкивается с элементом script, прекращает обработку HTML документа, загружает скриптовый файл и выполняет его содержание. И только после того, как завершится выполнение скрипта, браузер возобновляет обработку HTML. Это обозначает, что браузер загрузит и выполнит выражения из simple2.js, прежде чем обработает остальную часть HTML и обнаружит элемент code. Скрипт не найдет элемент, который он ищет, и поэтому никаких изменений не последует. После того как скрипт завершит свою работу, браузер продолжит разбирать (парсить) HTML и найдет элемент code. Но это уже слишком поздно для скрипта, который не будет выполняться снова. Один из очевидных путей решения этой проблемы – это вставка элемента script в конец документа, как показано в листинге 7-22.

Листинг 7-22: Решаем проблему со временем выполнения скрипта, передвигая элемент script в конец документа
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
	<script src="simple2.js"></script>
</body>
</html>

При этом подходе принимается во внимание то, как браузер реагирует на элемент script, и гарантируется, что скрипт не загрузится и не выполнится пока элементы, в которых заинтересован скрипт, не будут обработаны. Как вы можете видеть на рисунке 7-11, вы получите тот результат, который вы ждете от выполнения скрипта.

Рисунок 7-11: Результат выполнения скрипта, примененный к элементу a

Такой подход является вполне допустимым, но в HTML5 можно добиться того же эффекта при помощи атрибута defer. Когда браузер встречает элемент script, в котором присутствует атрибут defer, он откладывает загрузку и выполнение скрипта, пока не будут обработаны все элементы в HTML документе. В листинге 7-23 показан элемент script, который использует атрибут defer.

Листинг 7-23: Использование элемента script с атрибутом defer
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script defer src="simple2.js"></script>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Загрузка этой страницы в браузер приводит к тому же результату, как и перемещение элемента script в конец страницы. Скрипт может найти элемент code и изменить текстовое содержание, что приводит к тому же результату, что вы видели на рисунке 7-11.

Совет

Вы можете использовать атрибут defer только для внешних скриптовых файлов. Это не будет работать для внутренних скриптов.

Асинхронное выполнение скриптов

Вы можете решить различные проблемы с помощью атрибута async. Как я упоминал ранее, по умолчанию браузер, когда сталкивается с элементом script, прекращает обрабатывать страницу, в то время как он загружает и выполняет скрипт. Каждый элемент script выполняется синхронно (то есть, ничего не происходит, пока скрипт загружается и выполняется) и по очереди (т.е. в том порядке, в котором они определены).

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

При использовании атрибута async браузер загружает и выполняет скрипт асинхронно, в то время как он продолжает обрабатывать другие HTML элементы, в том числе другие элементы script. Если использовать этот атрибут для правильного вида скриптов, вы можете значительно улучшить общую производительность. В листинге 7-24 показано использование атрибута async с элементом script.

Листинг 7-24: Использование атрибута async
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script async src="simple2.js"></script>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Одним важным моментом использования атрибута async является то, что скрипты на странице могут быть выполнены не в том порядке, в котором они определены. Это делает использование атрибута async непригодным для скриптов, которые зависят от функций или переменных, определенных в других скриптах.

Элемент noscript

Элемент noscript позволяет отображать контент для пользователей, которые отключили JavaScript или которые используют браузер, не поддерживающий его. В таблице 7-19 описан элемент noscript.

Таблица 7-19: Элемент noscript
Элемент noscript
Тип элемента Метаданные/фразовый/потоковый
Разрешенные родительские элементы Любой элемент, который может содержать метаданные, фразовые или потоковые элементы
Локальные атрибуты Нет
Содержание Фразовые или потоковые элементы
Стиль тегов Требуются открывающий и закрывающий теги
Новый в HTML5 Нет
Изменения в HTML5 Нет
Соглашение по стилям Нет

Как и с элементом script, тип элемента noscript зависит от того, где он расположен в документе.

Несмотря на то, что в наши дни осуществляется широкая поддержка JavaScript, есть еще некоторые специализированные браузеры, которые не поддерживают его. Даже когда браузер применяет JavaScript, пользователь может отключить его; во многих крупных корпорациях работает правило без-JavaScript для работников компании. Элемент noscript позволяет вам работать с этими пользователями, то есть вы можете отобразить для них содержание, для работы с которым не требуется JavaScript, или, по крайней мере, объяснить, что они не могут использовать ваш сайт или страницу, если не включен JavaScript. В листинге 7-25 показано, как используется элемент noscript для отображения простого сообщения.

Листинг 7-25: Использование элемента noscript
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script defer src="simple2.js"></script>
	<noscript>
		<h1>Javascript is required!</h1>
		<p>You cannot use this page without Javascript</p>
	</noscript>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Вы можете увидеть результат использования элемента noscript на рисунке 7-12. Для достижения этого результата, я отключил поддержку JavaScript в Google Chrome и загрузил HTML из листинга.

Рисунок 7-12: Результат использования элемента noscript

Обратите внимание, что оставшаяся часть страницы обрабатывается как обычно, и содержание элементов по-прежнему отображается.

Совет

Вы можете добавить несколько элементов noscript на страницу, так чтобы они соответствовали отдельным функциональным областям, которые требуют наличия скриптов. Этот подход является наиболее полезным для обеспечения резервной разметки, которая не зависит от JavaScript.

Альтернативный подход состоит в перенаправлении браузера пользователя на другой URL, если он не поддерживает JavaScript. Это можно сделать путем размещения элемента meta внутри элемента noscript, как показано в листинге 7-26.

Листинг 7-26: Использование элемента noscript для перенаправления браузера пользователя
<!DOCTYPE HTML>
<html>
<head>
	<title>Example</title>
	<base href="http://titan/listings/" />
	<meta name="author" content="Adam Freeman" />
	<meta name="description" content="A simple example" />
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
	<script defer src="simple2.js"></script>
	<noscript>
		<meta http-equiv="refresh" content="0; http://www.apress.com" />
	</noscript>
</head>
<body>
	<p>
		I like <code id="applecode">apples</code> and oranges.
	</p>
	<a href="http://apress.com">Visit Apress.com</a>
	<a href="page2.html">Page 2</a>
</body>
</html>

Это позволит перенаправить пользователя на сайт www.apress.com, если браузер, который не поддерживает JavaScript или в котором JavaScript отключен, пытается загрузить эту страницу.