Веб-программирование
0,0
рейтинг
27 октября 2015 в 10:43

Разработка → <input> Я ♥ тебя, но ты меня обламываешь перевод


Привет, представляю твоему вниманию перевод статьи Моники Динкулеску '<input> I ♡ you, but you're bringing me down'. Художественный перевод с английского не является моей основной специализацией, поэтому в тексте возможны неточности. Правки призываю отправлять личным сообщением, а если есть что сказать, велкам в комментарии. Отдельное спасибо @Kt за редакторские правки. Приятного чтения.


Некоторые люди делают мебель. Некоторые люди вяжут. Некоторые люди имеют хобби, которые никак не пересекаются с HTML спецификациям из 90-х. Но я не из таких. И, вот история о том, как <input> стал той хренью, которой он является, и почему его надо сжечь


Ранние годы



1995 был клевым годом. Друзья, Скорая Помощь, Зена по телеку. TLC занимали верхушки чартов с хитом "Waterfalls". С браузерами было нормуль, потому что HTML было все очень нормуль. У нас были Mosaic, Netscape и IE1, а при утверждении спеков HTML 2, наконец, выкроили время для стандартизации форм. Девяносто пятый был годом рождения <input>, и теперь, когда он достаточно взрослый, чтобы покупать в магазине алкоголь, нам нужно поговорить.

Изначально <input> пришел к нам в восьми видах: text, password, checkbox, radio, image, hidden, submit и reset, а так же с отдельном последующим RFC, file.

Подожди, ты сказал image? Да, давай я расскажу о нем.

<input type='image' src='cat.png'> выглядит как обычное изображение, но на самом деле это изображение-кнопка, которая при нажатии также передает x и y координаты того места, в котором на нее нажали. При этом, если не указано изображение для атрибута src, «изображение-кнопка» станет кнопкой с надписью «Submit». А если дело будет происходить Firefox, то текст кнопки изменится на «Submit Query» и кнопка будет выглядеть как обычный текст. А если открыть пример в IE, в этом случае ты не увидишь ничего.



А вот вопрос, достойный вашего местного клуба «Что? Где? Когда?», если тип элемента = 'file', то текст который будет отображаться на месте этого элемента, когда не выбран ни один из файлов: «No file chosen», «no file selected», «No file selected», и просто пустой текстовый блок в Chrome, Safari, Firefox и IE соответственно.

Ладно, хорошо.


А вот, тирада в честь <textarea>



Я всегда думала, что input и textarea были придуманы в разное время, и это объясняет, почему они так безумно отличаются. Это в целом так, input был частью браузера Mosaic по крайней мере с 1993, и он был, по сути, исправленной имплементацией ISINDEX. Тем не менее, официально, они оба были детьми HTML2, который решил, что <input> это самозакрывающийся тег в котором значение тега помещаяется в атрибут value, в то время как для тега <textarea> нужен закрывающий тег, а его значение хранится в его содержимом, даже если они оба тега используются только для хранения простого текста, который кто-то ввел:

<input value="batman">
<textarea rows="1">batman</textarea>


Небольшой апдейт: некто подсказывает, что <textarea> должен поддерживать ввод многострочного текста, а символы переноса строки не допускаются внутри значений атрибутов, вот почему мы должны использовать содержимое тега. А это имеет смысл!


1995-2011, средние года



В 1999 году, в HTML4 добавили только один новый тип тега = 'button'. Что мне в этом особенно нравится, что без каких-либо дополнительных пользовательских стилей, <input type='button'> и <input type='button' value='Submit'> помещенные в одну и ту же строку, не совпадают по вертикали в Chrome/Safari/Edge.




Все становится еще хуже



Позже, в 2011 году, спецификация HTML5 добавила тысячи новых типов для <input>. И на сегодняшний день, большинство из них не реализовано. Вот краткий перечень неработающих фич: type=color работает только в Firefox/Chrome, date/time работает только в Chrome/EDGE/iOS, и все, что работает в Chrome работает в Opera. Вот сравнение всех доступных типов input'ов на сегодня, так что ты можешь сравнить и поплакать наедине.

Давай поговорим о некоторых интересных фактах.

<input type='search'> имеет странные случайно выбранные отступы между текстом и границей, а так же популярные в середине 2000-х закругленные углы, внешний вид которых отличается от браузера к браузеру и от которых почти невозможно избавиться.



А если твоему браузеру повезло поддерживать тип = 'date', не волнуйся о стилизации элемента выбора даты – у нас есть 8 чудесных ::webkit псевдо-селекторов, которые помогут настроить стиль текстового блока, но ни одного для стилизации выпадающего блока выбора даты! В любом случае, знай, CSS вреден для твоего здоровья.


И в тот момент, когда ты подумал, что хуже уже не будет: JavaScript



Видите ли, я могу оправдать причуды CSS. Я работала над браузером Chrome в течение 2 лет, сейчас я работаю с командой Blink, я понимаю, что мы все пишем разные рендеры и что для них свойственны свои собственные баги CSS. Тем не менее, <input> API даже нельзя назвать странным – он буквально как банка пауков, и в тот момент, когда ты открываешь банку, уже слишком поздно. Ты весь в пауках. Даже твоя кошка стала пауком. Лучше сжечь тут всё.

Начиная с 1995 года, элементы формы с типами radio и checkbox имеет дополнительный атрибут 'checked' который позволяет определить состояние элемента. Поскольку HTMLInputElement это HTMLInputElement и это HTMLInputElement, выходит, что во всех остальных типах элемента <input> этот атрибут также присутствует, но его просто игнорируют. Да, даже если это и не имеет смысла, это восхитительно:

var textInput = document.querySelector('input[type="text"]');
console.log(textInput.checked);  // prints false.
textInput.checked = true;
console.log(textInput.checked);  // prints true.
// did not open the hellmouth.

Круто. Круто-круто-круто!

<input> содержит текст, текст может быть выделен, а в прототипе HTMLInputElement определенны два свойства: selectionStart и selectionEnd – два числа которые определяют диапазон выбора. Таким образом, ты можешь сделать:

document.querySelector('input').selectionStart += 2;


И продвинуться на 2 символа вперед от начала выделения текста. Мега-заурядное исключение из этого факта то, что selectionStart – атрибут который доступен только для input'ов c типами text, url и password. А еще он доступен для вызова (это даже не настраивается) бросая исключение так же для всех остальных типов элемента :

Uncaught DOMException: Failed to read the 'selectionStart'
property from 'HTMLInputElement': The input elements type ('number')
does not support selection.

Даже если я могу вручную выделить этот текст:



Вот и получается, что в некоторых случаях свойства могут реально использоваться, а в других случаях они покажут свой «волчий оскал». Ве-ли-ко-леп-но. Именно такого постоянства я ищу в API.




К сожалению, это еще не все. Я уверена, что это еще не все. Дело в том, у разработчиков браузеров был 21 год, чтобы починить отображение input'ов, но им даже не удалось договориться о том, как писать «you haven't picked a file».

Теперь представь будущее, в котором веб-компоненты поддерживаются нативно, кто угодно может написать свой <better-input> – реальный инкапсулированный DOM элемент, а не просто лапшу из DIV'ов. Представь, как ты используешь этот <better-input>, что его реализация не отличается от браузера к браузеру, он выглядит одинаково везде, и что, вероятно, он знает, как испечь тебе вишневый торт. Только представь.
Перевод: Monica Dinculescu
AreD @AreD
карма
27,8
рейтинг 0,0
Веб-программирование
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (55)

  • +6
    Когда не знаешь ещё, в какую сторону будет развиваться технология, придумать правильный стандарт, правильный API очень сложно. Удачная абстракция быстро стала популярной, стала обрастать фичами, не вписывающимися в первоначальный дизайн, и вот результат. Своего рода проклятие первопроходцев.
    • +1
      Да, но какие то легаси проблемы, например, решаются. Те же флекс блоки позволяют вертикальное позиционирование делать. А тут казалось бы простая вещь – стандартизация и возможность широкой настройки стилей элементов форм. Веб состоит из дизайна/верстки и пользовательского взаимодействия с сайтом. Вот когда верстаешь, делаешь красоту и душа прям радуется, вот тебе веб инспектор, вот тебе и инструменты для оптимизации CSS, вот тебе удобные медиа-запросы. Но как только ты доходишь до пользовательского взаимодействия – боль.
  • +2
    Как-то установил на проекте тип email для всех полей, предназначенных для ввода почты. Сначала радовался (автоматическое добавление нужных символов на клавиатурах мобильных устройств), а потом вернул тип text. Почему? Потому что если случайно добавить лишний пробел (перед адресом или после), то браузеры считают значение неверным и не дают отправить форму. А ведь это происходит очень часто и вводит пользователей в заблуждение (особенно при copy-paste). В итоге, бесполезный тип без костылей на JavaScript, хотя при отправке достаточно было бы сделать trim. Возникает еще проблема с доступом к value из скрипта, но могли бы что-нибудь придумать.
    • +1
      Возникает еще проблема с доступом к value из скрипта, но могли бы что-нибудь придумать.

      А о какой проблеме идет речь?
      • 0
        Я имею в виду, что если делать trim при отправке формы, то как быть, например, в случае ajax (когда скрипт сам берет значение из поля)? Как быть с псевдоклассами валидации? Т. е. визуально значение одно (с пробелом), а фактически для скриптов другое?
        • +1
          Ну в идеале в такое поле не должен просто никак попасть пробел и не надо тогда никаких неожиданных trim`ов.
      • +1
        Кстати с value действительно был косяк, однажды столкнулся. Если в number поле было вбить невалидное значение, то value говорит, что там пусто
      • 0
        На самом деле проблема не только с email. Например, тип url. Значение www.ya.ru по сути неверное, но браузер может преобразовать в www.ya.ru и отправлять именно это значение (и предоставлять его скриптам).
        • 0
          В помощь призывается pattern!
          • 0
            И он воспринимается мобильными устройствами? Они добавляют на клавиатуру все нужные спец. символы?
            • 0
              Когда я последний раз тестировал — судя по поведению типизированные поля вроде url, email, tel просто используют некий pattern «по-умолчанию». Если его переписать — валидация будет плностью своя. При этом поле не теряло своих новых качеств на клавиатуре.
              Но конечно, все может меняться от платформы к платформе. У меня яблоко.
              • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Так и есть.
    • 0
      достаточно форме добавить атрибут novalidate, тогда браузер не будет применять к таким инпутам правила валидации по умолчанию, а клавиатура на мобильных будет открываться нужная
  • –5
    Вы просто не умеете это готовить
  • +1
    Интересно мнение экспертов: если по аналогии с ВК, вместо инпутов использовать повсеместно дивы с атрибутом contenteditable="true" , ничего страшного не произойдет? (там то со стилями все менее плачевно)
    • +1
      Придётся писать апи самому, хех. И насколько я помню (давно таким не занимался) — там далеко не нулевое количество кроссбраузерных несовместимостей.
      • 0
        Стоит ли так все усложнять? (Я, например, просто брал яваскриптом содержимое этих div-ов и отправлял на сервер аяксом)
        • 0
          Ну это же в первую очередь от задачи зависит О_о

          Если вам понадобиться делать произвольные формы с валидацией, разными вариантами отображения, подгрузкой подсказок аяксом и т. д. — всё будет сложно, и гарантированно сложнее, чем на инпутах, к сожалению.

          Нет, конечно, наверняка есть фреймворки, которые такое делают… Но в таком случае ты просто променяешь одно АПИ на другое.
          • 0
            Не исключаю, что у меня имеются пробелы в знаниях JS, но какая разница, куда, например, выводить сообщение об ошибке, которое пришло от сервака — под соответствующий инпут, или под такой же див? :)
            • +1
              Со стандартными формами есть, например, специальные JS библиотеки для валидации, отображением ошибок и тд, которые можно просто настроить.
              Вообще в целом, кажется что разницы не будет, если элементы формы сделать свои, но на практике оказывается, что не хватает многого из стандартного поведения, например переходы по табу, клик по лейблу — клик по элементу и тд. В целом приходится нифигово всякого дописывать самому.
            • +5
              Я вам не про то. Давайте я вам набросаю краткий список того, что нужно дописать для редактируемого дива, чтобы они сравнился по функционалу с современным инпутом.
              • Типы форм. Придётся делать проверку на ввод только чисел для чисельного ввода, отображение календарика для ввода даты, проверку ввода корректной даты и времени для соотв. типов, цветовой ввод для color, ползунок для rangе… Да и что я вам перечисляю, вот тут всё есть. Это уж не говоря про всякие радиобаттоны и флажки.
              • Перехватывать нажатия таба для нормального перехода по элементам формы, и вообще разные сочетания клавиш для accesskey.
              • Модификаторы поведения — disabled, readonly, checked, autofocus...
              • Валидация. Это поля pattern, min, max, minlength, maxlength, step, встроенная регулярка для урлов, емейлов, телефонов...
              • Разные другие плюшки — placeholder, list.
              • Связь с формой отправки на сервер.
              • Событийная система.

              Наконец, есть вещи, которые вы никак не сможете эмулировать — автозаполнение, переключение видов клавиатуры на телефонах в зависимости от типа инпута, выбор файла (это можно кое-где, но тоже очень геморройно). Смекаете? Чтобы реально замениить инпуты чем-то другим, надо проделать огромную работу.
              • 0
                А в случае инпутов в вебприложении приходится всё равно это делать, но и попутно рубить дефолтное поведение не совпадающее между браузерами.
                • 0
                  В случае contenteditable некроссбраузерного поведения гораздо больше, а фичей — меньше.
    • +4
      Можно и на канвасе полностью свой интефрейс намутить, вопрос в поддержке всеми браузерами, сложности разработки и с поддержкой нестандартных решений следующим разработчиком. Как по мне, так лучше использовать стандартные элементы и запариваться со стилями.
    • +3
      Придётся очень дико обрабатывать событие copy/paste потому что в contenteditable вставляется текст в формате text/html со всеми вытекающими. Но это еще не всё — так же придётся обрабатывать события перетаскивания в это поле и (внимание!) событие document.execCommand из консоли, через которое в contenteditable можно вставить всё что угодно. А это уже довольно объёмная портянка кода.
    • +3
      ничего страшного не произойдет?

      Нет, ничего. Просто отдельный котёл в аду.
  • 0
    Безотносительно самого перевода. Вы цитаты вставляли как картинку верт икальной черты плюс обтекание текстом, который заголовок с выравниванием по центру? Просто очень непривычно. Синтаксисом не поделитесь?
    • +2
      Ответил в личку
      • 0
        Спасибо большое. Только, видимо, не мне в личку)
        • +3
          Вам, вам, проверьте)
          • 0
            Протупил мессенджер местный) Теперь оба сообщения пришло. Спасибо.
          • 0
            А можно и мне в личку? :-)
            • +2
              Можно и вам) Отправил
      • +2
        В андроид клиенте видны только полосы. Даже не догадывался что это что-то большее, чем разделитель глав, пока не прочёл эту ветку.
        • 0
          О сколько нам открытий чудных гототовят хаброредактор.
  • 0
    Госпожа Динкулеску написала поток нытья вместо статьи.
    Из перечисленных проблем реальная только одна — ограничение для selectionStart.
    если тип элемента = 'file', то текст который будет отображаться на месте этого элемента, когда не выбран ни один из файлов: «No file chosen», «no file selected», «No file selected», и просто пустой текстовый блок в Chrome, Safari, Firefox и IE соответственно.
    он выглядит одинаково везде

    Почему это вообще кого-то беспокоит? Это нативные элементы браузера и пользователь этого конкретного браузера узнаёт их и понимает что от него в этом месте хотят.
    • +3
      да, статья написана в достаточно ироничном ключе, но скажите, вас устраивает, например, отсутсвие возможности стилизировать выпадающий список тега select с помощью css?
      • +2
        И для каких именно браузеров вы собрались его стилизовать?
        Вы, например, видели, как он отображается в мобильных браузерах? Скорее всего, видели.
        Вы уверены что сможете полностью корректно стилизовать его для этого случая? Для других случаев?
        Вы уверены что он будет выглядеть как минимум не хуже нативного, работать не хуже нативного и что после вашей кастомизации пользователь поймёт что это именно селект, а не что-либо ещё?
        • 0
          Это вы шутите так?
          Когда код уходит на продакшн он тоже теоретически может не работать. Но никого это не останавливает почему-то…
          • +4
            Нет, я не шучу.
            Просто я ставлю интересы пользователя выше интересов дизайнера.
            • –4
              Вы ставите свое умение ниже интересов пользователя.
        • +7
          На современном мобильном селект выглядит как часть интерфеса операционной системы, все ок, я не вижу проблемы.
          Проблема с моей стороны с десктопными браузерами. Да, я знаю доводы за нативное отображение системных элементов и отчасти поддерживаю их, но вот нифигаж оно не работает, посмотрите на «нативный» селект фаерфокса под OS X. И как написал Drag13 ниже, мы за то, что бы мы могли выбирать, сделать веб приложение как нативное под ОС, или сделать дизайнерский сайт с теми формами которые мне надо. Да посмотрите же, никого это ограничение не останавливает и появляются монстры написанные на jQuery которые эмулируют селект, но с настраиваемым внешним видом, но вот не задача, то он криво под старыми бразуерами отобразиться, то он с помощью клавиатуры не выделяется, и прочие баги. Печальное это, 21 год уже как печально. Что касаемо вашего мнения, я его понимаю и принимаю, но спорить с вами не буду.
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Совершенно с вами согласен.
  • +1
    Проблемы роста, проблемы архитектуры, неудачных решений, непредвиденных технологий, обратной совместимости, и много чего ещё. В программировании эти все грабли известны, изучены и классифицированы.
    Но главное — если с такими проблемами не может справиться, например, десктопное приложение — его обгоняет конкурент, который молод, который другой, которому удаётся принять и похендлить новые вызовы. А в интернете, к сожалению, кто-то решил что конкуренция платформ не нужна, а всем хватит одного стандарта.
  • +1
    У четвёртого «Нетскейка» была тогда масса странных типов тега INPUT. Например, TYPE=OBJECT, TYPE=READONLY или TYPE=JOT.
  • +3
    Хаха, детка. Это все ерунда. Вот попробуй застайлить дропдаун, вот где БОЛЬ. Причем дизайнеры этой проблемы не замечают и год из года рисуют всякое безумие в виде дропдаунов
    • 0
      Ты про <select>?
      • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        да, конечно.
  • –3
    Что касается <better-input>… что тут скажешь.
    Старо как мир
    Собрались как-то инженеры и говорят — что-то у нас слишком много стандартов для проводов, передающих данные от устройства к устройству. Тут тебе и USB, и COM, и LPT, и FireWire, и ThunderBolt, и так далее. Аж 14 штук насчитали. А давайте, говорят, придумаем единый стандарт, который будет удовлетворять всем условиям, будет максимально универсальным, самым гибким и широкораспространённым? «Хорошая идея,» — поддержали все. И теперь у нас 15 стандартов.
  • +1
    «у разработчиков браузеров был 21 год, чтобы починить отображение input'ов»
    У разработчиков стандартов была куча времени чтобы понять что никогда не смогут заставить производителей броузеров выработать какой-то стандарт по отображению/поведению контролов. Но все равно наступили на эти грабли второй раз, когда придумали:
    color
    date
    datetime
    datetime-local
    email
    month
    number
    range
    search
    tel
    time
    url
    week
  • 0
    input — одна из причин, почему я так ненавижу вёрстку. И хотя я разработчик, но ею тоже иногда приходится заниматься.
  • +1
    Еще в мобильном Хроме из-за каких-то там системных сложностей событие keypress не возвращает код клавиши/символ. И разработчики говорят «а что-то мы не можем это реализовать» )))

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.