const inputs = document.querySelectorAll('input[data-type="number"]');
for(let i = 0; i < inputs.length; i++)
{
  inputs[i].addEventListener("input", onInput);
  inputs[i].addEventListener("keydown", onKeydown);
  inputs[i].nextSibling.addEventListener("mousedown", onMousedown);
  inputs[i].nextSibling.addEventListener("mouseup", onMouseup);
}
function onInput(e)
{
  clearTimeout(this._timer);
  const input = e.target,
        min = input.min === "" ? null : Number(input.min),
        max = input.max === "" ? null : Number(input.max),
        canMinus = min === null || min < 0,
        canPoint = input.hasAttribute("nopoint") ? false : true;
  let curStart = input.selectionStart,
      dot = 0,
      minus = 0,
      i = 0,
      timeout = null,
      val = input.value;
  val = val.replace(/[^0-9]/g, (char, pos) =>
  {
    if (      (char == "-" && canMinus && !(pos-i) && --minus)
          ||  ((char == "." || char == ",") && canPoint && pos && (pos-i > 1 || !minus) && !dot++))
    {
      return char;
    }
    if (i < curStart)
      curStart--;
    i++;
    return "";
  });
  if (curStart < 0)
    curStart = 0;
  const isNumber = val.match(/[0-9]/);
  
  if (isNumber && min !== null && val < min)
    val = timeout = min;
  if (isNumber && max !== null && val > max)
    val = timeout = max;
  const exec = () =>
  {
    input.value = val
    input.selectionStart = curStart;
    input.selectionEnd = curStart;
  }
  if (timeout === null)
    return exec();
  this._timer = setTimeout(exec, 1000);
}
function onKeydown(e)
{
  const input = e.target,
        min = input.min === "" ? null : Number(input.min),
        max = input.max === "" ? null : Number(input.max),
        step = input.step === "" ? 1 : Number(input.step),
        keys = {ArrowUp: step, ArrowDown: -step};
  if (keys[e.key])
  {
    let val = (keys[e.key] == ~~keys[e.key] ? ~~input.value : Number(input.value)) + keys[e.key];
    if (min !== null && val < min)
      val = min;
    if (max !== null && val > max)
      val = max;
    input.value = val;
    return e.preventDefault();
  }
}
function onMousedown(e)
{
  if (e.target.parentNode.previousSibling.tagName != "INPUT")
    return;
  const that = this,
        obj = {
          target: e.target.parentNode.previousSibling,
          key: (e.target.previousSibling === null) ? "ArrowUp" : "ArrowDown",
          preventDefault: ()=>{}
        };
  let time = 300;
  !function loop()
  {
    onKeydown(obj);
    that._timer = setTimeout(loop, time);
    time = 30;
  }();
}
function onMouseup(e)
{
  clearTimeout(this._timer);
}
input[data-type="number"] {
  appearance: textfield;
  padding-right: 1.2em;
}
input[data-type="number"]:not(:focus):not(:hover) ~ span:not(:focus):not(:hover)
{
  visibility: hidden;
}
input[data-type="number"] ~ span
{
  float:right;
  position: relative;
  right: 1.8em;
  top: 0.2em;
  height: 1.8em;
  width: 1.5em;
  line-height: 1em;
  font-size: 0.6em;
  cursor: default;
  display: grid;
  background-color: #F1F1F1;
  user-select: none;
}
input[data-type="number"] ~ span > span:nth-child(1):before,
input[data-type="number"] ~ span > span:nth-child(2):before
{
  transform: scaleY(0.6);
  display: block;
}
input[data-type="number"] ~ span > span:nth-child(1):before
{
  content: "▲";
}
input[data-type="number"] ~ span > span:nth-child(2):before
{
  content: "▼";
}
input[data-type="number"] ~ span > span:nth-child(1),
input[data-type="number"] ~ span > span:nth-child(2)
{
  color: #505050;
  width: 100%;
  text-align: center;
}
input[data-type="number"] ~ span > span:nth-child(1):hover,
input[data-type="number"] ~ span > span:nth-child(2):hover
{
  background-color: #D2D2D2;
}
input[data-type="number"] ~ span > span:nth-child(1):active,
input[data-type="number"] ~ span > span:nth-child(2):active
{
  color: white;
  background-color: #787878;
}
input[data-type="number"] ~ span > span:nth-child(1)
{
  top: 0;
}
input[data-type="number"] ~ span > span:nth-child(2)
{
  bottom: 0;
}
<table>
  <tr>
    <td>Native type="number"</td>
    <td><input class="input-price" type="number"></td>
  </tr>
  <tr>
    <td>Any number</td>
    <td><input class="input-price" data-type="number"><span><span></span><span></span></span></td>
  </tr>
  <tr>
    <td>Min 11 / max 123</td>
    <td><input class="input-price" data-type="number" min="11" max="123"><span><span></span><span></span></span></td>
  </tr>
  <tr>
    <td>No decimal point</td>
    <td><input class="input-price" data-type="number" nopoint=""><span><span></span><span></span></span></td>
  </tr>
</table>