Pro Yearly is on sale from $80 to $50! »

input, i ♥️ you, but you're bringing me down

input, i ♥️ you, but you're bringing me down

Browsers have had an <input> element since the dawn of time, and yet any time you talk to web developers about it, everyone complains about it. It's unpredictable. It's grumpy. It's got reaaaaally strong opinions about style, and it doesn't want to listen to yours. I'm going to tell you a story about how grew up to be the moody adult it is, and why it's maybe time we stood up to it.

053e75a5b48b44d6dd0612795dfb326d?s=128

Monica Dinculescu

June 16, 2016
Tweet

Transcript

  1. but you’re bringing me down i you <input>

  2. @notwaldorf

  3. emojineer

  4. None
  5. None
  6. type=date not working properly empty input is invalid regardless of

    minlength type=number doesn’t work with pattern type=number can type eee without firing event weird caret offset with type=search typing moves cursor to the end
  7. story time

  8. 1993 the early years

  9. 1993 <isindex>

  10. 1995 html2

  11. 1995 <input type=button>

  12. <input type=button> 1995 checkbox text password radio image hidden submit

    reset file
  13. 1995 <input type=button> checkbox text password radio image hidden submit

    reset file
  14. None
  15. (710, 303)

  16. <input type=image src=“map.png”>

  17. <input type=image>

  18. None
  19. None
  20. None
  21. <input type=file>

  22. None
  23. None
  24. None
  25. None
  26. cool cool cool because input

  27. 1995 1999 bit slow, tbh -

  28. in which input does a lot of suffering

  29. An element satisfies its constraints if it is not suffering

  30. Suffering from being missing

  31. Suffering from being too short

  32. Suffering from being too long

  33. Suffering from a step mismatch

  34. Suffering.

  35. html4 1999

  36. <input type=button> 1999

  37. None
  38. None
  39. None
  40. cool cool cool because input

  41. html5 2011

  42. <input type=button> 2011 week/month color date/time number range search email

    tel url
  43. <input type=button> 2016 week/month color date/time number range search email

    tel url
  44. <input type=button> 2011 week/month color date/time number range search email

    tel url
  45. but, as we know, CSS

  46. None
  47. input[type=range] { … } // Webkit ::-webkit-slider-thumb { … }

    ::-webkit-slider-runnable-track { … } // FF ::-moz-range-thumb { … } ::-moz-range-track { … } // Never stop being different, IE <3 ::-ms-thumb { … } ::-ms-track { … } ::-ms-fill-lower { … } ::-ms-fill-upper { … }
  48. input[type=range] { … } // Webkit ::-webkit-slider-thumb { … }

    ::-webkit-slider-runnable-track { … } // FF ::-moz-range-thumb { … } ::-moz-range-track { … } // Never stop being different, IE <3 ::-ms-thumb { … } ::-ms-track { … } ::-ms-fill-lower { … } ::-ms-fill-upper { … }
  49. input[type=range] { … } // Webkit ::-webkit-slider-thumb { … }

    ::-webkit-slider-runnable-track { … } // FF ::-moz-range-thumb { … } ::-moz-range-track { … } // Never stop being different, IE <3 ::-ms-thumb { … } ::-ms-track { … } ::-ms-fill-lower { … } ::-ms-fill-upper { … }
  50. input[type=range] { … } // Webkit ::-webkit-slider-thumb { … }

    ::-webkit-slider-runnable-track { … } // FF ::-moz-range-thumb { … } ::-moz-range-track { … } // Never stop being different, IE <3 ::-ms-thumb { … } ::-ms-track { … } ::-ms-fill-lower { … } ::-ms-fill-upper { … }
  51. None
  52. None
  53. but as we know,
 JavaScript

  54. <input type=number>

  55. value = “1234”

  56. value = “1234” value = “”

  57. value = “1234” value = “” value = “”

  58. wait for it

  59. is an HTMLInputElement

  60. is an HTMLInputElement is an HTMLInputElement

  61. is an HTMLInputElement is an HTMLInputElement is an HTMLInputElement

  62. None
  63. None
  64. None
  65. <input type=checkbox>

  66. <input type=checkbox checked>

  67. $(‘input[type=checkbox]’).checked

  68. $(‘input[type=checkbox]’).checked = false

  69. $(‘input[type=number]’)

  70. $(‘input[type=number]’).checked

  71. $(‘input[type=number]’).checked = true

  72. None
  73. None
  74. cool cool cool because input

  75. let’s do better

  76. <input type=text> <input type=number> <input type=color>

  77. <text-input> <number-input> <color-input>

  78. a new hope 2012

  79. web components 2012

  80. we reusable things

  81. we encapsulation

  82. None
  83. None
  84. how?

  85. <html> <head> <link rel=“import” href=“number-input.html”> </head> <body> <input type=“number” value=“3”></input>

    </body> </html>
  86. <html> <head> <link rel=“import” href=“number-input.html”> </head> <body> <number-input value=“3”></number-input> </body>

    </html>
  87. <html> <head> <link rel=“import” href=“number-input.html”> </head> <body> <number-input value=“3”></number-input> </body>

    </html>
  88. what do we need?

  89. what do we need? specs!

  90. encapsulation shadow DOM 1

  91. reusability document.registerElement 2

  92. imports <link href=“my-input.html”> 3

  93. but like, with code

  94. <html> <head> <link rel=“import” href=“number-input.html”> </head> <body> <number-input value=“3”></number-input> </body>

    </html>
  95. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput);
  96. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput);
  97. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput);
  98. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput);
  99. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); createdCallback() { this._value = null; }
  100. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); attachedCallback() { this._input = document.createElement('input'); this._input = 'text'; this._input = this._value; this.createShadowRoot().appendChild(this._input); this._input.addEventListener(‘keypress’, _restrict); this._input.addEventListener(‘input’, _onInput); }
  101. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); attachedCallback() { this._input = document.createElement('input'); this._input = 'text'; this._input = this._value; this.createShadowRoot().appendChild(this._input); this._input.addEventListener(‘keypress’, _restrict); this._input.addEventListener(‘input’, _onInput); }
  102. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); attachedCallback() { this._input = document.createElement('input'); this._input = 'text'; this._input = this._value; this.createShadowRoot().appendChild(this._input); this._input.addEventListener(‘keypress’, _restrict); this._input.addEventListener(‘input’, _onInput); }
  103. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); attachedCallback() { this._input = document.createElement('input'); this._input = 'text'; this._input = this._value; this.createShadowRoot().appendChild(this._input); this._input.addEventListener(‘keypress’, _restrict); this._input.addEventListener(‘input’, _onInput); }
  104. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); getValue() { return this._value; }
  105. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); setValue(v) { this._input.value = this._value = this._fix(v); } getValue() { return this._value; }
  106. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); _fix(value) { if (!value) return null; if (awfulRegex.test(value)) return Number(value); return NaN; }
  107. class NumberInput extends HTMLElement { constructor() {…} createdCallback() {…} attachedCallback()

    {…} attributeChanged(which, oldV, newV) {} getValue() {…} setValue(v) {…} } document.registerElement(‘number-input’, NumberInput); attributeChangedCallback(which, oldV, newV) { if (which == 'value') { this._input.value = newV; } }
  108. None
  109. when do we get it? now! sort of.

  110. when do we get it? ~~polyfills~~

  111. <better-input> cool cool cool

  112. <script src=“components/webcomponentsjs/webcomponents-lite.min.js"></script> <link rel="import" href=“components/emoji-rain/emoji-rain.html”> <emoji-rain></emoji-rain>

  113. @notwaldorf