Иногда мы не знаем, сколько именно данных пользователь захочет сообщить, но дать ему возможность выбирать нужно. Скажем, требуется получить несколько номеров телефонов из необязательных полей, или сформировать опрос с неизвестным заранее числом вариантов.
Один из возможных вариантов решения — получать информацию в сыром виде и обрабатывать ее согласно определенным алгоритмам. Допустим, поместить слова в массив и пройти через него регулярным выражением на сервере.
Можно использовать сложный плагин jQuery и оперировать объектами JSON.
Или можно построить простой клиентский скрипт для отрисовки массива полей по флагам.
Первый вопрос, который приходит в голову после получения задачи организовать произвольное число полей для ввода — как обеспечить уникальные имена для правильной отправки данных на сервер? Для этого можно использовать уникальные идентификаторы, генерирующиеся при прохождении через цикл, либо использовать массивы. Но в первом случае для извлечения иноформации в правильный контейнер потребуется сопоставлять каждый ключ с предзаданным шаблоном и, вероятно, использовать функции поиска подстроки. Во втором случае для перебора нам потребуется только функция рекурсивного прохода массива — конкретные ключи и их количество не имеют значения на этапе получения и валидации данных.
Далее следует придумать механизм добавления полей. В простейшем случае мы формируем html-шаблон поля и добавляем его в определенный блок нужное число раз. Обратная сторона этой простоты — невозможность удалить какое-то определенное поле. Потому что как скрипт узнает, в какой именно блок мы ткнули, желая убрать его из списка? Можно передавать идентификатор строки функции разбора DOM, которая пройдет по содержимому целевого блока до нужного узла и отсоединит его. Или инициализировать счетчик и использовать флаги: если значение — 1, то такой блок нам нужен, а если 0 — давайте его удалим.
Кроме того, стоит обрабатывать и добавление и удаление полей одной функцией, для чего достаточно научить ее отличать плюс от идентификатора.
Посмотрим на код:
<script>
var i = 0; // Инициализируем счетчик
var emp_arr = new Array();
function emp_list(flag, emp_arr)
{
var emp_div = document.getElementById('employees'); // Находим целевой элемент
emp_div.innerHTML = ''; // Очищаем целевой элемент
if('+' == flag)
{
i++;
emp_arr[i] = 1; // Добавляем в массив сотрудников
}
else
{
var sum = 0; // Не позволяем удалять последний элемент - если сумма ключей в массиве равна единице, ничего не делаем
for(var z=0; z<=emp_arr.length; z++)
{
if(1 == emp_arr[z]) {sum++;}
}
if(1 != sum) {emp_arr[flag] = 0;}
}
for(var z=0; z<=emp_arr.length; z++)
{
// Для дальнейшей обработки данных на сервере передаем элементы с именами в виде массивов. Затем сможем получить их значения при переборе $_POST
var emp_field='<p><input type="text" name="family_name[]" value="Фамилия" size="20" /> <input type="text" name="first_name[]" value="Имя" size="20" /> <input type="text" name="fathers_name[]" value="Отчество" size="20" /> | Номер мобильного телефона: <input type="text" name="tel_num[]" value="+7(999) 999-9999" size="20" /> | <span class="link" onclick="emp_list(''+z+'', emp_arr);">Удалить</span></p>';
if(1 == emp_arr[z]) {emp_div.innerHTML+=emp_field;}
}
}
</script>
Добавим разметку для вывода, кнопку вызова функции и инициализирующую инструкцию:
<div id="employees">
<!-- Здесь будут поля формы -->
<script>
emp_list('+', emp_arr);
</script>
</div>
<p><span class="link" onclick="emp_list('+', emp_arr);">Добавить сотрудника</span></p>
Стили для кнопок:
<style>
.link { color: #0069c4; cursor: pointer;}
.link:hover {text-decoration: underline;}
</style>
Готово
<!DOCTYPE html>
<html>
<head>
<title>Произвольное число полей в веб-форме</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.link { color: #0069c4; cursor:pointer;}
.link:hover {text-decoration:underline;}
</style>
<script>
var i = 0; // Инициализируем счетчик
var emp_arr = new Array();
function emp_list(flag, emp_arr)
{
var emp_div = document.getElementById('employees'); // Находим целевой элемент
emp_div.innerHTML = ''; // Очищаем целевой элемент
if('+' == flag)
{
i++;
emp_arr[i] = 1; // Добавляем в массив сотрудников
}
else
{
var sum = 0; // Не позволяем удалять последний элемент - если сумма ключей в массиве равна единице, ничего не делаем
for(var z=0; z<=emp_arr.length; z++)
{
if(1 == emp_arr[z]) {sum++;}
}
if(1 != sum) {emp_arr[flag] = 0;}
}
for(var z=0; z<=emp_arr.length; z++)
{
// Для дальнейшей обработки данных на сервере передаем элементы с именами в виде массивов. Затем сможем получить их значения при переборе $_POST
var emp_field='<p><input type="text" name="family_name[]" value="Фамилия" size="20" /> <input type="text" name="first_name[]" value="Имя" size="20" /> <input type="text" name="fathers_name[]" value="Отчество" size="20" /> | Номер мобильного телефона: <input type="text" name="tel_num[]" value="+7(999) 999-9999" size="20" /> | <span class="link" onclick="emp_list(''+z+'', emp_arr);">Удалить</span></p>';
if(1 == emp_arr[z]) {emp_div.innerHTML+=emp_field;}
}
}
</script>
</head>
<body>
<h1>Информация о сотрудниках</h1>
<div id="employees">
<!-- Здесь будут поля формы -->
<script>
emp_list('+', emp_arr);
</script>
</div>
<p><span class="link" onclick="emp_list('+', emp_arr);">Добавить сотрудника</span></p>
</body>
</html>
Для повышения гибкости можно избавиться от указания на функциональность в именах переменных и предоставлять функции больше аргументов — допустим, идентификатор целевого блока и шаблон вывода. В таком случае использовать ее можно будет для динамического добавления любых блоков и полей.
Автор: lutov