автор:
дмитрий верещака

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

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

пусть, для определённости, пользователю необходимо ввести информацию о детях, а для упрощения примера - только имя и дату рождения. со стороны пользователя нам понадобится браузер, понимающий тэг <span> и регулярные выражения, поддерживающий функцию getelementbyid объекта document, а также понимающий свойство innerhtml, например, internet explorer 4.0+ с установленой поддержкой dhtml (будьте внимательны, по умолчанию при установке ie версии ниже 5.5 поддержка dhtml отключена. чтобы включить поддержу dhtml, например, в английском internet explorer 5.0, нужно запустить ie5setup и выполнить действия, показанные на рисунках 1 и 2), konqueror 2.2+, netscape 6, mozilla начиная с m16.

оформим ту часть формы, которая содержит информацию о детях, в виде таблицы. в самой первой строке таблицы мы разместим названия столбцов и добавим ещё одну ячейку, в которой разместим ссылку на добавление ещё одной строки с полями ввода информации. во второй строке таблицы мы разместим сами поля ввода информации плюс ячейку со ссылкой на удаление строки с информацией. чтобы можно было отличить строку данных от строки названий, добавим в тэг <tr> параметр id="newline" и номер строки в квадратных скобках (чтобы было легче отличить номер строки от символа 0) nomer="[0]". затем поместим всю таблицу во внутрь тэга span с каким-либо именем, например, table.
в итоге у нас должно получиться что-то вроде следующего html-кода:

<span id="table">
<table border=0 cellspacing=0 cellpadding=3>
<caption>сведения о детях</caption>
<tr><td>имя</td><td>дата рождения</td><td>
<a href="#" onclick="return addline();">добавить</a></td></tr>
<tr id="newline" nomer="[0]">
<td><input type="text" name="name[0]"></td><td><input type="text" name="date[0]"></td>
<td valign="top"><a href="#" onclick="return rmline(0);">удалить</td></tr></table>
</span>

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

<script>
var c=0; //счётчик количества строк
function addline()
{
c++; // увеличиваем счётчик строк
s=document.getelementbyid('table').innerhtml; // получаем html-код таблицы
s=s.replace(/[\r\n]/g,''); // вырезаем все символы перевода строк
re=/(.*)(<tr id=.*>)(<\/table>)/gi;
                // это регулярное выражение позволяет выделить последнюю строку таблицы
s1=s.replace(re,'$2'); // получаем html-код последней строки таблицы
s2=s1.replace(/\[\d+\]/gi,'['+c+']'); // заменяем все цифры к квадратных скобках
                // на номер новой строки
s2=s2.replace(/(rmline\()(\d+\))/gi,'$1'+c+')');
                // заменяем аргумент функции rmline на номер новой строки
s=s.replace(re,'$1$2'+s2+'$3');
                // создаём html-код с добавленным кодом новой строки
document.getelementbyid('table').innerhtml=s;
                // возвращаем результат на место исходной таблицы
return false; // чтобы не происходил переход по ссылке
}
function rmline(q)
{
                // if (c==0) return false; else c--;
                // если раскомментировать предыдущую строчку, то последний (единственный)
                // элемент удалить будет нельзя.
s=document.getelementbyid('table').innerhtml;
s=s.replace(/[\r\n]/g,'');
re=new regexp('<tr id="?newline"? nomer="?\\['+q+'.*?<\\/tr>','gi');
                // это регулярное выражение позволяет выделить строку таблицы с заданным номером
s=s.replace(re,'');
                // заменяем её на пустое место
document.getelementbyid('table').innerhtml=s;
return false;
}
</script>

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

таким образом, мы обнаружили, что использование регулярных выражений в javascript+dhtml открывает нам много новых возможностей для создания удобного пользовательского интерфейса. в частности, данный приём используется автором этих строк в интерфейсе администратора своего сайта для добавления нескольких картинок к странице в одной форме.