【问题标题】:I want to toggle between form top input and first blank input我想在表单顶部输入和第一个空白输入之间切换
【发布时间】:2021-12-28 18:05:53
【问题描述】:

示例#1:用户点击#back2Top,焦点位于“P99”,期望的结果是document.getElementById('P1').focus();

示例#2:用户点击#backtoTop,焦点位于“P1”,期望的结果是document.getElementById('PXX').focus(); 当 PXX 是第一个空白“PXX” ID 时

HTML

<div id = "back2Top" onclick = "togglePX ()">TOP</div>
<input id = "P1">
...
<input id = "P99">

CSS

#back2Top {display: table;  z-index: 999; cursor: pointer;  position: fixed; background-color: transparent;  text-align: center;  text-decoration: none; right:20px; bottom:20px }

JS

function togglePX () {
    if ($('#P1').is(":visible")) {
        for (let i = 1; i < 64; i++) {
            y = document.getElementById("P" +i).value; 
            alert(y)
            if (!y) {
                document.getElementById("P" +i).focus(); 
                break;
            }
        }

    } else {
        document.getElementById("P1").focus()
    }
    }
}

【问题讨论】:

标签: javascript jquery


【解决方案1】:

希望我理解你想要实现的逻辑。

我对您编写的代码进行了一些更改,我想现在它可以正常工作了,就像您提供的示例一样。

使用带有breakfor 循环并不好,所以我使用了while 循环。我用blank替换了y,在那里我可以保留我找到的第一个空白输入,如果循环结束时没有空白输入,这意味着我们必须回到第一个输入#P1

function togglePX () {
  if ($('#P1').is(":visible")) {
    var i = 1;
    var blank;
    while(i<100 && blank == undefined){
      
      if (document.getElementById("P" +i).value.length == 0) {
        blank = document.getElementById("P" +i);
      }
      i++
    }
    if(blank == undefined)
      document.getElementById("P1").focus()
    else
      blank.focus()

  }
}

【讨论】:

    【解决方案2】:

    您可以使用querySelector 获取第一个可用的非空值。

    let lastFocus = null;
    
    const togglePx = (e) => {
      if (lastFocus && lastFocus.id === 'P1') {
          const result = document.querySelector('input[value=""][id^="P"]');
          if (result) result.focus();
      } else {
          document.getElementById("P1").focus();
      }
    };
    document.getElementById("back2top").addEventListener('click', togglePx);
    
    for (const e of document.querySelectorAll('input[id^="P"]')) {
        e.addEventListener("focus", (e) => {
            lastFocus = e.target;
        });
    }
    <input value="full" id="P1"><BR />
    <input value="" id="P2"><BR />
    <input value="" id="P3"><BR />
    <div id="back2top">back to top</div>

    这将获取第一个 ID 以P 开头的空白值,条件是最后一个被关注的元素。如果您的命名策略更复杂,我建议使用类,但您也可以使用正则表达式。

    更多信息请参见querySelector, wildcard element match?

    --

    至于您问题的另一部分,您对我的要求并不完全清楚,但如果您想对课程采取行动而不是按可见性过滤,我强烈建议您切换课程。这更灵活且不易出错,以防您以后想更改它的外观/外观。

    例如,如果您想在输入后隐藏输入,您应该考虑在focusout 上添加一个添加“隐藏”类的事件,并让该类为您隐藏。然后,您可以将其作为条件添加到 querySelector,例如 querySelector('input:not(.hidden)[value=""][id^="P"]')

    【讨论】:

      【解决方案3】:
      function togglePX () {
        if ($('#P1').is(":visible")) {
          for (let i = 1; i < 64; i++) {
            // check for null
            if ( document.getElementById("P" +i) != null )
            {
              valueInText = document.getElementById("P" +i).value;                   
              if (!valueInText) {
                  document.getElementById("P" +i).focus(); 
                  break;
              }
            }
          }
      
      } else {
          document.getElementById("P1").focus()
          }
      

      }

      【讨论】:

        【解决方案4】:

        你们都没有遵循规范或给出在我的装备上有效的合理答案。话虽如此,我很感激(我猜...)这些努力。

        我解决了根据#P1 是否可见需要两个函数的问题。我用https://github.com/customd/jquery-visible/blob/master/jquery.visible.min.js

        function togglePX () {
        if ($('#P1').visible(true)) {
        
        for (let i = 1; i < 64; i++) {
        y = document.getElementById("P" +i).value; 
                   
        if (!y) {
        document.getElementById("P" +i).focus(); 
        break;}
            
          
        }
        
        }
        
         else {
           document.getElementById("P1").focus();
        }   
        }
        

        【讨论】:

          【解决方案5】:

          您需要跟踪焦点输入元素。因为当您单击顶部按钮时,当前焦点输入会失去焦点。

          演示代码:

          let focusedInput = null;
          
          $(document).ready(function() {
            let noOfInputs = 99;
            // create input elements for the demo
            for (let count = 1; count <= noOfInputs; count++) {
              let elm = $("<input id='P" + count + "'></input>").val(count);
              $("body").append(elm);
            }
            //make one input empty for the demo
            $('body>input:eq(3)').val('');
          
            //this is important
            //track the focused element
            $('body>input').focus((event) => focusedInput = $(event.target));
          });
          
          function togglePX() {
            if (focusedInput) {
              if (focusedInput.is('body > input:last-of-type')) { //if last input is focused
                $('body > input:first-of-type').focus();
          
              } else if (focusedInput.is('body > input:first-of-type')) { //if first input is focused
                selectBlank();
              }
            } else { // if no input is selected select first blank
              selectBlank();
            }
          }
          
          function selectBlank() {
            //get all the blank elements
            let blanks = $('body > input').filter(function() {
              return this.value == ''
            });
          
            if (blanks.length > 0)
              blanks.first().focus();
            else //if all inputs are filled select first
              $('body > input:first-of-type').focus();
          }
          #back2Top {
            display: table;
            z-index: 999;
            cursor: pointer;
            position: fixed;
            background-color: transparent;
            text-align: center;
            text-decoration: none;
            right: 20px;
            bottom: 20px
          }
          
          input {
            display: block;
          }
          <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
          
          <div id="back2Top" onclick="togglePX ()">TOP</div>

          我使用'body &gt; input' 选择输入元素,您可以使用'yourContainer &gt; input''.inputStyleClass' 等。

          在上面的演示中使用了:first-of-type:last-of-type 伪类。这样您就不必硬编码 #P1#P99 来选择第一个和最后一个输入。

          要查找空白输入,我们可以使用 jQuery .filter API。然后选择第一个进行对焦。



          我添加了两个额外的用例:

          • 当应用程序加载且用户未选择任何输入并单击顶部按钮时。然后选择第一个空白。
          • 当所有输入都填满并且用户单击顶部按钮时。然后选择第一个输入。

          【讨论】:

            【解决方案6】:

            事实上,你并没有解释你当前的问题是什么,你也没有解释你试图用 is:visible 选择器做什么。但无论如何,我相信你需要检查是否有一个空的text input(下面是一个例子)并设置一个异步焦点。

            编辑:您是否希望每次都在第一个输入和第一个空输入之间切换?只需在单击按钮之前将最后一个焦点元素的信息存储在某处即可。

            function togglePX() {
            
              function delayedFocus(el, delay) {
                if(document.activeElement) document.activeElement.blur();
                setTimeout(function() {
                  el.focus();
                }, delay || 1);
              }
                
              var noOfTextInputs = document.getElementsByClassName('set-of-inputs').length,
                  container = document.getElementById('content'),
                  lastFocusedId = container.lastFocusedId,
                  firstTextInput = document.getElementById('P1'),
                  firstEmptyTextInput;
            
              for(var i=0; i<noOfTextInputs; i++) {
                var id = 'P' + (i+1),
                    el = document.getElementById(id),
                    txt = el.value;
                if(txt.length == 0) { 
                  firstEmptyTextInput = el;
                  break;
                }
              }
              
              var textInputToFocus = lastFocusedId == "P1" ?
                  firstEmptyTextInput || firstTextInput :
                  firstTextInput;
            
              delayedFocus(textInputToFocus, 100);
            }
            #back2Top {
              z-index: 999; 
              cursor: pointer;  
              position: fixed; 
              background-color: transparent;
              border: none;
              text-align: center;  
              text-decoration: none; 
              right:20px; 
              bottom:20px
            }
            #content {
              padding: 1em;
            }
            .set-of-inputs {
              margin: 0.5em;
              display: block;
            }
            <!DOCTYPE html>
            <html>
              <head>
                <meta charset="utf-8" />
              </head>
              <body>
                <div id="page">
                  <button type="button" id="back2Top" onclick="togglePX()">TOP</button>
                  <div id="content"></div>
                </div>
                <script>
                  // create some text-inputs, some of them w/out content
                  var emptyElem = [11,42,97], 
                      container = document.getElementById('content');
                  for(var i=1; i<100; i++) {
                    var el = document.createElement('input');
                    el.id = 'P' + i;
                    el.type = 'text';
                    el.classList.add('set-of-inputs');
                    if(!~emptyElem.indexOf(i)) el.value = i;
                    container.appendChild(el);
                  }
                  // store the last element which has got focused
                  container.addEventListener('focusin', function(e){
                    this.lastFocusedId = e.target.id;
                  });
                </script>
              </body>
            </html>

            【讨论】:

              【解决方案7】:

              您被否决了,因为这个问题有点不清楚,但希望这与您所追求的相近。您的代码是 jQuery 和纯 JS 的混合体,但您确实使用 jQuery 标记了您的问题,所以这是一个 jQuery 解决方案。

              棘手的部分是找到重点关注的input。这很棘手,因为一旦你点击你的TOP div,之前关注的input 突然不关注了!在点击的时候,焦点已经消失了。

              所以答案是跟踪关注哪个input;每次input 成为焦点时,将其保存在变量中:

              let focussed;
              $('input').on('focus', function() {
                  focussed = $(this).attr('id');
              });
              

              现在即使焦点转移了,我们仍然知道是哪一个。

              剩下的就比较简单了:

              • 如果焦点元素是(曾经)P99,则将焦点设置为P1;

              • 否则,找到第一个空输入,并在那里设置焦点。请注意,这与您指定的内容略有不同。您说如果单击 TOP 时焦点为 P1,则焦点应转移到第一个空输入。在此代码中,在 任何 输入(P99 除外)处单击 TOP 并将焦点转移到第一个空输入。我这样做是因为如果你只在 P1 时转移焦点,那么当焦点在 P2 - P98 时你会做什么?我的猜测是您希望这些情况下的行为相同。

              这是一个有效的 sn-p。一些注意事项:

              • 我只包含输入 1-30 和 99,足以让页面滚动;

              • 我将内联 onclick() 移至单独的事件处理程序,因为这被认为是更好的做法,并将您的 HTML 与 JS 分开,参见例如 jQuery.click() vs onClick;

              • 我不确定if ($('#P1').is(":visible")) { 测试的用途,您的文字没有提及任何有关输入可见性的内容。我假设这是一个实验/尝试,不相关;

              • 我假设您的代码中的 64 只是一个中间实验/尝试,因为您的文本和 HTML 指定应该有 99 个输入;

              $(document).ready(function() {
                  let focussed,
                      $inputs = $('input'),
                      $back2Top = $('#back2Top'),
                      $p1 = $('#P1');
              
                  // The function to set focus
                  function togglePX() {
              
                      // First check if we are at P99
                      if (focussed == 'P99') {
                          $p1.focus();
              
                          // We're done
                          return;
                      }
              
                      // For focus at any other input, let's find first blank input.
                      // Iterate over all inputs, trimming whitespace to find the
                      // empty ones, then take the first and focus it.
                      $inputs.filter(function (index, element) {
                          return $.trim($(element).val()) === '';
                      }).first().focus();
                  }
              
                  // Handle clicks on TOP 
                  $back2Top.on('click', function() {
                      togglePX();
                  });
              
                  // Every time an input is focussed, store which one it was
                  $inputs.on('focus', function() {
                      focussed = $(this).attr('id');
                      // console.log('Input #' + focussed + ' is focussed')
                  });
              });
              #back2Top {
                  display: table;
                  z-index: 999;
                  cursor: pointer;
                  position: fixed;
                  background-color: transparent;
                  text-align: center;
                  text-decoration: none;
                  right:20px;
                  bottom:20px;
              }
              input {
                  padding: 6px;
                  margin: 4px;
                  display: block;
              }
              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
              
              <div id="back2Top">TOP</div>
              <input id="P1">
              <input id="P2">
              <input id="P3">
              <input id="P4">
              <input id="P5">
              <input id="P6">
              <input id="P7">
              <input id="P8">
              <input id="P9">
              <input id="P10">
              <input id="P11">
              <input id="P12">
              <input id="P13">
              <input id="P14">
              <input id="P15">
              <input id="P16">
              <input id="P17">
              <input id="P18">
              <input id="P19">
              <input id="P20">
              <input id="P21">
              <input id="P22">
              <input id="P23">
              <input id="P24">
              <input id="P25">
              <input id="P26">
              <input id="P27">
              <input id="P28">
              <input id="P29">
              <input id="P30">
              ....
              <input id="P99">

              【讨论】:

                猜你喜欢
                • 2012-03-11
                • 1970-01-01
                • 2018-02-05
                • 1970-01-01
                • 2012-10-15
                • 2018-01-17
                • 1970-01-01
                • 1970-01-01
                • 2014-12-21
                相关资源
                最近更新 更多