Створення елементів форми із можливістю вибору одного значення
ЗавданняФорма повинна містити поле, яке пропонує користувачеві багато варіантів, але дозволяє вибрати лише один із них.
РішенняВикористовуйте елементи з можливістю вибору єдиного значення зі списку (single-pick list element). До них відносяться набори перемикачів, спливаючі меню або списки, що прокручуються.
ОбговоренняЕлементи форми з можливістю вибору єдиного значення дозволяють пропонувати на вибір кілька варіантів, з яких можна вказати лише один. У нашому прикладі є кілька наборів таких елементів:
• Список кольорів таблиці cow_color. Їх можна отримати за допомогою такого запиту:
mysql> SELECT color FROM cow_color ORDER BY color;
Зверніть увагу на те, що деякі назви кольорів містять символ &, що має спеціальне значення в HTML.
Тобто при використанні для елементів списку такі значення необхідно кодувати за стандартом HTML. (Насправді ми будемо виконувати кодування для всіх спискових елементів форми, але ці значення наочно демонструють, що кодування є гарною звичкою.)
• Список допустимих розмірів фігурок зі стовпчика size таблиці cow_order.
Стовпець відноситься до типу ENUM, тому можливі значення та значення за замовчуванням можна отримати за допомогою пропозиції SHOW COLUMNS:
mysql> SHOW COLUMNS FROM cow_order LIKE 'size'\G *************************** 1. row ******* ******************** Field: size Type: enum('small','medium','large') Null: YES Key: Default: medium Extra:
• Список назв та абревіатур штатів, які зберігаються в таблиці states:
mysql> SELECT abbrev, name FROM states ORDER BY name;
+--------+---------------+ abbrev name +--------+---------------+ AL Alabama AK Alaska AZ Arizona AR Arkansas CA California CO Colorado CT Connecticut .
Кількість значень для вибору у всіх цих списках різна: 3 розміри, 7 кольорів та 50 штатів.
Значення розмірів найкраще подати у вигляді перемикачів, у списку, що прокручується, необхідності немає через невелику кількість значень для вибору. Багато кольорів прийнятно уявити будь-яким з елементів для вибору єдиного значення. Воно досить маленьке, так що набір перемикачів займе не дуже багато місця, але й досить велике для того, щоб використовувати прокручування – особливо якщо додаватимуться додаткові кольори. Список штатів, ймовірно, має занадто багато значень, щоб бути представленим у вигляді перемикачів, тому найбільш розумним його відображенням буде спливаюче меню або список, що прокручується.
Розглянемо синтаксис кожного з типів елементів, та був спробуємо згенерувати їх із сценаріїв.
Перемикачі. Група перемикачів складається із елементів типу radio з однаковими атрибутами name. Кожен елемент також має атрибут value. Текст можна вказати після тега .
Щоб позначити значення як вихідний варіант вибору за умовчанням, додайте атрибут checked. Наступна група перемикачів виводить можливі розміри фігурок корів, при цьому середнє значення (medium) позначено як за замовчуванням:
small medium large
Спливне меню – це список, укладений між тегами, в якому кожен пункт меню містить теги. У кожного елемента \n", htmlspecialchars ($values[$i]), $checked, htmlspecialchars ($labels[$i])); > $str = sprintf ( "\n", htmlspecialchars ($name), $str); return ($str); >
У функції make_popup_menu() немає параметра $vertical, але в іншому вона викликається так само, як make_radio_group():
print (make_popup_menu ("color", $values, $values, ""));
Функція make_scrolling_list() схожа на make_popup_menu(), тому я не наводжу її реалізацію. Якщо ви бажаєте викликати її для формування списку з можливістю вибору єдиного елемента, передайте їй ті ж аргументи, що й make_popup_menu(), вкажіть, скільки рядків має відображатися одночасно і додайте аргумент multiple зі значенням FALSE:
print (make_scrolling_list ("color", $values, $values, "", 3, FALSE));
Список штатів використовує різні набори даних для значень та видимого тексту. Витягнемо їх так:
$ values = array (); $labels = array(); $query = "SELECT abbrev, name FROM states ORDER BY name"; $result_id = mysql_query ($query, $conn_id); if ($result_id) $values[] = $abbrev; $labels[] = $name; > mysql_free_result ($result_id); >
Потім використовуємо видимий текст та значення для формування необхідного списку:
print (make_popup_menu ("state", $values, $labels, "")); print (make_scrolling_list ("state", $values, $labels, "", 6, FALSE));
Реалізація функцій Python аналогічна версіям на PHP. Наприклад, функція make_popup_menu() виглядає так:
def make_popup_menu (name, values, labels, default): якщо type (values) не в (types.ListType, types.TupleType): return ("make_popup_group: values argument must be a list") if type (labels) not in (types.ListType, types.TupleType): return ("make_popup_group: labels arguments must be a list") if len (values) != len (labels): return("make_popup_group: цінність і мітка символів") str = "" for i in range (len (values)): value = values[i] label = labels[i ] # перевірити, чи є значення та видимий текст рядками if type (value) is not types.StringType: value = `value` if type (label) is not types.StringType: label = `label` # вибрати елемент, якщо він відповідає за промовчанням if type (default) is not types.StringType: default = `default` if value == default: checked = "selected=\"selected\"" else: checked = "" str = str + \ " \n" \ % (cgi .escape (value, 1), checked, cgi.escape (label, 1)) if type (name) is not types.StringType: name = `name` str = " \n" \ % (cgi.escape (name, 1), str) return (str)Для подання у формі кольорів корів витягуємо їх з таблиці: values = [] query = "SELECT color FROM cow_color ORDER BY color" cursor = conn.cursor () cursor.execute (query) for (color, ) in cursor.fetchall (): values .append (color) cursor.close ()
Потім перетворимо список елемент форми:
print make_radio_group ("color", values, values, "", 1) print make_popup_menu ("color", values, values, "") print make_scrolling_list ("color", values, values, "", 3, 0)
Для виведення списку штатів витягуємо їх назви та абревіатури:
values = [] labels = [] query = "SELECT abbrev, name FROM states ORDER BY name" cursor = conn.cursor () cursor.execute (query) for (abbrev, name) in cursor.fetchall (): values.append (abbrev) labels.append (name) cursor.close ()
Потім передаємо відповідної функції:
print make_popup_menu ("state", values, labels, "") print make_scrolling_list ("state", values, labels, "", 6, 0)
Єодна річ, яку функції на Python виконують, а їх аналоги на PHP – ні: явне перетворення значень аргументів, що вбудовуються до списку у рядковому форматі. Це необхідно, тому що метод cgi.escape() породжує виняток, якщо ви намагаєтеся використовувати його для кодування HTML нестрокового значення.
Поки що ми говорили про вилучення рядків з таблиць cow_color і states та їх перетворення на елементи форми. Для онлайн-застосування для замовлення фігурок корів необхідний ще один елемент форми - поле, що вказує розмір статуетки. Дозволені значення цього поля визначаються стовпцем size таблиці cow_order. Цей стовпець відноситься до типу ENUM, так що для отримання допустимих значень елемента форми слід отримати визначення стовпця і виділити потрібну інформацію.
На щастя, більша частина роботи з вирішення цього завдання вже була зроблена в рецепті 9.6, де створювалися функції виведення метаданих стовпців ENUM і SET. Наприклад, у Perl для отримання метаданих стовпця size викличте функцію get_enumorset_info():
my $size_info = get_enumorset_info ($dbh, "cow_order", "size");
Член values є посиланням на дозволені значення перерахованого типу, а default – це значення стовпця за умовчанням. Формат інформації дозволяє безпосередньо перетворити її на елемент форми, наприклад у групу перемикачів або спливаюче меню:
print radio_group (-name => "size", -values => $size_info->, -default => $size_info->, -linebreak => 1) ; # розташувати кнопки вертикально print popup_menu (-name => "size", -values => $size_info->, -default => $size_info->);
Значенням за промовчанням є medium, це значення буде обрано під час відкриття форми броузером.
Функція вилученняметаданих для PHP повертає асоціативний масив. Використовуємо його для генерування елементів форми на основі метаданих стовпця size так:
$size_info = get_enumorset_info ($conn_id, "cow_order", "size"); print (make_radio_group ("size", $size_info["values"], $size_info["values"], $size_info["default"], TRUE)) ; # розташувати елементи вертикально print (make_popup_menu ("size", $size_info["values"], $size_info["values"], $size_info["default"]));
Версія функції Python повертає словник, який використовується аналогічно:
size_info = get_enumorset_info (conn, "cow_order", "size") print make_radio_group ("size", size_info["values"], size_info["values"], size_info[" default"], 1) print make_popup_menu ("size", size_info["values"], size_info["values"], size_info["default"])
Якщо ви саме так використовуєте значення ENUM для створення спискових елементів, вони виводяться в тому порядку, в якому були вказані у визначенні стовпця. У визначенні стовпця size значення представлені у зручному для відображення порядку (small, medium, large), якщо вас не влаштовує порядок стовпців у визначенні, відсортуйте їх.
Щоб проілюструвати створення елементів форми для JSP-сторінок на основі метаданих стовпця, я використовуватиму функцію, що вбудовується в сторінку. Найбільш вдалим способом є створення в бібліотеці тегів дії користувача (custom action), яке відповідає класу, що повертає інформацію, але створення користувацьких тегів виходить за рамки даної книги. Тому в прикладах застосовуватимуться такі прийоми:
• Використовуємо теги JSTL для виконання запиту SHOW COLUMNS з метою отримання визначення стовпця ENUM, потім переміщуємо визначення в контекстсторінки.
• Пишемо функцію, яка вибирає визначення з контексту сторінки, розбиваємо його на масив окремих значень і поміщаємо масив назад у контекст сторінки.
• Звертаємось до масиву за допомогою ітератора JSTL, який виводить кожне із значень як елемент списку. Кожне значення порівнюється зі значенням стовпця за замовчуванням і, у разі збігу, значення позначається як обране.
Функція, що отримує дозволені значення визначення стовпця ENUM або SET, називається getEnumOrSetValues(). Помістимо її до сторінки JSP так:
Функція приймає три аргументи:
• Об'єкт контексту сторінки.
• Ім'я атрибута сторінки, який містить визначення стовпця. Це "вхід" функції.
• Ім'я атрибута сторінки, на якому міститься результуючий масив дозволених значень стовпця. Це "вихід" функції.
Для формування спискового елемента на основі стовпця size почнемо з одержання метаданих стовпця: вилучимо список значень стовпця у змінну JSTL values, а значення за замовчуванням – змінну default:
SHOW COLUMNS FROM cow_order LIKE 'size'
Потім використовуємо список значень і значення за промовчанням для побудови елемента форми. Наприклад, створимо групу перемикачів:
Або спливаюче меню:
Методи формування списків, що обговорюються, не пов'язані з якоюсь певною таблицею бази даних, тому можуть використовуватися при створенні елементів форми для будь-яких типів даних, а не тільки аналізованих нами для виробництва фігурок корів. Наприклад, щоб дати користувачеві можливість вибрати таблицю в додатку адміністрування бази даних, можна сформувати список імен всіх її таблиць, що прокручується.
Сценарій CGI.pm міг би це робити так:
my$table_ref = $dbh->selectcol_arrayref ("SHOW TABLES"); print scrolling_list (-name => "table", -values => $table_ref, -size => 10); # показувати 10 записів одночасно
Результати запиту навіть необов'язково мають бути пов'язані з таблицями бази даних. Наприклад, якщо ви хочете вивести на сторінку JSP список, що містить запис для кожного з останніх семи днів, то можете отримати ці дати за допомогою такого запиту:
SELECT DATE_SUB(CURDATE(),INTERVAL 5 DAY),DATE_SUB(CURDATE(),INTERVAL 4 DAY), DATE_SUB(CURDATE(),INTERVAL 3 DAY), DATE_SUB(CURDATE(),INTERVAL 2 DAY), DATE_SUB(CURDATE(),INTERVAL 1 DAY), CURDATE()
Потім використовувати дати для формування спискового елемента:
(Звичайно, якщо API забезпечує простий спосіб обчислення дат, то можливо ефективніше виводити список дат з клієнтської сторони, не надсилаючи запит на сервер MySQL.)