webew
Войти » Регистрация
 
HTML

Tabindex - умный переход между элементами с помощью клавиши Tab

25 июня 2008, 23:38

При работе с формами зачастую удобнее и быстрее переключаться между полями с помощью клавиши Tab, чем тыкать в нужное поле мышью. Однако, не всем известно, что можно управлять последовательностью, по которой происходит смена фокуса при нажатии Tab-а. Для этого в HTML4.01 существует атрибут tabindex.

С помощью клавиши TAB на странице можно ходить по элементам, которые способны принимать фокус. К ним относятся ссылки (A), элементы форм (BUTTON, INPUT, TEXTAREA, SELECT), области имедж-мапы (AREA) и OBJECT. Причем последовательность обхода такая же, в каком порядке элементы располагаются в потоке документа.

Browser-test

Однако, не все браузеры одинаково полезны ведут себя при tab-обходе. Убедимся в этом на примере простого кода:

<p>
    <a href="#">Первая ссылка</a><br>
    <button>Первая кнопка</button><br>
    <input type="text" value="Первый текстбокс"><br>
    <textarea>Первая текстария</textarea><br>
    <select><option value="#">Первый селект</option></select><br>
</p>
<p>
    <a href="#">Вторая ссылка</a><br>
    <button>Вторая кнопка</button><br>
    <input type="text" value="Второй текстбокс"><br>
    <textarea>Вторая текстария</textarea><br>
    <select><option value="#">Второй селект</option></select><br>
</p>

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

  • IE6, IE7 — отрабатывают так, как ожидалось.
  • Mozilla 1.7.2, Netscape 7.1 сначала совершают обход, как ожидалось, затем передают фокус адресной строке, а потом всему документу.
  • Firefox 2.0 работает так же, как мозилла и нетскейп, плюс на после адресной строки фокус передается в search-bar (если он есть) и на активную закладку.
  • WIN: Opera (версии 7.5, 9.2, 9.5) и Safari 3 передают фокус только элементам форм, напрочь игнорируя ссылки

Итак, есть серьезные отличия в поведении браузеров, а в случае Сафари и Оперы они довольно критичны.

О tabindex

Атрибут tabindex принимает целочисленные неотрицательные значения (не более 32767), которые показывают порядок, в котором будет совершаться tab-обход. Для предыдущего примера расставим табиндексы так, чтобы фокус сначала получили ссылки, потом текстарии, а остальные элементы оставим без атрибута:

<p>
    <a tabindex="1" href="#">Первая ссылка</a><br>
    <button>Первая кнопка</button><br>
    <input type="text" value="Первый текстбокс"><br>
    <textarea tabindex="3">Первая текстария</textarea><br>
    <select><option value="#">Первый селект</option></select><br>
</p>
<p>
    <a tabindex="2" href="#">Вторая ссылка</a><br>
    <button>Вторая кнопка</button><br>
    <input type="text" value="Второй текстбокс"><br>
    <textarea tabindex="4">Вторая текстария</textarea><br>
    <select><option value="#">Второй селект</option></select><br>
</p>

И, о чудо, даже неисправимые Опера и Сафари отрабатывают именно так, как задумывалось.

Tabindex & HTML5

В спецификации, описывающей отличия HTML4 от HTML5, в разделе New Attributes

указано, что tabindex будет глобальным атрибутом для всех HTML-элементов. Удобно, однако :-)

© Все права на данную статью принадлежат порталу webew.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в печатных изданиях допускается только с разрешения редакции.
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
NO USERPIC

pepelsbey

Не очень понятно какой это язык:

<BUTTON>Первая кнопка</BUTTON><br/>


…не то HTML (капс в тегах), не то XHTML (закрытый одиночный тег). Странно, в общем.
26.06.2008, 17:41
Ответить

bur

Привел к HTML4.01, а то действительно как-то странно.
26.06.2008, 17:50
Ответить
NO USERPIC

rgbeast

Что означает на практике, что tabindex станет применим ко всем элементам? Правильно ли я понимаю, что можно будет задать tabindex у div, tr, td, br? Изменят ли дефолтное поведение браузеры?
26.06.2008, 23:01
Ответить

bur

В спецификации нет данных о каких-то исключениях.
27.06.2008, 12:33
Ответить

1234ru

tabindex - круто!
Серьезно, очень удобно. Спасибо за просвещение :)
То, что не убивает нас, делает нас инвалидами.
27.06.2008, 03:54
Ответить

bur

Велкам :-)
27.06.2008, 12:33
Ответить
NO USERPIC

AlexNZ

Не стоит пугаться парного варианта тэга button, это вполне нормальный тег.
Вот что позваляет делать такая версия:
<button>Главная <span style="color:#FF0000;">красная</span> кнопка</button>
04.08.2008, 09:39
Ответить

1234ru

Всегда хотел знать, для чего нужна кнопка, сделанная через тег <button> в терминах HTTP.
По-другому этот вопрос звучит так: <button> - это только для JavaScript'а?
То, что не убивает нас, делает нас инвалидами.
05.08.2008, 21:42
Ответить
NO USERPIC

AlexNZ

Тег <button> (а так же <input type="button"/>, <input type="submit"/> и <input type="reset"/>) как и вообще любые тэги разметки HTML, не имеют никакого отношения к протоколу передачи данных HTTP.
Может показаться, что <input type="submit"/> вызывает передачу данных используя HTTP. Однако <input type="submit"/> вызывает всего лишь другое событие form: submit. Посмотрим это на практике.

<form id="form1" name="form1" method="post" action="" onsubmit="alert('Submited!'); return false;">
  <input type="submit" name="button" id="button" value="Submit" />
</form>

Тут мы перехватываем это событие и выдаем alert, затем отменяем передачу даных (используя код return false). Вспомните о bubbling. Кто не знаком, поясню: bubbling можно представить как стек событий, управление которым передается по очереди. Так вот, 'return false' обывает эту передачу управления.
Событие form: submit тоже не обращается к HTTP, хотя без кода 'return false' это вызовет передачу данных. Это сделает браузер, проведя прежде различные манипуляции (например откодирует данные в формат URLEncode, соберет строку для POST запроса и много еще чего), и потом только вызовет сервер.
Что же может дать тэг <button>. Он как и другие кнопки обладает обработчиками onclick, onfocus, onblur и т.д. Смотрим пример, как эмулировать этим тэгом Submit:

<form id="form1" name="form1" method="post" action="" onsubmit="if(confirm('Are you sure?')){this.submit }else{return false;}">
  <button onclick="document.getElementById('form1').submit()">Батон</button>
</form>

Тут мы используем, такой полезный код:
if(confirm('Are you sure?')){this.submit }else{return false;}

Т.е. вы спросили у пользователя его согласие, как это принято в параноидальной MS Windows (R).

М-да. Но тут есть подводный камень. Дело в том, что такой полезный код работает только при кнопке <input type="submit"/> (как в первом примере), а вот во втором примере случится следующее: FireFox и Opera покажут вопрос юзеру, но данные отправят при любом ответе, а IE так и вовсе не покажет вопроса. :-) Возрадуйтесь!

Как же это решить.
<script type="text/javascript">
function sendit()
{
    if(confirm('Are you sure?'))
    {
        var form1 = document.getElementById('form1');
        form1.action = 'http://myserver.me/myscript.name';
        form1.submit();
    }
}
</script>
<form id="form1" name="form1" method="post" action="javascript:void(0);">
  <button onclick="sendit()">Батон</button>
</form>

По порядку.
action="javascript:void(0);" - замыкаем форму на пустое действие. Для button onclick указываем функцию (разрастается код) sendit(), из которой спросим юзера, и если "да", то назначим форме нужный нам URL и отправим данные.
Строку form1.action = 'http://myserver.me/myscript.name'; можно написать так: form1.action = '';
это просто отправит данные на текущий URL (вы ведь могли "нарисовать" форму из скрипта, который её данные и обработает).

<button> - это только для JavaScript'а? Нет.
Вы можете обработать события возникающие в тэге <button> другими средствами. Например IE может обрабатывать события HTML на языке visualbasic (но только IE). Вы можете написать плагин к браузеру используя его API. Еще есть язык Java, да и ActionScript (из Flash) теперь способен на многое. Это не весь список.
Более того, мы ведь говорим об HTML, а не о браузерах, так что можно написать свою программу поддерживающую стандарт HTML, со своим макроязыком. Короче не стоит замыкаться :-)

Ну вот, хотел отделаться только первым предложением... :-)
06.08.2008, 07:08
Ответить

bur

В Вашем комментарии много ошибочных утверждений. Начнем по порядку.

Подозреваю, что камрад 1234ru перепутал и написал HTTP вместо HTML, поэтому дам ответ на его вопрос, как если бы он звучал о HTML. Так вот, существенное отличие тега <button> от <input type="button" /> состоит в том, что в инпут - это одиночный тег и текст кнопки можно задать только атрибутом value. А <button> - это контейнер, в который можно помещать HTML-код. Следующий пример это демонстрирует (Valid XHTML 1.0 Strict!):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang='ru-RU'>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Test</title>
    <style type="text/css">button {border:0; background:#FFF;}</style>
</head>
<body>
<div>
    <form action="#" method="get">
        <p>
            <button type="submit">
                <img src="http://webew.ru/i/logo.gif" width="327" height="86" alt=""/>
                <br />
                <strong>STRONG</strong>
                <br />
                <em>EM</em>
            </button>
        </p>
    </form>
</div>
</body>
</html>


Также, в моем примере можно заметить у тега <button> атрибут type="submit", который доказывает, что onclick вешать на button для сабмита формы совершенно не обязательно и <input type="submit" /> - это не единственная кнопка для сабмита.

----------------------------------

Теперь о событиях. Зря вы упомянули bubbling. return false - просто вернет текущему обработчику ложное значение, но не прекратит вплывание события. Для того, чтобы прекратить всплывание используется свойство cancelBubble объекта event. Продемонстрирую:

<div onclick="alert('Div 1');">
    <a onclick="alert('Link1'); return false;" href="">Link1</a>
</div>

<div onclick="alert('Div 2');">
    <a onclick="alert('Link2'); evt = event || window.event; evt.cancelBubble = true; return false;" href="">Link2</a>
</div>


Во втором примере мы не увидим alert('Div 2').

При сабмите о всплывании вобще лучше не упоминать, т.к. кроме тега form никто не генерирует это событие.

Итого, Ваш пример наиболее правильно переделать вот так:

<form id="form1" name="form1" method="post" action="#" onsubmit="if(!confirm('Are you sure?')) return false;">
  <button type="submit">Батон</button>
</form>
06.08.2008, 12:14
Ответить
NO USERPIC

AlexNZ

Да, это правильно.
Отдельно спасибо, насчет cancelBubble
07.08.2008, 08:53
Ответить
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
© 2008—2017 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100