title: How to customise `<input>` element with tighter restrictions
body: <p>I have a html <code>&lt;input&gt;</code> element that I want to accept only numbers and to be recognised on mobile devices as a number field. I also want invalid characters to be swallowed, just like for standard <code>type=number</code> swallowing disallowed characters.  </p>
  
  <p>I've tried the obvious <code>type=number</code> but it has a number of shortcomings. Specifically it allows 'e', '+' and '-' (at least in chrome), but these were easy to fix with some JS. The real problem is with the '.' character, I want to be able to enter floating point numbers e.g. '0.10', '5.5054', but don't want to be able to enter invalid strings like '0.10.1' for instance. I tried to resolve this by allowing only 1 '.' at a time but this failed as the <code>input.value</code> gets massaged by the browser e.g. '5.' becomes '5', '5..' becomes null (!) and it seems impossible to get the raw string value typed in the input. The above means checking for existing '.'s and taking action appears to be a dead end...</p>
  
  <p>Core questions:  </p>
  
  <ol>
  <li>Is there a way I missing to inspect and conform the input?  </li>
  <li>'Is there a way of marking an input as a number without the logistical baggage of <code>type=number</code>?</li>
  </ol>
  
  <p>Note:<br>
  * I realise that you can paste whatever you want in, I consider that behaviour pathological and shouldn't be covered by input prevention.</p>
  
  <h2>Update</h2>
  
  <p>To clarify, I have already tried <code>keypress</code>, <code>keydown</code> etc events and they aren't adequate as I want to see how many '.'s exist in the input currently to choose whether or not to allow another. At this point the <code>input.value</code> has been massaged by the browser to remove '.'s. I want to conditionally allow characters based on the current number of '.'s that have been entered.</p>
  
  <h2>Example</h2>
  
  <p>HTML (angular style binding for brevity)</p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;input type="number" (keydown)="keyDown()"&gt;
  </code></pre>
  
  <p>JS</p>
  
  <pre class="lang-js prettyprint-override"><code>function keyDown($event: KeyboardEvent) {
    const inputField = // obtain reference to input element
    const value = inputField.value;
    if ( value.indexOf('.') !== -1 &amp;&amp; $event.key === '.') { // disallow another . if one is present
      // ! input field prunes . so this check isn't sufficient
      $event.preventDefault();
      return;
    }
  
    // This is the crux of the problem e.g.
    // type 5. into input field, value === 5
    // type 5.. into the input field, value === null
    // Since the . char is removed by the input element there's no way to know how many are present!
    console.log(value);
  }
  </code></pre>
  
  <h2>Summary</h2>
  
  <ol>
  <li>Is there a way to signal that an <code>&lt;input&gt;</code> is of type number without using the <code>type=number</code> attribute setting.  
  
  <ol>
  <li>i.e. mobile devices recognise and display number pad etc  </li>
  </ol></li>
  <li>For an <code>&lt;input&gt;</code> that has <code>type=number</code> is there a way to swallow all key input that doesn't result in a valid number  
  
  <ol>
  <li>Before the character is added to the input by the browser, no janky deletion on <code>keyup</code>  </li>
  </ol></li>
  </ol>