【问题标题】:navigation in multiple inputs when reaching max length达到最大长度时在多个输入中导航
【发布时间】:2019-09-17 18:34:49
【问题描述】:

我基本上试图让这三个文本输入代表 00h 00m 00s 以供我的计时器获取用户输入。我希望能够制作谷歌计时器(如果你只是在谷歌中输入计时器,你可以看到这个计时器)但我被困在正确导航上 - 当用户输入两位数字然后专注于下一个输入并且没有“表单”时元素跳出循环。但是,我不断收到“无法读取 null 的属性 'firstElementChild'”。

另外,我希望看到的是当用户输入数字(例如 01 : 30: 00)然后按回车键时,我希望能够获得用户值,这样我就可以根据然而,用户输入,监听“Enter”键触发提交的按键事件似乎不起作用,并且 e.preventDefault() 也不起作用..

<div class="form-container">
   <form class="1" action=""> 
        <input class="1" type="text" maxlength="2" placeholder="00:">
   </form>
   <form class="2" action=""> 
        <input class="2" type="text" maxlength="2" placeholder="00:">
    </form>
    <form class="3" action=""> 
        <input class="3" type="text" maxlength="2" placeholder="00:">           
    </form>
</div>



formContainer.addEventListener('keyup', function(e){
    let target = e.srcElement || e.target;
    let targetValue = target.attributes["maxlength"].value
    let maxLength = parseInt(targetValue, 10);
    let currentLength = target.value.length;

    if(currentLength >= maxLength) {
      let next = target;
      let nextInputParent = target.parentElement.nextElementSibling
      let nextInputInNextSibling = nextInputParent.firstElementChild

      while (next = nextInputInNextSibling){
        if (next.parentElement == null){
          break;
        }

        if (next.tagName.toLowerCase() === "input") {
            next.focus();
            break;
          }
      }
   }
    // Move to previous field if empty (user pressed backspace)
    else if (currentLength === 0) {
      let previous = target;
      let previousInputInPreviousSibling = target.parentElement.previousElementSibling.children[0]
      while (previous = previousInputInPreviousSibling) {
          if (previous == null)
              break;
          if (previous.tagName.toLowerCase() === "input") {
              previous.focus();
              break;
          }
      }
  }
})

form.addEventListener('keydown', function(e){
  if(e.key == "Enter" || e.keyCode == 13){
    console.log("submit");
      e.preventDefault()
      form.submit()
      let userInput = inputEl.value
      let countdown = 60 * userInput

      timer = new Timer(countdown, userInput)
      timer.start()
      toggleStartTimer.textContent = "stop"
      timer.isOn = true
  }
})

【问题讨论】:

    标签: javascript forms input


    【解决方案1】:

    为什么要为每个input 元素使用三种不同的形式?您可以使用一种形式,每个input 元素都有一个oninput 事件处理程序。基本上,只要用户在input 中按下键/写任何内容,就会触发oninput 事件。

    然后,您可以使用表单的 onsubmit 处理程序来处理按 Enter,如下所示:

    //event handler that will fire whenever the user types something in one of the inputs
    $("#timer input[type='text']").on("input", function() {
      //inside the event handler, `this` refers to the input element that fired the event 
      if(this.value.length == 2) {
      
        //move to the next input, if any
        if(next = $(this).next("#timer input[type='text']")[0]) {
          $(this).blur(); //lose focus from the element
          next.focus();
        }
      }
    });
    
    //handling case when user presses 'Enter' 
    //(note that using this approach, one of the inputs should be in focus when Enter is hit)
    $("#timer").on("submit", function(e) {
      //here e is your event object
      e.preventDefault();
      //build your timer and start it
      console.log("Timer started!");
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="form-container">
       <form id="timer" action=""> 
            <input class="1" type="text" maxlength="2" placeholder="00:">
            <input class="2" type="text" maxlength="2" placeholder="00:">
            <input class="3" type="text" maxlength="2" placeholder="00:"> 
            <!-- An input type='submit' is needed, otherwise the form will never submit when Enter is hit.-->
            <input type='submit' value='submit' style='display:none'/>
        </form>
    </div>

    或者,使用纯 Javascript:

    //event handler that will fire whenever the user types something in one of the inputs
    
    var inputs = document.querySelectorAll('#timer input[type="text"]');
    for(let input of inputs) {
      input.oninput = function() {
        if(this.value.length == 2) {
          //move to the next input, if any
          next = this.nextElementSibling;
          if(next && next.type == 'text') {
            this.blur(); //lose focus from the element
            next.focus();
          }
        }
      }
    }
    
    //handling case when user presses 'Enter' 
    //(note that using this approach, one of the inputs should be in focus when Enter is hit)
    $("#timer").on("submit", function(e) {
      //here e is your event object
      e.preventDefault();
      //build your timer and start it
      console.log("Timer started!");
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="form-container">
       <form id="timer" action=""> 
            <input class="1" type="text" maxlength="2" placeholder="00:">
            <input class="2" type="text" maxlength="2" placeholder="00:">
            <input class="3" type="text" maxlength="2" placeholder="00:"> 
            <!-- An input type='submit' is needed, otherwise the form will never submit when Enter is hit.-->
            <input type='submit' value='submit' style='display:none'/>
        </form>
    </div>

    【讨论】:

    • 嘿!感谢您的帮助,但您是否有机会使用 vanila javascript 做到这一点?
    • 非常感谢。它工作得很好。您能否解释一下为什么需要最后一个带有 type="submit" 的输​​入来触发提交?根本不知道那一点!
    【解决方案2】:

    我认为更好的方法是依靠一些最大约束,而不是输入长度。我为你创建了一个简单的 sn-p。有 3 个输入和一个计时器,当您点击“Enter”时会启动。

    const form = document.querySelector(".timer");
    const time = document.querySelector(".time");
    
    const limits = {
      hours: 23,
      minutes: 59,
      seconds: 59
    };
    
    const multipliers = {
      hours: val => (parseInt(val, 10) || 0) * 60 * 60,
      minutes: val => (parseInt(val, 10) || 0) * 60,
      seconds: val => parseInt(val, 10) || 0
    };
    
    let interval = null;
    let totalTime = 0;
    
    form.addEventListener("keyup", function(event) {
      if (event.keyCode === 13) {
        totalTime = Array.from(form.querySelectorAll("input")).reduce(function(
          sum,
          input
        ) {
          const { name, value } = input;
          return (sum += multipliers[name](value));
        },
        0);
    
        if (totalTime > 0) {
          if (interval) {
            clearInterval(interval);
          }
    
          interval = setInterval(() => {
            totalTime--;
            time.innerHTML = totalTime;
          }, 1000);
        }
      }
    
      const { name, value } = event.target;
    
      const parsedValue = parseInt(value, 10);
      const newValue = Math.min(limits[name], parsedValue);
    
      if (parsedValue > newValue) {
        const sibling = event.target.nextElementSibling;
        if (sibling && "focus" in sibling) {
          sibling.focus();
        }
    
        event.target.value = newValue;
      }
    });
    	<form class="timer">
    		<input name="hours" placeholder="00"/>
    		<input name="minutes" placeholder="00"/>
    		<input name="seconds" placeholder="00"/>
    	</form>
    
    	<h1 class="time"></h1>

    【讨论】:

    • 顺便说一下,这是香草 js =)
    猜你喜欢
    • 2023-04-07
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    相关资源
    最近更新 更多