Недавно мой очень хороший знакомый попросил меня написать небольшой скрипт, который бы мог находить на загружаемой странице сайта определенное регулярное выражение и записывать вхождение в базу данных на сервере. Как только я услышал задачу, понял, что без AJAX тут никак. Пока с AJAXом у меня очень посредственные отношения: я написал только один полускрипт, который состоял в том, что при выборе категории товара на сайте подгружались подкатегории и товары этой супер категории, а при выборе подкатегории, выбирались товары только этой одной подкатегории и все это было выполнено в виде выпадающих списков <input type=”option”>… Итак, тот первый полускрипт я написал на чистом JavaScript с помощью XMLHttpRequest (XHR) и, конечно же, не без помощи w3school.org.
В этой задаче мне пришлось также столкнуться с объектом RegExp JavaScript. Я немного потренировался в его использовании, что, несомненно пошло мне на пользу. Например, я узнал, что для того, чтобы использовать РегЭксп-ы, не обязательно объявлять переменную, новый экземпляр объекта RegExp, а можно просто записать регулярное выражение в виде текcтовой строки, т.е. вместо
var r = new Regexp('.*', 'g');
можно просто написать вот так:
var r = '/.*/g';
Но, обратите внимание, что при использовании конструкции new RegExp использовать обратные слэши не нужно, т.к. при работе с регулярным выражением, объявленным таким образом, обработчик сам добавит недостающие символы. Также, в этом примере видно, что ключи к РегЭксп-у идут отдельным параметром к объекту, тогда как при составлении выражения в текстовой строке, ключ просто добавляется в конце регулярного выражения. В общем, если регулярное выражение просо записывается в строку, то и составляется оно по всем правилам составления регулярных выражений.
Ключ ‘g’ говорит обработчику, что не нужно останавливаться после первого вхождения регулярного выражения, а нужно искать по всему тексту, но простого указания этого ключа, как оказалось, совсем не достаточно.
В отличие от РНР, где функция preg_match_all записывает все вхождения в массив самостоятельно, для того, чтобы проделать тоже самое в JavaScript мне пришлось ускорить седение волос на голове:) Оказалось, что для поиска всех вхождений в документе с помощью JavaScript, нужно написать код такого плана:
r = new RegExp('.*text-([0-9]+).*', 'g'); res = null; while(res = r.exec(s)){ var i = r.lastIndex; // сюда вставляем код, который должен выполняться при нахождении регулярного выражения // это может быть запить найденного в переменную или ещё что-нибудь }
где res – массив в который записываются результаты поиска, где, в свою очередь, res[0] будет содержать вхождение всего регулярного выражения, res[1] будет содержать вхождение в первой группе скобок, res[2] – во второй и т.д.
r – экземпляр регулярного выражения;
exec() – метод объекта RegExp, который находит вхождения, соответствующие регулярному выражению и записывает их в массив. exec() отличается от test() тем, что записывает данные в массив, тогда как test() просто возвращает true если находит вхождение или false если не находит. Если же предпочитаете работать не с объектом, а с текстовой строкой, которая содержит РегЭксп, то используйте обычные методы match() – аналог exec(), или search() – почти аналог test(), с тем отличием, что возвращает позицию начала вхождения.
Тут потребуется небольшая оговорка по поводу использования search(): так как он возвращает число, а не булев тип (true/false), при отсутствии вхождения этот метод возвращает -1.
Кстати, при использовании просто текстовой строки для хранения РегЭксп-а, можно также использовать метод replace(), который находит вхождение регулярного выражения, или обычного текста, и заменяет на указанный в параметре текст.
Идем далее: s – источник поиска, т.е. где будем искать.
.lastIndex – параметр, отвечающий за позицию, где было найдено последнее вхождение. Если этот параметр не указать, обработчик JavaScript найдет только первое вхождение, даже при указании ключа ‘g’.
Далее, часть Ajax. На сайте этого моего товарища уже были подключены Prototype и jQuery, потому, я решил не подключать еще и Mootools к этому салату (вначале думал подключить, так как только с ним и знаком). Решил просто посмотреть документацию по этим библиотекам, чтобы понять, какой из них лучше воспользоваться для составления пакета и отправки на скрипт сервера. Оказалось, что проще, чем это предлагает сделать jQuery, не получится!
$.post(ServerSideScriptUrl, {var1:value1, val2:val2 ...})
Как видно из этого, вообще ничего проще нет. Спасибо jQuery!! Знакомый до боли селектор из Mootools $, потом указываем метод отправки – get/post, и несколько параметров. Конечно, в моем скрипте, требовалось лишь отправить данные, без их последующего приема, потому мне именно вариант jQuery показался самым простым. К сожалению, массивы с данными через XHR отправить не получится, но форма передачи данных на сервер, указанная выше, вполне справится с задачей передачи вполне большого объема данных.
Думаю, на этом и хватит описывать мой героический скрипт
РНР скрипт на стороне сервера даже описывать не буду, т.к. это скрипт на уровне первого класса (выполнен, тоже на уровне первого класса): получил данные, подключился к БД, записал в таблицу. Всё!
Конечно, это не большое достижение, но, все-таки – достижение. А тот факт, что я это все описал в этом посте, еще больше закрепит эти знания в моем прогламмерском мозгу.
Кстати, на фоне моего поста, посвященного первой решенной практической задачке, объявляю акцию:
Если вы учитесь программированию и решаете какие-либо задачи, присылайте их мне, буду их с удовольствием публиковать на рассмотрение всех посетителей блога. Думаю, они будут интересны не только мне!
Удачи!
P.S. Ух! Сколько ж раз я повторяю это слово в своих постах… со счета сбился… Но, КСТАТИ! Мой следующий урок Mootools посвещается именно работе с регулярными выражениями, так что НЕ пропустите!

#1 by Ильмир on 27.12.2010 - 2:41 am
Спасибо за урок, а демо можно глянуть?
#2 by proglammer on 29.12.2010 - 3:12 pm
К сожалению, для демки мне нужно будет подключать еще и библиотеку jQuery, а пока не хочется. В любом случае, с тех пор я уже научился нормально пользоваться классом Request моей любимой Mootools, потому, думаю, в скором постараюсь написать пост об использовании этого класса, и, конечно же, с демками
Спасибо за “Спасибо” !