Умное Кеширование и Версионность в Javascript/CSS

Подключая внешние CSS и Javascript, мы хотим снизить до минимума лишние HTTP-запросы.

Для этого .js и .css файлы отдаются с заголовками, обеспечивающими надежное кеширование.

Но что делать, когда какой-то из этих файлов меняется в процессе разработки? У всех пользователей в кеше старый вариант — пока кеш не устарел, придет масса жалоб на сломанную интеграцию серверной и клиентской части.

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

Простое кеширование ETag

Самый простой способ кеширования статических ресурсов — использование ETag.

Достаточно включить соответствующую настройку сервера (для Apache включена по умолчанию) — и к каждому файлу в заголовках будет даваться ETag — хеш, который зависит от времени обновления, размера файла и (на inode-based файловых системах) inode.

Браузер кеширует такой файл и при последующих запросах указывет заголовок If-None-Match с ETag кешированного документа. Получив такой заголовок, сервер может ответить кодом 304 — и тогда документ будет взят из кеша.

Выглядит это так:

Первый запрос к серверу (кеш чистый)

GET /misc/pack.js HTTP/1.1
Host: javascript.ru

Вообще, браузер обычно добавляет еще пачку заголовоков типа User-Agent, Accept и т.п. Для краткости они порезаны.

Ответ сервераСервер посылает в ответ документ c кодом 200 и ETag:

HTTP/1.x 200 OK
Content-Encoding: gzip
Content-Type: text/javascript; charset=utf-8
Etag: "3272221997"
Accept-Ranges: bytes
Content-Length: 23321
Date: Fri, 02 May 2008 17:22:46 GMT
Server: lighttpd

Следующий запрос браузера
При следующем запросе браузер добавляет If-None-Match: (кешированный ETag):

GET /misc/pack.js HTTP/1.1
Host: javascript.ru
If-None-Match: "453700005"

Ответ сервера
Сервер смотрит — ага, документ не изменился. Значит можно выдать код 304 и не посылать документ заново.

HTTP/1.x 304 Not Modified
Content-Encoding: gzip
Etag: "453700005"
Content-Type: text/javascript; charset=utf-8
Accept-Ranges: bytes
Date: Tue, 15 Apr 2008 10:17:11 GMT

Альтернативный вариант — если документ изменился, тогда сервер просто посылает 200 с новым ETag.

Аналогичным образом работает связка Last-Modified + If-Modified-Since:

1. сервер посылает дату последней модификации в заголовке Last-Modified (вместо ETag)
2. браузер посылает дату закешированной версии в заголовке If-Modified-Since(вместо If-None-Match)
3. Если скрипт не изменился — ответ содержит только код 304

Эти способы работают стабильно и хорошо, но браузеру в любом случае приходится делать по запросу для каждого скрипта или стиля.

Умное кеширование. Версионность

Общий подход для версионности — в двух словах:

1. Во все скрипты добавляется версия (или дата модификации). Например, http://javascript.ru/my.js превратится в http://javascript.ru/my.v1.2.js
2. Все скрипты жестко кешируются браузером
3. При обновлении скрипта версия меняется на новую: http://javascript.ru/my.v2.0.js
4. Адрес изменился, поэтому браузер запросит и закеширует файл заново
5. Старая версия 1.2 постепенно выпадет из кеша

Дальше мы разберем, как сделать этот процесс автоматическим и прозрачным.

Жесткое кеширование

Жесткое кеширование — своего рода кувалда которая полностью прибивает запросы к серверу для кешированных документов.

Для этого достаточно добавить заголовки Expires и Cache-Control: max-age.

Например, чтобы закешировать на 365 дней в PHP:

header("Expires: ".gmdate("D, d M Y H:i:s", time()+86400*365)." GMT");
header("Cache-Control: max-age="+86400*365);

Или можно закешировать контент надолго, используя mod_header в Apache:

Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT"
Header add "Cache-Control" "max-age=315360000"

Получив такие заголовки, браузер жестко закеширует документ надолго. Все дальнейшие обращения к документу будут напрямую обслуживаться из кеша браузера, без обращения к серверу.

Большинство браузеров (Opera, Internet Explorer 6+, Safari) НЕ кешируют документы, если в адресе есть вопросительный знак, т.к считают их динамическими. Именно поэтому мы добавляем версию в имя файла. Конечно, с такими адресами приходится использовать решение типа mod_rewrite, мы это рассмотрим дальше в статье.P.S А вот Firefox кеширует адреса с вопросительными знаками.

Автоматическое преобразование имен

Разберем, как автоматически и прозрачно менять версии, не переименовывая при этом сам файлы.

Имя с версией -> Файл

Самое простое — это превратить имя с версией в оригинальное имя файла.

На уровне Apache это можно сделать mod_rewrite:

RewriteEngine on
RewriteRule ^/(.*\.)v[0-9.]+\.(css|js|gif|png|jpg)$    /$1$2    [L]

Такое правило обрабатывает все css/js/gif/png/jpg-файлы, вырезая из имени версию.

Например:

/images/logo.v2.gif -> /images/logo.gif
/css/style.v1.27.css -> /css/style.css
/javascript/script.v6.js -> /javascript/script.js

Но кроме вырезания версии — надо еще добавлять заголовки жесткого кеширования к файлам. Для этого используются директивы mod_header:

Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT"
Header add "Cache-Control" "max-age=315360000"

А все вместе реализует вот такой апачевый конфиг:

RewriteEngine on
# убирает версию, и заодно ставит переменную что файл версионный
RewriteRule ^/(.*\.)v[0-9.]+\.(css|js|gif|png|jpg)$ /$1$2 [L,E=VERSIONED_FILE:1]
 
# жестко кешируем версионные файлы
Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE
Header add "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

Из-за порядка работы модуля mod_rewrite, RewriteRule нужно поставить в основной конфигурационный файл httpd.conf или в подключаемые к нему(include) файлы, но ни в коем случае не в .htaccess, иначе команды Header будут запущены первыми, до того, как установлена переменная VERSIONED_FILE. Директивы Header могут быть где угодно, даже в .htaccess — без разницы.

Автоматическое добавление версии в имя файла на HTML-странице

Как ставить версию в имя скрипта — зависит от Вашей шаблонной системы и, вообще, способа добавлять скрипты (стили и т.п.).

Например, при использовании даты модификации в качестве версии и шаблонизатора Smarty — ссылки можно ставить так:

<link href="{version src='/css/group.css'}" rel="stylesheet" type="text/css" />

Функция version добавляет версию:

function smarty_version($args){
 
  $stat = stat($GLOBALS['config']['site_root'].$args['src']);
  $version = $stat['mtime'];
 
  echo preg_replace('!\.([a-z]+?)$!', ".v$version.\$1", $args['src']);
}

Результат на странице:

<link href="/css/group.v1234567890.css" rel="stylesheet" type="text/css" />

Отпимизация

Чтобы избежать лишних вызовов stat, можно хранить массив со списком текущих версий в отдельной переменной

$versions['css'] = array(
  'group.css' => '1.1',
  'other.css' => '3.0',
}

В этом случае в HTML просто подставляется текущая версия из массива.

Можно скрестить оба подхода, и выдавать во время разработки версию по дате модификации — для актуальности, а в продакшн — версию из массива, для производительности.

Применимость

Такой способ кеширования работает везде, включая Javascript, CSS, изображения, flash-ролики и т.п.

Он полезен всегда, когда документ изменяется, но в браузере всегда должна быть текущая актуальная версия.

Регулярные выражения в JavaScript

Если вам нужно использовать регулярные выражения при создании сайта, вовсе не обязательно прибегать к использованию Perl или PHP, — JavaScript вполне может справится с этой работой. В этой статье мы рассмотрим объект RegExp в JavaScript и его методы. Я уверен, что после прочтения, JaveScript представится вам в другом свете.

Настоящий Мир

Большинство Настоящих Программистов относятся к JavaScript, словно к бедной родственнице из деревни — иногда полезна, но не очень важна. Настоящих Программистов не интересует язык, чье предназначение в том, чтобы заменять одно изображение другим или рисовать след за мышью по веб-странице. У Настоящих Программистов есть более важные дела.

Что ж, JavaScript ограничен стороной клиента в веб-транзакции, но на этой территории, он безусловный король. Нет языка, настолько простого к изучению или дающего возможность сделать столько полезных вещей с минимальными усилиями. И одно из того, что вы можете делать, это использовать регулярные выражения.

По ходу этой статьи, я собираюсь дать вам представление о регулярных выражениях в контексте JavaScript. Я покажу, как использовать объект String в JavaScript для простейших возможностей поиска соответствия или осуществления замены, так же, как и для более сложных действий со строками. И я представлю вам объект RegExp, который предоставляет удобный путь для создания более эффективного кода распространенной проверки входящих данных на стороне клиента. Итак, приступим; независимо от того, Настоящий ли вы Программист, или только пытаетесь им стать, я уверен, что вы найдете для себя кое-что полезное ниже.

Входим в Матрицу

Регулярные выражения, также известные как «регэкспы» среди программистов — мощный инструмент, использующийся для поиска по шаблону и замены подстрок. Они тесно связаны с почти всеми основанными на *nix утилитами, включая редакторы, вроде vi, скриптовые языки вроде Perl или PHP и консольными программами, такими, как awk и sed.

Регулярные выражения дают вам возможность построить шаблоны, используя набор специальных символов; эти шаблоны затем могут сопоставляться с текстом из файла, введенной в приложение датой или данными из формы, заполненной пользователем на сайте. В зависимости от того, есть ли совпадение, или нет, принимается соответствующее действие и вызывается соответственный программный код.

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

Регулярное выражение обычно имеет вид, подобный этому:

/matrix/

Нахождение шаблона «matrix» это все, что оно делает. Как насчет чего-то более сложного? Попробуйте это:

/mat+/

Это найдет слова «matting» и «mattres», но не «matrix». Почему? Потому что символ «+» используется для вхождения одного или более символа, расположенного перед ним. В нашем случае, за символами «ma» следует одно или более вхождение буквы «t».

Также есть мета-символы (это официальный термин), похожие на «+»: «*» и «?». Они используются для обозначения от нуля и более количества вхождений и нуля или одного вхождения предыдущего символа, соответственно. Поэтому:

/eg*/

может найти «easy», «egocentric» и «egg», в то время, как

/Wil?/

может найти «Winne», «Wimpy», «Wilson» и «William», но не «Wendy» или «Wolf». Если все это будет немного неточным, вы можете также указать интервал чисел совпадений. Например, регулярное выражение

/jim{2,6}/

может найти «jimmy» и «jimmmmmy!», но не «jim». Числа в фигурных скобках указывают минимальное и максимальное значения интервала соответствия; вы можете не указывать верхний предел для бесконечного количества соответствий.

Двое для Танго

А сейчас вы узнаете, какие регулярные выражения есть, давайте посмотрим на их использование в скрипте. Объект String в JavaScript дает набор методов, которые поддерживают регулярные выражения. Первый из них — это метод search(), используемый для поиска строки для соответствия определенному регулярному выражению. Посмотрите на следующий пример:

<script language="JavaScript">
 
// определяем строку для поиска
 
var str = "The Matrix";
 
// определяем шаблон поиска
 
var pattern = /trinity/;
 
// ищем и возвращаем результат
 
if(str.search(pattern) == -1) 
 
{
 
   alert("Тринити не в Матрице");
 
} else 
 
{
 
   alert("Трините в Матрице на символе " + 
 
   str.search(pattern));
 
}
 
</script>

Если вы выполните этот скрипт, вы увидете следующее:

Тринити не в Матрице

Метод search() возвращает позицию подстроки, соответствующую регулярному выражению или -1 в случае отсутствия такого соответствия. В нашем примере видно, что шаблона «trinity» в строке «The Matrix» нет, поэтому мы и получаем сообщение об ошибке. А теперь посмотрим, что будет, если изменить регулярное выражения так, чтобы результат был положительным:

<script language="JavaScript">
 
// определяем строку для поиска
 
var str = "The Matrix";
 
// определяем шаблон поиска
 
var pattern = /tri/;
 
// ищем и возвращаем результат
 
if(str.search(pattern) == -1) 
 
{
 
   alert("Тринити не в Матрице");
 
} else 
 
{
 
   alert("Трините в Матрице на символе " + 
 
   str.search(pattern));
 
}
 
</script>

В этот раз, интерпретатор JavaScript найдет соответствие (и место, где его нашел). Вот результат:

Trinity located in The Matrix at character 7

Игра, Установка, Соответствие

Объект String также предоставляет метод match(), который может расцениваться, как близкий родственник метода search(). В чем же разница? Что ж, вы уже увидели, что метод search() возвращает позицию, где находится соответствие. Метод match() работает немного по-другому: он применяет шаблон к строке и возвращает массив найденных значений.

Смущены? Посмотрите на следующий пример:

<script language="JavaScript">
 
// определяем строку
 
var str = "Mississippi";
 
// определяем шаблон
 
var pattern = /is./;
 
// проверяем на вхождение
 
// помещаем результат в массив
 
var result = 
 
str.match(pattern);
 
// display matches
 
for(i = 0; i < result.length; i++) 
 
{
 
 alert("Соответствие #" + (i+1) + ": " + result[i]);
 
}
 
</script>

Просмотрите этот пример в браузере, и вы получите сообщение, показывающее первый результат соответствия. Вот такой:

Соответствие #1: iss

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

Почему?

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

<script language="JavaScript">
 
// определяем строку
 
var str = "Mississippi";
 
// определяем шаблон
 
// и глобальный модификатор
 
var pattern = /is./g;
 
// проверяем на вхождение
 
// помещаем результат в массив
 
var result = 
 
str.match(pattern);
 
// display matches
 
for(i = 0; i < result.length; i++) 
 
{
 
 alert("Соответствие #" + (i+1) + ": " + result[i]);
 
}
 
</script>

И теперь, когда вы попробуете этот пример, вы должны увидеть два сообщения, показывающих нахождение двух вхождений этого шаблона в строку. Добавленный модификатор «g» обеспечивает нахождение всех вхождений шаблона в строку и сохранение в возвращаемый массив. Далее в этой статье, я покажу вам несколько других модификаторов.

Найти и Уничтожить

Предыдущий набор примеров демонстрировал возможности поиска объекта String. Но это ещё не все! Вы также можете осуществлять операции поиска и замены с помощью метод replace(), который принимает регулярное выражение и значение для его замены. Вот так:

<script language="JavaScript">
 
// определяем строку
 
var str = "Welcome to the Matrix, Mr. Anderson";
 
// заменяем одну строку на другую
 
str 
 
= str.replace(/Anderson/,"Smith");
 
// показываем новую строку
 
alert(str);
 
</script>

Если вы загрузите этот пример в браузере, вы увидите, что подстрока «Anderson» была занесена строкой «Smith». Что и иллюстрирует результат:

Welcome to the Matrix, Mr. Smith

Помните, как мы использовали модификатор «g» для поиска нескольких вхождений шаблона в строку? Переходим на следующую ступень — вы можете использовать его для замены нескольких вхождений шаблона в строку:

<script language="JavaScript">
 
// определяем строку
 
var str = "yo ho ho and a bottle of gum";
 
// возвращает "yoo hoo hoo and a bottle of gum"
 
alert(str.replace(/os/g, "oo "));
 
</script>

Здесь мета-символ «s» обозначает пробелы после «yo» и «ho» и заменяет на «oo».

Также, вы можете использовать нечувствительный к регистру поиск по шаблону — просто добавьте модификатор «i» в конце шаблона. Следующий пример демонстрирует, как это делается:

<script language="JavaScript">
 
// определяем строку
 
var str = "he He hE HE";
 
// возвращает ho ho ho ho
 
alert(str.replace(/he/gi, "ho"));
 
</script>

Разделяя

Объект String также предоставляет метод split(), который может быть использован для разделения одной строки на отдельные части на основе особого значения разделения. Эти части затем помещаются в массив для дальнейшей обработки. Демонстрирует это следующий пример:

<script language="JavaScript">
 
// определяем строку
 
var friends = "Joey, Rachel, Monica, Chandler, Ross, 
 
Phoebe";
 
// разделяем на части с помощью запятых
 
var arr = friends.split(", ");
 
// проходим по массиву и выводим
 
// каждое значение
 
for (x=0; x < arr.length; x++)
 
{
 
   alert("Hiya, " + arr[x]);
 
}
 
</script>

В JavaScript версии 1.1 и ниже, вы можете использовать только строковые значения в качестве разделителей. JavaScript 1.2 меняет все это, теперь вы можете разделять строки даже на основе регулярных выражений.

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

Neo
 
| Trinity   |Morpheus    |  
 
Smith|  Tank

Здесь символ «|» используется для разделения различных имен. И количество пробелов между разными «|» разное — это означает, что прежде, чем вы сможете использовать разные элементы строки, вы вынуждены удалить лишние пробелы вокруг них. Разделение с использованием регулярного выражения в качестве разделителя является элегантным решением этой проблемы, что мы и видим на следующем примере:

<script language="JavaScript">
 
// определяем строку
 
var str = "Neo| Trinity   
 
|Morpheus    |  Smith|  Tank";
 
// определяем шаблон
 
var pattern = /s*|s*/;
 
// разделяем строку с помощью
 
// регулярного выражения в
 
// качестве разделителя
 
result = 
 
str.split(pattern);
 
// проходим получившийся массив
 
for(i = 0; i < result.length; i++) 
 
{
 
 alert("Символ #" + (i+1) + ": " + result[i]);
 
}
 
</script>

Результатом работы этого кода будет массив, содержащий имена, без всякого удаления пробелов.

Объекты в зеркале заднего вида

Итак, все примеры в этой статье связаны с объектом String для демонстрации мощи реализации регулярных выражений в JavaScript. Но JavaScript также предоставляет базовый объект, RegExp, смысл существования которого — поиск по шаблону в строках и переменных.

Этот объект имеет три полезных метода. Вот они:

test() — проверяет строку на вхождение по шаблону.

exec() — возвращает массив найденных вхождений в строке, позволяя расширенную работу с регулярными выражениями

compile() — после того, как регулярное выражение связано с объектом RegExp.

Давайте рассмотрим простой пример:

<script language="JavaScript">
 
// определяем строку
 
var str = "The Matrix";
 
// создаем объект RegExp
 
var character = new RegExp("tri");
 
// ищем по шаблону в строке
 
if(character.test(str)) {
 
    alert("User 
 
          located in The Matrix.");
 
} else {
 
    alert("Sorry, user is not in The 
 
           Matrix.");
 
}
 
</script>

Это похоже на один из самых первых примеров этой статье. Тем не менее, как вы видите, он имеет совершенно другую реализацию.

Основное отличие находится в том, что создается объект RegExp для поиска с помощью регулярного выражения. Он создается с помощью ключевого слова «new», следующего за конструктором объекта. По определению, конструктор принимает два параметра: шаблон для поиска и модификаторы, если они имеют место быть (в этом примере их нет).

Следующим шагом после создания объекта, является его использование. Здесь мы использовали метод test() для поиска вхождения по шаблону. По умолчанию, этот метод принимает строковую переменную и сравнивает её с шаблоном, переданным в конструктор объекта. В случае нахождения соответствия, он возвращает true, в противном же случае false. Очевидно, что это более логичная реализация, чем использование метода search() объекта String.

Раз Миссиссипи, два Миссиссипи…

Следующий метод, который мы рассмотрим — это exec(). Поведение этого метода похоже на то, что делает метод match() объекта String. Посмотрим:

<script language="JavaScript">
 
// определяем строку
 
var place = "Mississippi";
 
// указываем шаблон
 
var obj = /is./;
 
// ищем вхождение,
 
// помещаем результат в массив
 
result = 
 
obj.exec(place);
 
// показываем результат
 
if(result != null) {
 
 alert("Found " + result[0] 
 
+ " at " + result.index);
 
}
 
</script>

Метод exec() возвращает соответствие указанному регулярному выражению, если такое имеется, как массив. Вы можете обратиться к первому элементу массива, чтобы получить найденную подстроку, а также её расположение с помощью метода index().

Главное различие между методами match() и exec() в передаваемых параметрах. Первый требует шаблон в качестве аргумента, второй же требует строку для проверки.

И это ещё не все. У метода exec() есть возможность продолжить поиск по строке для нахождения аналогичного вхождения без указания модификатора «g». Протестируем эту возможность с помощью следующего примера:

<script language="JavaScript">
 
// определяем строку
 
var place = "Mississippi";
 
// определяем шаблон
 
var obj = /is./;
 
// ищем все вхождения в строку
 
// показываем результат
 
while((result = 
 
   obj.exec(place)) != null) {
 
    alert("Found " + result[0] + " at " + 
 
          result.index);
 
}
 
</script>

Итак, что у нас есть здесь? Для начинающих: я использовал цикл «while» для вызова метода exec() до тех пор, пока не достигнут конец строки (на котором объект вернет null и цикл закончится). Это возможно, потому что каждый раз, вызывая exec(), объект RegExp продолжит поиск с того места, на котором закончил.

Но это все теория — такой код не будет работать ни в Internet Explorer, ни в NetScape Navigator, так что используйте его осторожно. Так что этот код чисто теоретический, по крайней мере до тех пор, пока не исправили ошибку (наверняка уже исправили — примеч. переводчика).

Другая интересная особенность этого кода заключается в создании объекта RegExp. Вы наверняка заметили, что, в отличие от предыдущего примера, здесь не используется конструктор для создания объекта. Вместо этого, шаблон просто применяется к переменной. Думайте об этом просто как о более коротком способе создания объекта RegExp.

Замены в ходе работы

Вы могли заметить в предыдущих примерах использования объекта RegExp, что регулярное выражение указывается во время создания объекта. Поэтому вы можете заинтересоваться, а что если требуется поменять шаблон позже?

Что ж, это не проблема. Метод compile() позволяет пользователю изменить шаблон объекта RegExp в выполнении поиска. Посмотрим:

<script language="JavaScript">
 
// определяем строку
 
var str = "The Matrix";
 
// определяем шаблон
 
var pattern = "trinity";
 
// define object
 
var character = new RegExp(pattern);
 
// смотрим вхождения
 
if(character.test(str)) {
 
alert("Looking for " + 
 
    pattern + "...User located in The Matrix");
 
} else {
 
alert("Looking for " 
 
    + pattern + "...Sorry, user is not in The Matrix");
 
}
 
// меняем шаблон
 
var pattern = "tri";
 
character.compile(pattern);
 
// смотрим на вхождение и показываем результат
 
if(character.test(str)) 
 
{
 
   alert("Looking for " 
 
     + pattern + "...User located in The Matrix");
 
} 
 
else {
 
   alert("Looking for " + pattern 
 
     + "...Sorry, user is not in The Matrix");
 
}
 
</script>

Учтите, что использование метода compile() для динамического изменения шаблона, связано с объектом RegExp.

Работаем с формами

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

<html>
 
<head>
 
<script 
 
language="Javascript">
 
// требует регулярное выражение
 
// в качестве параметра
 
function checkField(theForm, 
 
theField, theFieldDisplay, objRegex) {
 
 objField = eval("document." + theForm + 
 
		"." + theField);
 
 if(!objRegex.test(objField.value))  {
 
     alert ("Please 
 
           enter a valid " + 
 
	   theFieldDisplay + "");
 
 objField.select();
 
 objField.focus();
 
 return (false);
 
 }
 
return (true);
 
}
 
// регулярные выражения для различных
 
// полей формы
 
// номер кредитной карты
 
// должен содержать 20 цифр
 
objPatCCNum = 
 
/^[0-9]{20}$/;       
 
// дата окончания действия
 
// кредитной карты
 
// должна состоять из месяца 
 
// от 01 до 12 и года от 2003 до 2010
 
objPatCCDOE = 
 
/^([0][1-9]|[1][1-2])/20(0[3-9]|10)$/; 
 
// пин-код кредитной карты 
 
// должен быть численным
 
objPatCCPin = 
 
/^[0-9]+$/;
 
// адрес e-mail
 
// должен быть в формате user@host
 
objPatCCEmail 
 
=
 
/^([a-zA-Z0-9])+([.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-]+)+/;
 
// проверяем различные поля формы
 
function checkForm(theForm)
 
{
 
if(checkField(theForm, "cc_num", "Credit card number", objPatCCNum) 
 
&&
 
checkField(theForm, "cc_doe", "Date of expiry", objPatCCDOE) 
 
&&
 
checkField(theForm, "cc_pin", "PIN code", objPatCCPin) 
 
&&
 
checkField(theForm, "cc_email", "Email address", objPatCCEmail)) 
 
{
 
 	return true;
 
} else {
 
	return false;
 
}
 
}
 
</script>
 
</head>
 
<body>
 
<h2>Информация о кредитной карте</h2>
 
<form 
 
name="frmCCValidation" 
 
onSubmit="return checkForm('frmCCValidation');">
 
Номер кредитной карты:<br>
 
<input name="cc_num" type="text">
 
<p>
 
Тип кредитной карты <br>
 
<select name="cc_type">
 
<option 
 
value="Visa">Visa</option>
 
<option 
 
value="Mastercard">Mastercard</option>
 
<option 
 
value="AmericanExpress">American 
 
Express</option>
 
</select>
 
<p>
 
Дата окончания действия (мм/гггг) <br>
 
<input name="cc_doe" 
 
type="text">
 
<p>
 
Пин-код <br>
 
<input name="cc_pin" type="text">
 
<p>
 
Адрес электронной почты<br>
 
<input name="cc_email" type="text">
 
<p>
 
<input type="submit" value="Отправить">
 
</form>
 
</body>
 
</html>

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

В заключение

После прочтения, я почти уверен, что вы взглянули на JavaScript совсем с другой стороны. Язык, который вы увидели, не был наиболее часто используемым в замене изображений и определении браузера. Теперь это мощный инструмент, помогающий выполнять поиск по шаблону на стороне клиента быстро и эффективно.

Я начинал с простого введения в регулярные выражения и быстро перешел к методам search() и replace() объекта String. Эти функции принимают регулярное выражение в качестве параметра и позволяют производить операции поиска и замены со строковыми переменными. Это привело нас к рассказу об объекте RegExp. Этот объект дает набор методов и свойств, позволяющих программистом повысить уровень мощности использования регулярных выражений в JavaScript.

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

Вот несколько дополнительных ссылок, которые помогут вам понять концепцию регулярных выражений ближе:

«Stringing Things Along»

«Pattern Matching and Regular Expressions»

«Regular Expressions for client-side JavaScript, a free online quick reference»