为什么在 mouseout 事件处理程序中将输入 type="number" 设置为 type="text" 不起作用?

Why doesn't setting an input type="number" to type="text" in an mouseout event handler working?

目标:

我有一个输入元素,用户应在其中输入 1 到 999 之间的数字,可以选择使用 (input type="number") up/down 微调器,但是当鼠标不在时t 在这个元素上或者元素没有焦点,我希望输入元素是 'text' 类型,以确保输入的大小只显示元素的值,而不显示微调器或空白区域隐藏的微调器。这样输入元素中的值和元素右侧的文本不会移动,无论元素是 'text' 还是 'number' 类型,元素是否有焦点,或者鼠标是否超过元素。

背景:

目前,我最初将输入元素的类型设置为 'text',左边距设置为“2ch”,宽度设置为“4ch”,然后当鼠标悬停在元素上时,我将元素的类型为 'number',左边距为“0”,宽度为“6ch”。当鼠标离开元素或元素失去焦点时,我将这些属性设置回它们的初始值。

代码:

<style>
  /* Number text (1/3 etc) */
  .numbertext { color: #f2f2f2; font-size: 12px; padding: 8px 12px; position: absolute; top: -90px; }
</style>
<div class="numbertext">
  <input type="text" style="text-align: right; margin-left: 2ch; width: 4ch;" min="1" max="999" value="1"
         onmouseover="setInputType( 'number' );"
         mouseout="setInputType( 'text' );"
         onblur="setInputType( 'text' );" />/
  <span>999</span>
</div>
<script>
  function setInputType( type ) {
    var input = window.event.currentTarget;

    if( type === 'text' ) {

      input.style.marginLeft = '2ch'; 
      input.style.width      = '4ch';

    }
    else {

      input.style.marginLeft = '0'; 
      input.style.width      = '6ch';

    }
    input.type = type;
  }
</script>

问题:

当页面最初显示时,代码以我想要的方式显示,将光标悬停在该字段上或关注它也有效。但是,在鼠标悬停在该字段上或该字段失去焦点后将鼠标从该字段上移开会不一致地恢复输入元素的初始设置,因为 mouseout 和 blur 事件处理程序并不总是触发。我知道这是因为在 setInputType 函数的 if( type === 'text' ) 语句分支和 运行 Chrome inspect > source 面板中的代码在鼠标移开时不会停止代码执行鼠标移到它上面后的元素。

关于为什么 mouseout 和 blur 事件处理程序不能正常工作的任何想法?

解法:

CodePage 显示了一个完整的解决方案,其中包括 Bryan Elliott 的更正和 Jon P 的建议。

谢谢

在你的元素事件中,你有 mouseout="...",它需要是:onmouseout="..."

像这样:

<input
    type="text"
    style="text-align: right; margin-left: 2ch; width: 4ch;"
    min="1" max="999"
    value="1"
    onmouseover="setInputType( 'number' );"
    onmouseout="setInputType( 'text' );"   //notice the onmouseout=""  instead of mouseout=""
    onblur="setInputType( 'text' );"
/>

使用事件侦听器以不显眼的方式绑定事件。然后使用 event.type 确定要采取的操作。

//Get the relevent elements
let numText = document.querySelectorAll(".numbertext input[type='text']");

//Loop them
for (var i = 0; i < numText.length; i++) {
  //Now loop the event types we're interested in
  "blur focus mouseenter mouseleave".split(" ").forEach(function(e) {
      //and add the event listener for that event type
      numText[i].addEventListener(e, setInputType);
    })
  }

  //Event listener
  function setInputType(event) {
    var type = "text";
    //Dont change on mouse leave if the element has focus
    if(event.type == "blur" || (event.type == "mouseleave" && this != document.activeElement )) {
      
      this.style.marginLeft = '2ch';
      this.style.width = '4ch';
      type = "text";

    } else {

      this.style.marginLeft = '0';
      this.style.width = '6ch';
      type = "number";

    }
    this.type = type ;
  }
.numbertext {
  color: #f2f2f2;
  font-size: 12px;
  padding: 8px 12px;
  /*position: absolute;
  top: -90px;*/
}
<div class="numbertext">
  <input type="text" style="text-align: right; margin-left: 2ch; width: 4ch;" min="1" max="999" value="1" />/
  <span>999</span>
</div>

<div class="numbertext">
  <input type="text" style="text-align: right; margin-left: 2ch; width: 4ch;" min="1" max="999" value="1" />/
  <span>999</span>
</div>