Поступайте правильно — как использовать HTML, CSS и JavaScript доступным способом

Кристиан Хейлман (Christian Heilman) | 5 мая 2010 г.

В этой статье мы обсудим некоторые ошибочные представления о доступности веб-дизайна и покажем, как можно создавать динамический поиск в Интернете, не жертвуя простотой использования или универсальным доступом к сайту.

Существует множество мифов о взаимосвязи специальных возможностей и современной веб-разработки. Годами я сражался с предубеждением о вредности JavaScript и невозможности его использования в среде, которая "должна быть доступной".

Во-первых, сама точка зрения, что приходится "делать" что-либо доступным, является неправильной. Универсальный доступ должен быть заложен в проект продукта, а не прикрепляться на финальном этапе. Это приводит к появлению, казалось бы, доступных решений, которые удовлетворяют законодательным требованиям и правилам, но в действительности являются ненужной тратой времени и денег — делайте все правильно с первого раза, перепроектирование гораздо более затратно, чем создание новых продуктов.

Довольно печально, что есть множество людей, обращающих внимание на юридические аспекты специальных возможностей, а не на работу с разработчиками, что, во-первых, приводит к множеству плохих примеров, которые лишь на первый взгляд кажутся правильными, а во-вторых, вызывает довольно сильную отрицательную реакцию сообщества создателей скриптов и разработчиков. Многие заявляют, что специальные возможности задерживают нас на пути разработки прекрасных веб-продуктов. Это полная ерунда. Интернет создан, чтобы облегчить жизнь людей независимо от их возможностей. Как только вы забываете, что это ваши пользователи, требования которых следует удовлетворять, и вместо этого пытаетесь использовать технологию ради технологии, вам не следует работать для других, поскольку то, что вы делаете, неправильно. У нас есть репозитории вдохновляющих образцов и портфели технологий — развлекайтесь там, но не усложняйте людям использование Интернета. Он слишком важен как средство массовой информации, и не следует его портить.

Множество аргументов не может объяснить главную идею специальных возможностей: они не для обслуживания особых случаев — они для удаления барьеров при входе.

Недоступные решения являются результатом нескольких ошибок, которые делают разработчики:

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

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

Взгляд на специальные возможности с высоты птичьего полета

Если вы освободились от приверженности к одному из двух лагерей (разработчиков или защитников специальных возможностей) при обсуждении специальных возможностей, то вы обнаружите, что существует несколько причин, по которым построение доступных продуктов не просто "полезно", а действительно необходимо.

  • Наша аудитория становится старше с каждым годом — если я покупаю что-нибудь в сети, мне нравится удобство, но я почти никогда не бываю дома при доставке. Более старшие люди, будучи менее мобильными, не имеют такой проблемы, и у них должна быть возможность покупать продукты в сети.
  • Мобильные компьютерные среды на подъеме — вместо сидения дома перед громоздкими настольными компьютерами мы теперь можем использовать смартфоны, ноутбуки, нетбуки и многие другие современные устройства. Все они имеют небольшие экраны и различные средства их использования — с помощью клавиатуры и мыши, сенсорных экранов, шаровых джойстиков, стилусов и маленьких клавиатур.
  • Люди пытаются искать и совместно использовать разные вещи в Интернете — если поисковая система не может индексировать какой-либо контент, пользователи не смогут найти его. Если я не могу отправить ваши ссылки моим друзьям в Facebook, я не смогу прорекламировать ваш контент.
  • Существует множество средств, помогающих людям приобрести собственный опыт работы в Интернете — например, если я не говорю на каком-либо языке, я могу перевести страницу с помощью переводчика Google Translate. Если весь текст представлен в виде изображений без альтернативного текста, то мне не удастся сделать это.

Это означает, что процесс создания доступных продуктов в основном сводится к нескольким моментам.

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

HTML, CSS и JavaScript — что и с чем делать?

HTML, CSS и JavaScript — это технологии, которые работают в браузере или на стороне клиента (т.е. клиент не обязательно должен быть браузером). Это означает следующее.

  • Простая разработка и отладка — не нужно запускать объекты на сервере, просто сохраните их на жестком диске и откройте в браузере.
  • Неизвестно, где эти технологии выполняются — браузер, его конфигурация, операционная система, спецификация оборудования, тип устройства могут постоянно изменяться, и нет способов указать, что именно следует использовать.
  • Эти технологии имеют очень облегченную конструкцию — при их использовании для тяжелых задач преобразования не следует удивляться замедлению работы.
  • Область действия сильно ограничена — по сравнению с "высокоуровневыми" языками программирования с этими средствами можно сделать не так много (за исключением JavaScript).

Каждая из этих технологий предназначена для выполнения определенной работы.

  • HTML предоставляет структуру и смысл контента. Он не предназначен для разработки, поэтому не нужно использовать разрывы строк и пустые параграфы для разметки приложения — это делают CSS. HTML должен быть логикой задания: заголовок — это <h1>, а не <div class="head"></div>. HTML также должен быть основным интерактивным элементом для задания: кнопка будет выполнять функциональность JavaScript, а ссылка без указания адреса перехода — нет по умолчанию.
  • Каскадные таблицы стилей CSS задают внешний вид. Все объекты, являющиеся чисто визуальными, должны задаваться в CSS. Сюда могут входить эффекты наведения, а в некоторых браузерах даже анимация и преобразования. Однако здравый смысл подсказывает, что контент не должен быть связан с CSS. Формируйте его в HTML, чтобы его можно было прочитать без CSS, например на старых устройствах Blackberry, а затем создайте другой его вид с помощью CSS.
  • JavaScript добавляет в статический документ поведение и функциональность — все, что должно реагировать на действия пользователя в этой технологии.

Для создания понятных, простых в обслуживании и доступных веб-продуктов эти слои должны оставаться разделенными. Это означает, что следует не приделывать к своему HTML встроенные обработчики событий типа <body onload="myscript()">, а использовать обработку событий.

Достаточно разговоров, давайте построим форму поиска

Итак, давайте попробуем построить форму поиска вместе. Первое, о чем следует подумать, это HTML, который будет отображаться. Независимо от того, является ли этот HTML жестко заданным или созданным JavaScript, в результате браузер или другая используемая технология должны понимать созданный HTML. Создадим для формы следующий HTML.

<form action="http://www.bing.com/search" id="bingform">
  <div>
    <label for="q">Search Bing:</label>
    <input type="text" name="q" id="q">
    <input type="submit" value="Go!" id="send">
  </div>
</form>
<div id="results"></div>

Это будет работать независимо от технологии. Мы указываем в форме страницу результатов поиска Bing и передаем ей параметр q в качестве условия поиска. Мы используем метку, чтобы привязать текст Search Bing к полю формы. Это очень важно, поскольку без метки пользователь программы чтения с экрана не будет иметь сведений о том, что это поле формы существует. Это также означает, что можно щелкнуть этот текст, чтобы выделить поле и начать его изменять. Это очень удобно при использовании флажков или переключателей, поскольку в них предусмотрено мало места для щелчка, а при наличии метки достаточно щелкнуть текст или коснуться его (на сенсорном экране). Метки подключаются с помощью свойства id, а не name. Это объясняется тем, что, например, в группе переключателей используется одно и то же имя, а переключатели необходимо различать.

Мы также добавляем раздел DIV, который будет содержать результат поиска, и несколько идентификаторов, чтобы разрешить доступ посредством JavaScript и задание стилей с помощью CSS.

И это фактически  все, что будет написано в качестве жестко заданного HTML. Причина в том, что никогда не следует строить HTML, которому для работы требуется JavaScript, поскольку в случае недоступности JavaScript на экране будут объекты, которые ничего не будут делать при их активации пользователем. Это одно из золотых правил доступной веб-разработки: не обещайте того, что не сможете обеспечить!

Поскольку остальная функциональность работает только при доступности JavaScript, мы создадим ее в JavaScript.

Легкий путь — CSS

Мы могли бы создать собственное решение в рамках CSS и задания стилей, но зачем проходить через трудности тестирования и понимания, как все виды браузеров перестают работать, когда можно прицепить решение, которое уже было кем-то создано?

В данном случае для создания структуры HTML я использовал инфраструктуру CSS сеток YUI и в частности веб-интерфейс построения сеток Grids Builder. Этот способ имеет несколько преимуществ.

  • Я знаю, что он работает во всех видах браузеров, поскольку построен на основе дифференцированной YUI поддержки браузеров и уже протестирован для меня.
  • CSS размещены Yahoo в быстрой глобально распределенной серверной сети.
  • Средство Grids Builder добавляет в документ ориентиры ARIA, которые делают возможным простой доступ для программ чтения с экрана.
  • Благодаря базовому модулю CSS я уже имею привлекательное и удобочитаемое определение шрифтов, с которым можно работать дальше.

В сущности, я ленив и предпочитаю использовать то, что уже работает. При использовании сеток все, что мне пришлось сделать, чтобы документ выглядел так, как сейчас — это добавить в документ следующее.

body,html{background:#999;color:#000;}
#doc{background:#fff;border:1em solid #fff;}
form{background:#ccc;padding:.5em;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;}
h2{margin:0;padding:.5em 0;color:#393;}
h3{margin:0;padding:.5em 0;color:#036;}
a:link{color:#369;}
a:visited{color:#999;}
a:hover{color:#69c;}
a:active{color:#69c;}
#related{background:#69c;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;}
#related h3{color:#000;padding:.5em;}
#related a{color:#000;}
.error, .error h2{color:#c00;}

Всего несколько цветов и несколько скругленных углов с помощью свойств CSS3 вместо работы со всеми видами несовершенных браузеров и необходимости подгонки изображений — и это все, что потребовалось, добро пожаловать в 2010 год.

Получение доступа к данным Bing

Теперь, чтобы отображать наши собственные результаты поиска, необходимо получить откуда-нибудь данные. Здесь вступают в дело интерфейсы API (интерфейсы прикладных программ). В настоящее время многие компании понимают преимущества предоставления своих данных в форматах для многократного использования, таким образом наделяя нас, разработчиков, полномочиями для построения отличного материала на их основе. В случае Bing мы имеет центр разработки Bing, куда я зашел, чтобы зарегистрироваться для получения ключа разработчика. Затем я продолжил работу, чтобы найти данные в подходящем для наших целей формате (это формат JSON) и извлечь демонстрационный код для нескольких параметров SourceType. Это дает мне понимание, как я могу получить доступ к API. Например, я могу выполнить поиск в Интернете с условием поиска "Mighty Mighty Bosstones" и получить данные, возвращенные в функции с именем bing:

http://api.bing.net/json.aspx?
  AppId=B59F3913692A46D75ED39BA8F472DF267E24B611
  &Query=mighty+mighty+bosstones
  &Version=2.0
  &Sources=Web+RelatedSearch
  &JsonType=callback
  &JsonCallback=bing

Оставалось только написать скрипт, извлекающий эти данные из API. Всякий раз при создании подобного решения рекомендуется создавать список требуемой функциональности, подобный приведенному ниже.

  • Пользователи должны вводить условие поиска и иметь возможность отправлять форму любым доступным способом — путем нажатия кнопки отправки или клавиши ВВОД.
  • Чтобы исключить путаницу, должен быть предусмотрен индикатор того, что что-то происходит, когда данные загружаются.
  • После загрузки данных требуется отобразить результаты и связанные варианты поиска в двух столбцах, а также сбросить индикатор загрузки.
  • Если пользователь нажимает какую-либо из ссылок связанных вариантов поиска, должен инициироваться новый поиск.

Далее приводится все, что было предпринято — в плане JavaScript — чтобы обеспечить эту функциональность.

var bisearch = function(){

  var form,resultscontainer,send,q;

  var appid = 'B59F3913692A46D75ED39BA8F472DF267E24B611';

  function init(){

    form = document.getElementById('bingform');

    send = document.getElementById('send');

    q = document.getElementById('q');

    resultscontainer = document.getElementById('results');

    resultscontainer.addEventListener('click',bingsearch.related,false);

    if(form && resultscontainer && send && q){

      form.addEventListener('submit',bingsearch.get,false);

    }

  }



  function get(e){

    e.preventDefault();

    send.value = 'Loading...';

    var searchterm = q.value;

    var url = 'http://api.bing.net/json.aspx?'+

              'AppId=' + appid +

              '&Query=' + encodeURIComponent(searchterm) + 

              '&Version=2.0' + 

              '&Sources=Web+RelatedSearch' + 

              '&JsonType=callback' + 

              '&JsonCallback=bingsearch.success';

    var s = document.createElement('script');

    s.setAttribute('src',url);

    s.setAttribute('id','leech');

    document.getElementsByTagName('head')[0].appendChild(s);

  };



  function bingresults(o){

    send.value = 'Go!';

    var out = '';

    var old = document.getElementById('leech');

    if(old){

      old.parentNode.removeChild(old);

    }

    if(undefined === o.SearchResponse.Errors){

      var out = '<h2>Results:</h2><div class="yui-gc">' +

                '<div class="yui-u first">' +

                renderWeb(o) + 

                '</div><div class="yui-u" id="related">'+

                renderRelated(o) + 

                '</div></div>';

    } else {

      out = '<div class="error"><h2>Error</h2>' +

            '<p>' + o.SearchResponse.Errors[0].Message + '</p>' +

            '</div>';

    }

    resultscontainer.innerHTML = out;

    if(undefined !== resultscontainer.getElementsByTagName('a')[0]){

      resultscontainer.getElementsByTagName('a')[0].focus();

    }

  }



  function renderWeb(o){

    var out = '';

    var results = o.SearchResponse.Web.Results;

    if(undefined !== results){

      var all = results.length;

      out += '<h3>Web Results:</h3><ol>';

      for(var i=0;i<all;i++){

        out += '<li><h4>' +

               '<a href="' + results[i].Url + '">' + 

               results[i].Title + 

               '</a>'+

               '</h4><p>' + results[i].Description + 

               ' <span>(' + results[i].DisplayUrl + ')</span></p></li>';

      }

      out += '</ol>';

    }

    return out;

  };



  function renderRelated(o){

    var out = '';

    var related = o.SearchResponse.RelatedSearch.Results;

    if(undefined !== related){

      var all = related.length;

      out += '<h3>Related Searches:</h3><ul>';

      for(var i=0;i<all;i++){

        out += '<li>' + 

               '<a href="' + related[i].Url + '">' + 

               related[i].Title + 

               '</a>'+

               '</li>';

      }

      out += '</ul>';

    } 

    return out;

  };



  function callRelatedSearch(e){

    var t = e.target;

    var findstring = 'http://www.bing.com/search?q=';

    if(t.nodeName.toLowerCase() === 'a'){

      if(t.getAttribute('href').indexOf(findstring) !== -1){

        e.preventDefault();

        q.value = t.getAttribute('href').replace(findstring,'');

        get(e);

      }

    }

  };

  return{get:get,success:bingresults,init:init,related:callRelatedSearch}

}();

bingsearch.init();

Давайте пройдем по этому коду и объясним, что он делает и почему.

Чтобы написать понятный скрипт, который не создает глобальные переменные, могущие пересекаться с другими скриптами, я использую открытый шаблон модуля JavaScript, позволяющий сохранить частные и общие переменные и методы. Это чистый вопрос кода JavaScript, и не нужно ничего делать со специальными возможностями, поэтому не будем на этом останавливаться. Достаточно сказать, что к этому имеет отношение весь раздел var bisearch = function(){}();.

Давайте рассмотрим первую часть кода.

var bisearch = function(){

  var form,resultscontainer,send,q;

  var appid = 'B59F3913692A46D75ED39BA8F472DF267E24B611';

  function init(){

    form = document.getElementById('bingform');

    send = document.getElementById('send');

    q = document.getElementById('q');

    resultscontainer = document.getElementById('results');

    if(form && resultscontainer && send && q){

            resultscontainer.addEventListener('click',bingsearch.related,false);

      form.addEventListener('submit',bingsearch.get,false);

    }

  };

Мы определили переменные, которые должны быть доступны из всех методов в решении — форму, контейнер для результата, кнопку отправки (работающую как индикатор загрузки) и поле, содержащее условие поиска.

Метод init() вызывается немедленно после создания браузером модуля и начинает действовать. Он проверяет, существуют ли все необходимые элементы HTML, и если существуют, то добавляет к ним обработчики событий.

  • Форма имеет обработчик submit, который вызывает метод get() при отправке формы, независимо от того, каким образом пользователь это делает. Множество форм с использованием технологии AJAX, которые можно видеть в Интернете, используют вместо этого обработчик нажатия кнопки отправки, но это не работает, если пользователь хочет только наживать клавишу ВВОД на клавиатуре, как я.
  • Мы назначаем единственный обработчик события нажатия всему разделу результатов на странице — таким образом не придется беспокоиться о динамически изменяющемся контенте. Если мы назначим по обработчику каждой ссылке в соответствующем разделе, нам придется постоянно добавлять и удалять обработчики нажатия, что ужасно для памяти. Такой прием называется делегированием событий и исключительно удобен.
function get(e){

    e.preventDefault();

    send.value = 'Loading...';

    var searchterm = q.value;

    var url = 'http://api.bing.net/json.aspx?'+

              'AppId=' + appid +

              '&Query=' + encodeURIComponent(searchterm) + 

              '&Version=2.0' + 

              '&Sources=Web+RelatedSearch' + 

              '&JsonType=callback' + 

              '&JsonCallback=bingsearch.success';

    var s = document.createElement('script');

    s.setAttribute('src',url);

    s.setAttribute('id','leech');

    document.getElementsByTagName('head')[0].appendChild(s);

  };

Обработчик события отправки формы будет получать метод get(). Первое, что он делает, это вызывает preventDefault(), чтобы убедиться, что форма не отправлена, и пользователь переходит на сайт Bing. Затем он изменяет текст кнопки поиска на "Loading...", чтобы сообщить пользователю, что что-то происходит, чтобы он не ждал проблем. Мы составляем URL-адрес, который получает данные из API Bing, и создаем новый элемент script, чтобы получить данные. Добавление его в заголовок запускает объекты. После того как API получит данные и отправит их нам обратно, функция bingresults() вызывается автоматически — в этом прелесть JSON-P.

Обратите внимание, что мы изменяем значение кнопки, чтобы сообщить пользователю, что происходит. Этот способ имеет несколько преимуществ.

  • Сведения передаются в то место, где произошло взаимодействие — если, например, пользователь увеличил масштаб этого раздела на смартфоне или с помощью экранной лупы, то он в курсе, что происходит, и ему не требуется снова уменьшать раздел, чтобы найти сообщение о загрузке где-нибудь вверху экрана.
  • Изменение значения формы автоматически заставляет программы чтения с экрана обновить свои копии сайта, что означает, что мы не ставим в тупик даже людей с серьезными проблемами зрения.
function bingresults(o){

    send.value = 'Go!';

    var out = '';

    var old = document.getElementById('leech');

    if(old){

      old.parentNode.removeChild(old);

    }

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

if(undefined === o.SearchResponse.Errors){

      var out = '<h2>Results:</h2><div class="yui-gc">' +

                '<div class="yui-u first">' +

                renderWeb(o) + 

                '</div><div class="yui-u" id="related">'+

                renderRelated(o) + 

                '</div></div>';

    } else {

Если API не возвращает никакие ошибки, мы можем показать результаты. Обычно я стремлюсь разделить визуализацию данных API и HTML, который должен быть вокруг этих данных. Это один из таких случаев. За заголовком следует конструкция YUI grids, а результаты из Интернета и соответствующие условия получают собственные функции визуализации. Этот небольшой ряд тегов DIV с правильными классами гарантирует отображение результатов поиска и связанных вариантов поиска в столбцах рядом друг с другом вместо отображения одного после другого. Если вы хотите задать, чтобы таблицы стилей CSS делали это сами, и проверить это во всех видах браузеров, то это, конечно, ваше право.

Использование реальных заголовков от <h1> до <h6> означает, что они не только отображаются правильным образом, но также создают структуру документа и помогают пользователям программ чтения с экрана быстро переходить от заголовка к заголовку.

out = '<div class="error"><h2>Error</h2>' +

            '<p>' + o.SearchResponse.Errors[0].Message + '</p>' +

            '</div>';

    }

Если API возвращает ошибку, то мы ее отображаем вместо результатов — возврат в DIV с помощью класса error дает нам возможность задать для нее другой стиль. Это замечательная особенность Bing API — другие могут возвращать вместо ошибки пустые массивы данных, что сильно усложняет жизнь.

resultscontainer.innerHTML = out;

    if(undefined !== resultscontainer.getElementsByTagName('a')[0]){

      resultscontainer.getElementsByTagName('a')[0].focus();

    }

  }

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

function renderWeb(o){

    var out = '';

    var results = o.SearchResponse.Web.Results;

    if(undefined !== results){

      var all = results.length;

      out += '<h3>Web Results:</h3><ol>';

      for(var i=0;i<all;i++){

        out += '<li><h4>' +

               '<a href="' + results[i].Url + '">' + 

               results[i].Title + 

               '</a>'+

               '</h4><p>' + results[i].Description + 

               ' <span>(' + results[i].DisplayUrl + ')</span></p></li>';

      }

      out += '</ol>';

    }

    return out;

  };

Никакого волшебства, только структура HTML. Результаты поиска возвращаются по порядку, поскольку упорядоченный список — это правильная конструкция для использования. Теги SPAN вокруг отображаемого URL-адреса позволяют разработчикам сделать с ним что-нибудь особенное, и опять реальные ссылки и заголовки позволяют разумные переходы с помощью клавиатуры.

function renderRelated(o){

    var out = '';

    var related = o.SearchResponse.RelatedSearch.Results;

    if(undefined !== related){

      var all = related.length;

      out += '<h3>Related Searches:</h3><ul>';

      for(var i=0;i<all;i++){

        out += '<li>' + 

               '<a href="' + related[i].Url + '">' + 

               related[i].Title + 

               '</a>'+

               '</li>';

      }

      out += '</ul>';

    } 

    return out;

  };

Нет необходимости упорядочивать результаты для условий связанных вариантов поиска, поскольку они более произвольные. Следовательно, UL будет достаточно.

function callRelatedSearch(e){

    var t = e.target;

    var findstring = 'http://www.bing.com/search?q=';

    if(t.nodeName.toLowerCase() === 'a'){

      if(t.getAttribute('href').indexOf(findstring) !== -1){

        e.preventDefault();

        q.value = t.getAttribute('href').replace(findstring,'');

        get(e);

      }

    }

  };

Это обработчик события нажатия в контейнере результатов. Делегирование событий работает как события нажатия в элементе, которые происходят не только в этом элементе, но и во всех его дочерних элементах. Чтобы найти, какие элементы были нажаты, можно прочитать свойство target события.

Здесь мы хотим знать, был ли нажатый элемент ссылкой, или это был один из элементов списка условий связанных вариантов поиска. Чтобы это узнать, можно проверить, является ли nodeName "a" (используя toLowerCase(), поскольку разные браузеры по-разному сообщают это), и что свойство href содержит URL-адрес Bing http://www.bing.com/search?q. Если оба условия удовлетворяются, то останавливается обычная обработка события нажатия, а вместо нее начинается чтение условия поиска из ссылки и установка его в качестве значения поля формы перед вызовом метода get(). В сущности это моделирует ввод пользователем этих сведений и отправку формы. Автоматическая отправка формы с помощью form.submit() не рекомендуется, поскольку может создать помехи специальным возможностям.

return{get:get,success:bingresults,init:init,related:callRelatedSearch}

}();

bingsearch.init();

В оставшейся части выполняется возврат методов, доступ к которым осуществляется извне или из обработчиков событий, и вызывается метод init(). И мы закончили — у нас есть динамический интерфейс поиска, доступный и не обещающий больше того, что может предоставить. Без JavaScript выполняется переход на сайт Bing, с помощью JavaScript пользователям предоставляется доступ к данным, в том числе с помощью клавиатур и устройств с маленькими экранами.

В этом не так много волшебства

Как можно видеть, большую часть можно сделать, сохраняя простоту. Некоторые приемы взаимодействия могут быть незнакомы, но это не высшая математика и не нейрохирургия. Главный прием состоит в том, чтобы прекратить перефразировать идеи прошлого и учитывать варианты (в том числе крайние) взаимодействия пользователей с системами. Приведем некоторые применявшиеся здесь простые приемы, до начала использования которых в целях обеспечения доступности продуктов был пройден длинный путь.

  • Использование правильного HTML для задания — списки, заголовки и ссылки преодолели долгий путь, прежде чем их начали использовать правильно, и хороший дизайнер может придавать им любой требуемый вид. Они представляют чудеса взаимодействия — пользователи программ чтения с экрана могут быстро перепрыгивать от заголовка к заголовку, и любой пользователь может нажимать ссылки, щелкать их правой кнопкой мыши, сохранять и перетаскивать их, в сущности делать с ними все, что угодно. Браузеры предоставляют все это нам свободно, и уму непостижимо, почему люди продолжают использовать для нажатий теги SPAN.
  • Создание всего, что зависит от скриптов, с помощью скриптов — это обеспечивает множество способов. Вы не обещаете пользователям того, что не работает и мешает им, и к тому же имеется очень четкий указатель, что кое-что оказалось неправильным, при отладке кода. Это аналогично серверу с PHP и выключенными отчетами об ошибках в браузере — если ничего не отображается, значит есть ошибка.
  • Предоставление отзыва при возникновении взаимодействия — изменение кнопки при ее нажатии и сообщение пользователю, что происходит, гарантирует, что никто не застрянет даже в чрезвычайно масштабированном интерфейсе.
  • Перемещение фокуса при завершении действия — направляйте пользователей в то, что для них загружено, чтобы они не задумывались, куда идти дальше.
  • Разделение вопросов и технологий — эффективно используйте обработку событий и сохраняйте представление вне HTML, и вы построите продукты, которые не только будут лучше работать, но также будут гораздо более просты в обслуживании.

Последнее, что следует учитывать, это постоянная эволюция мира веб-разработки. При использовании решения, найденного в Интернете, проверьте его дату и выполните некоторые исследования, прежде чем применить его. Многие приемы и идеи, особенно в области специальных возможностей, были прекрасными в прошлом, но теперь устарели и даже могут оказаться вредными.

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

Взгляните на демонстрацию динамического поиска Bing.