В этой главе мы рассмотрим элементы управления и научимся с помощью JavaScript обрабатывать данные, введенные пользователем.
Командная кнопка является наиболее часто используемым элементом управления. При нажатии кнопки мы можем выполнить какую-либо операцию. Кнопка вставляется с помощью тега <input> или <button>. При использовании тега <button> текст на кнопке можно сделать цветным, имеется возможность отобразить значок, а также можно задать клавишу быстрого доступа. Пример создания кнопок:
<input type="button" value="Текст на кнопке">
<button type="button">Текст на кнопке</button>В параметре type указывается тип кнопки:
button — обычная командная кнопка;reset — кнопка, при нажатии которой вся форма очищается (элементы формы примут значения по умолчанию);submit — кнопка, при нажатии которой происходит отправка данных формы.Кнопки поддерживают следующие основные свойства:
value — текст, отображаемый на кнопке (для тега <input>);disabled — если задано значение true, то кнопка является неактивной (отображается серым цветом);type — тип кнопки.Методы:
blur() — убирает фокус ввода;focus() — устанавливает фокус ввода.События:
onblur — наступает при потере фокуса ввода;onclick — возникает при нажатии кнопки;onfocus — происходит при получении фокуса ввода.Пример обработки нажатия кнопки приведен в листинге 8.1.
Листинг 8.1. Обработка нажатия кнопки
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Командная кнопка</title>
</head>
<body>
<input type="button" value="Кнопка 1" id="btn1">
<button type="button" id="btn2">Кнопка 2</button>
<button type="button" id="btn3">Неактивная кнопка</button>
<script>
let btn1 = document.getElementById('btn1');
btn1.addEventListener('click', () => {
console.log('Нажата кнопка 1');
});
let btn2 = document.getElementById('btn2');
btn2.addEventListener('click', () => {
console.log('Нажата кнопка 2');
});
document.getElementById('btn3').disabled = true;
</script>
</body>
</html>Однострочные поля вставляются с помощью тега <input>. Параметр type может принимать следующие значения:
text — обычное текстовое поле;password — текстовое поле для ввода пароля (все введенные символы заменяются точками);search — поле ввода подстроки для поиска;url — текстовое поле для ввода URL Значение автоматически проверяется. Форма отправляется только в случае, если поле не заполнено или содержит корректное значение URL. Существование URL не проверяется. Если нужно исключить пустое значение, то следует дополнительно указать параметр required;email — текстовое поле для ввода E-mail. Значение автоматически проверяется. Форма отправляется только в случае, если поле не заполнено или содержит корректное значение E-mail. Существование E-mail не проверяется. Если нужно исключить пустое значение, то следует дополнительно указать параметр required;tel — текстовое поле для ввода телефона;date — поле для ввода даты. Справа от поля выводится значок, с помощью которого можно отобразить календарь;time — поле для ввода времени. Справа от поля выводится значок, с помощью которого можно отобразить возможные значения;datetime-local — поле для ввода даты и времени. Справа от поля выводится значок, с помощью которого можно отобразить календарь;month — поле для ввода месяца и года. Справа от поля выводится значок, с помощью которого можно отобразить возможные значения;week — поле для ввода номера недели и года. Справа от поля выводится значок, с помощью которого можно отобразить возможные значения.С помощью параметра value мы можем указать значение по умолчанию, а с помощью параметра placeholder — текст подсказки:
<input type="text" value="Значение по умолчанию">
<input type="text" placeholder="Текст подсказки">Если указан параметр autofocus, то после загрузки поле получит фокус ввода:
<input type="text" autofocus>Параметр required указывает, что поле обязательно для заполнения:
<input type="text" required>С помощью параметра pattern мы можем ограничить вводимое значение шаблоном регулярного выражения:
<input type="tel" placeholder="+0 (000) 000-00-00" required
pattern="\+[1-9] \([0-9]{3}\) [0-9]{3}-[0-9]{2}-[0-9]{2}">Поля имеют следующие основные свойства:
value — значение элемента формы;defaultValue — начальное значение, заданное параметром value;disabled — если задано значение true, то поле является неактивным (отображается серым цветом);maxLength — максимальное количество символов, которое может быть введено в поле;type — тип элемента;readOnly — если задано значение true, текст в поле нельзя редактировать, если false — можно.Методы:
blur() — убирает фокус ввода с текущего элемента;focus() — помещает фокус на текущий элемент;select() — выделяет текст в поле.Поддерживаются следующие события:
onblur — происходит при потере фокуса элементом формы;onchange — наступает после изменения данных в поле и при переводе фокуса ввода на другой элемент либо при отправке данных формы. Наступает перед событием onblur;onfocus — возникает при получении фокуса ввода.Кроме перечисленных событий можно использовать стандартные события мыши и клавиатуры.
Поле для ввода многострочного текста, описываемое парным тегом <textarea>, поддерживает те же свойства, методы и события, что и простое поле ввода, за исключением свойства maxLength. Кроме того, поддерживается еще одно свойство:
wrap — режим переноса слов. Может принимать следующие значения:off — не переносить слова;physical — слова переносятся как на экране, так и при передаче данных серверу;virtual — слова переносятся только на экране, но не при передаче данных серверу.Для примера рассмотрим возможность добавления слов из текстового поля в поле для ввода многострочного текста (листинг 8.2). Добавить слово можно с помощью кнопки Добавить слово или с помощью клавиши <Enter>. Так как по умолчанию нажатие клавиши <Enter> приводит к отправке данных формы, то всплывание события прерывается. При нажатии кнопки Значение поля выводится текущее значение тега <textarea>.
Листинг 8.2. Добавление слов из текстового поля в поле <textarea>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Пример использования поля <TEXTAREA></title>
<script>
function frmSubmit() {
let v = document.getElementById('txt1').value;
console.log('Текущее значение: \n' + v);
return false;
}
function btnClick() {
let txt2 = document.getElementById('txt2');
let text = txt2.value;
if (text != '') {
document.getElementById('txt1').value += text + '\n';
txt2.value = '';
txt2.focus();
}
else {
console.log('Поле не заполнено!');
txt2.focus();
}
}
window.onload = function () {
document.getElementById('txt2').onkeypress = function(e) {
if (e.keyCode == 13) {
btnClick();
e.preventDefault();
}
}
}
</script>
</head>
<body>
<form action="#" id="frm" onsubmit="return frmSubmit()">
<div>
Слово:<br>
<input type="text" name="txt2" id="txt2"><br>
<textarea name="txt1" id="txt1" cols="15" rows="10"></textarea>
<br><input type="button" value="Добавить слово"
onclick="btnClick()"><br>
<input type="submit" value=" Значение поля ">
</div>
</form>
</body>
</html>Поле для ввода числового значения реализуется с помощью тега <input>, параметр type которого имеет значение number. Справа от поля Web-браузер отображает две кнопки с помощью которых можно увеличить или уменьшить значение на шаг, указанный в параметре step. Значение автоматически проверяется. Форма отправляется только в случае, если поле не заполнено или содержит положительное или отрицательное число. Если нужно исключить пустое значение, то следует дополнительно указать параметр required:
<input type="number" step="5" required>
<input type="number" step="0.5" required>Если в параметре type указать значение range, то отобразится ползунок, с помощью которого можно выбрать числовое значение из диапазона. Элемент не содержит маркеров и меток, поэтому выставить значение можно только примерно. Для информирования пользователя о точном текущем значении нужно использовать дополнительные скрипты. Минимальное значение задается параметром min, максимальное — параметром max, текущее — параметром value, а шаг — параметром step:
<input type="range" min="0" max="100" value="10" step="2">Элементы number и range поддерживают следующие основные свойства:
value — текущее значение;min — минимальное значение;max — максимальное значение;step — шаг.Тег <select> создает список с возможными значениями:
<select>
<option>Элемент1</option>
<option>Элемент2</option>
</select>Основные свойства объекта списка:
disabled — если задано значение true, то список является неактивным (отображается серым цветом);length — количество пунктов в списке (доступно и для записи);multiple — true, если из списка можно выбрать сразу несколько элементов одновременно;options — ссылка на коллекцию пунктов в списке;selectedOptions — ссылка на коллекцию выбранных пунктов списка;selectedIndex — номер выбранного пункта (нумерация начинается с нуля);size — число одновременно видимых элементов списка;type — тип элемента формы (select-multiple или select-one);value — значение пункта, выбранного в списке.Свойства пункта списка:
defaultSelected — пункт списка, выбранный изначально;index — номер пункта в списке;selected — true, если пункт выбран в списке;disabled — если задано значение true, то пункт списка является неактивным (отображается серым цветом);text — текст пункта списка;value — значение пункта, выбранного в списке.Методы:
blur() — убирает фокус ввода с текущего элемента формы;focus() — помещает фокус на текущий элемент формы.События:
onblur — наступает при потере фокуса элементом формы;onchange — происходит после выбора нового пункта списка;onfocus — наступает при получении фокуса ввода элементом формы.Рассмотрим пример работы со списками. Документ, приведенный в листинге 8.3, демонстрирует следующие возможности:
Листинг 8.3. Обработка списков
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Пример обработки списков</title>
</head>
<body>
<form action="#" id="frm">
<!-- Добавление пункта в список -->
<script>
function addOption() {
let txt1 = document.getElementById('txt1');
let txt2 = document.getElementById('txt2');
let select1 = document.getElementById('select1');
if (txt1.value != '' && txt2.value != '') {
let i = select1.length++;
select1.options[i].text = txt1.value;
select1.options[i].value = txt2.value;
txt1.value = '';
txt2.value = '';
txt1.focus();
}
else {
console.log('Поле не заполнено!');
txt1.focus();
}
}
function press1(e) {
if (e.keyCode == 13) {
document.getElementById('txt2').focus();
e.preventDefault();
}
}
function press2(e) {
if (e.keyCode == 13) {
addOption();
e.preventDefault();
}
}
</script>
<div>
<b>Добавление пункта в список:</b><br><br>
Текст пункта:<br>
<input type="text" id="txt1" onkeypress="press1(event)">
<br>Значение пункта:<br>
<input type="text" id="txt2" onkeypress="press2(event)">
<br><select id="select1">
</select><br>
<input type="button" value="Добавить"
onclick="addOption()"><br><br>
<!-- Список со множественным выбором -->
<script>
function multi() {
let msg = '';
let select2 = document.getElementById('select2');
if (select2.selectedOptions) {
let obj = select2.selectedOptions;
let count = obj.length;
for (let i = 0; i < count; i++) {
msg += obj[i].value + ' - ';
msg += obj[i].text + '\n';
}
}
else {
let count = select2.length;
for (let i = 0; i < count; i++) {
if (select2.options[i].selected) {
msg += select2.options[i].value + ' - ';
msg += select2.options[i].text + '\n';
}
}
}
console.log(msg);
}
</script>
<b>Список со множественным выбором:</b><br><br>
<select id="select2" size="5" multiple>
<option value="1" selected>Элемент1</option>
<option value="2">Элемент2</option>
<option value="3">Элемент3</option>
<option value="4">Элемент4</option>
<option value="5">Элемент5</option>
<option value="6">Элемент6</option>
</select><br>
<input type="button" value="Значения списка"
onclick="multi()"><br><br>
<!-- Взаимосвязанные списки -->
<script>
let arr = [];
arr[1] = ['Тема1 Элемент1', 'Тема1 Элемент2'];
arr[2] = ['Тема2 Элемент1', 'Тема2 Элемент2',
'Тема2 Элемент3'];
let value1 = [];
value1[1] = ['1', '2'];
value1[2] = ['3', '4', '5'];
function change1() {
let index = document.getElementById('select3').value;
let select4 = document.getElementById('select4');
let count = arr[index].length;
select4.length = count;
for (i = 0; i < count; i++) {
select4.options[i].value = value1[index][i];
select4.options[i].text = arr[index][i];
}
}
function change2() {
let sel = document.getElementById('select4');
let msg = 'Значение: ' +
sel.options[sel.selectedIndex].value;
msg += '\nТекст: '
+ sel.options[sel.selectedIndex].text;
console.log(msg);
}
</script>
<b>Взаимосвязанные списки:</b><br><br>
<select name="select3" id="select3" size="5"
onchange="change1()">
<option value="1">Тема1</option>
<option value="2">Тема2</option>
</select><br>
<select name="select4" id="select4" onchange="change2()">
<option value="1" selected>Тема1 Элемент1</option>
<option value="2">Тема1 Элемент2</option>
</select>
</div>
</form>
</body>
</html>Флажок и переключатели вставляются с помощью тега <input>, параметр type которого может принимать следующие значения:
checkbox — поле для установки флажка;radio — элемент-переключатель.Флажки и переключатели имеют следующие свойства:
value — значение текущего элемента формы;checked — true, если флажок или переключатель находится во включенном состоянии;defaultChecked — флажок или переключатель установлен по умолчанию. Содержит true или false;disabled — если задано значение true, то элемент является неактивным (отображается серым цветом);indeterminate — если true, то флажок находится в неопределенном состоянии, и false — в противном случае;type — тип элемента.Методы:
blur() — убирает фокус ввода с текущего элемента формы;focus() — помещает фокус на текущий элемент формы.События:
onblur — наступает при потере фокуса элементом формы;onclick — возникает при выборе элемента;onfocus — происходит при получении фокуса ввода элементом формы.Чтобы найти выбранный элемент-переключатель в группе, необходимо перебрать все переключатели в цикле. Получить значение выбранного переключателя можно указав внутри квадратных скобок индекс элемента в группе. Рассмотрим это на примере (листинг 8.4).
Листинг 8.4. Обработка флажков и переключателей
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Пример использования флажков и переключателей</title>
<script>
function btnClick() {
let msg = '';
if (document.getElementById('check1').checked) {
msg = 'Флажок установлен\n';
msg += 'Значение: ' +
document.getElementById('check1').value + '\n';
}
else {
msg = 'Флажок снят\n';
}
let value1 = '';
let count = document.frm.radio1.length;
for (i = 0; i < count; i++) {
if (document.frm.radio1[i].checked) {
value1 = document.frm.radio1[i].value;
break;
}
}
if (value1 == 'male') {
msg += 'Пол: Мужской\n';
}
else {
msg += 'Пол: Женский\n';
}
console.log(msg);
}
</script>
</head>
<body>
<form action="#" name="frm" id="frm">
<div>
<input type="checkbox" name="check1" id="check1"
value="yes" checked>
Текст<br><br>
Укажите ваш пол:<br>
<input type="radio" name="radio1" id="radio1"
value="male" checked>Мужской
<input type="radio" name="radio1" id="radio2"
value="female">Женский
<br><br>
<input type="button" value="Вывести значения"
onclick="btnClick()">
</div>
</form>
</body>
</html>Поле для выбора файла вставляется с помощью тега <input>, параметр type которого имеет значение file:
<input type="file">Поле для выбора файла поддерживает следующие параметры:
multiple — если параметр указан, то можно выбрать сразу несколько файлов:<input type="file" multiple>accept — задает поддерживаемые MIME-типы или расширения файлов (значения перечисляются через запятую):<input type="file" accept="image/jpeg,image/png,image/gif">
<input type="file" accept="image/*">
<input type="file" accept=".gif,.jpg,.jpeg">Все выбранные файлы доступны через коллекцию files. Если файлы выбраны, то свойство length будет иметь значение больше 0. Получить путь к выбранному файлу позволяет свойство path (листинг 8.5).
Листинг 8.5. Поле для выбора файла
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Поле для выбора файла</title>
</head>
<body>
<input type="file" id="file1">
<button type="button" id="btn1">Проверить</button>
<script>
document.getElementById('btn1').addEventListener('click', () => {
let file1 = document.getElementById('file1');
if (file1.files.length === 0) {
console.log('Файл не выбран');
}
else {
console.log(file1.files[0].path);
}
});
</script>
</body>
</html>Элемент для выбора цвета реализуется с помощью тега <input>, параметр type которого имеет значение color. При щелчке на элементе отображается диалоговое окно, в котором можно выбрать цвет или ввести его значение вручную. Текущее значение задается с помощью параметра value в формате #RRGGBB:
<input type="color" value="#000000" id="color1">Получить выбранное значение позволяет свойство value:
let color1 = document.getElementById('color1');
console.log(color1.value);Парный тег <progress>, позволяет в графической форме отобразить текущее состояние хода выполнения процесса. Тег имеет следующие параметры:
value — текущее значение;max — максимальное значение.Пример:
<progress max="100" value="50"></progress>Все элементы управления можно поместить внутри формы. В этом случае внутри обработчика отправки формы (событие onsubmit) можно выполнить автоматическую проверку данных, внесенных пользователем в элементы управления. Для этого к элементам управления добавляем параметр required и правильно выбираем сам элемент, чтобы он соответствовал нашим требованиям. Например, для ввода E-mail выбираем элемент с типом email, а не text.
Выполнить проверку на корректность введенных данных сразу всех элементов позволяет метод checkValidity() объекта формы (листинг 8.6). Он возвращает true, если во все элементы управления формы занесены корректные данные, и false — в противном случае.
Листинг 8.6. Проверка корректности введенных данных
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Проверка корректности введенных данных</title>
</head>
<body>
<form action="#" id="frm">
<input type="email" name="email" required>
<input type="submit" value="Проверить">
</form>
<script>
let frm = document.getElementById('frm');
frm.addEventListener('submit', (e) => {
e.preventDefault();
if ( !frm.checkValidity() ) {
console.log('Введите корректные данные!');
}
else {
console.log('Данные введены правильно');
}
});
</script>
</body>
</html>Элементы управления поддерживают следующие свойства:
validationMessage — возвращает текст сообщения об ошибке;validity — сведения об ошибках. Содержит объект класса ValidityState, который поддерживает следующие свойства:badInput — true, если введенное значение неполное;patternMismatch — true, если введенное значение не совпадает с заданным шаблоном регулярного выражения, из параметра pattern);rangeOverflow — true, если введенное число больше указанного максимального значения;rangeUnderflow — true, если введенное число меньше указанного минимального значения;stepMismatch — true, если введенное число не укладывается в заданный интервал;tooLong — true, если введенная строка слишком длинная;typeMismatch — true, если введенное значение не соответствует требуемому типу;valueMissing — true, если обязательное поле пустое;customError — true, если было задано иное сообщение об ошибке ввода данных;valid — true, если введенное значение полностью корректно (и все перечисленные ранее свойства хранят значение false);willValidate — содержит true, если значение элемента будет проверяться на корректность.Пример проверки корректности ввода значения для конкретного элемента управления приведен в листинге 8.7.
Листинг 8.7. Свойство validity
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline'">
<title>Свойство validity</title>
</head>
<body>
<input type="email" name="email" id="email" required>
<input type="button" id="btn1" value="Проверить">
<script>
let btn1 = document.getElementById('btn1');
btn1.addEventListener('click', (e) => {
let email = document.getElementById('email');
if (!email.validity.valid) {
console.log('Введите корректные данные!');
console.log(email.validationMessage);
}
else {
console.log('Данные введены правильно');
}
});
</script>
</body>
</html>