Javascript 下一个兄弟姐妹

Javascript Next Sibling

我有一个示例 fiddle 说明了我要完成的任务: https://jsfiddle.net/qscL4gjh/1/

输入框必须是“文本”输入(不是“数字”),并且只能输入空白值或 8 位数字。我有那部分工作。

但如果用户输入的键值不符合要求,我想显示一个错误块(在输入下方)- 由于某种原因 我无法 javascript识别错误块。我希望错误块出现 3 秒然后淡出。

function validateObj(obj, evt) {
   var key = (evt.which) ? evt.which : evt.keyCode
   var b = (!(key > 31 && (key < 48 || key > 57)) && obj.value.length < 9);
   if (!b) {
    var a = obj.getAttribute("data-errorid");
    console.log("Error Block Id: " + a);
    
    
     var $err = document.querySelector(a) || obj.nextElementSibling;
     
     if ($err.length) {
       console.log("Found error note");
       $err.style.visibility = "visible";
       $err.style.opacity = "1";
       $err.style.transition = "3s";
       $err.style.opacity = "0";
     }
     else {
       console.error("Could not find error block");
     }
   }
   return b;
 }
<label>Test 1</label>
<input type="text" id="num" value="" onkeypress="return validateObj(this, event)" data-errorid="#error_note1" value=""/>
<div id="error_note1" class="error_note">
  Must be empty or 8 numeric digits
</div>

<br><br>

<label>Test2</label>
<input type="text" id="num" value="" onkeypress="return validateObj(this, event)" data-errorid="#error_note2" value=""/>
<div id="error_note2" class="error_note">
  Must be empty or 8 numeric digits
</div>

function validateObj(obj, evt) {
var key = evt.which ? evt.which : evt.keyCode;
var b = !(key > 31 && (key < 48 || key > 57)) && obj.value.length < 9;
if (!b) {
    var a = obj.getAttribute("data-errorid");
    console.log("Error Block Id: " + a);
    var $err = document.querySelector(a) || obj.nextElementSibling;

    if ($err.length) {
      alert("Found error note");
      $err.style.visibility = "visibile";
      $err.style.opacity = "1";
      $err.style.transition = "3s";
      $err.style.opacity = "0";
    } else {
      document.querySelector(a).style.display = "block";
      setTimeout(function () {
        document.querySelector(a).style.display = "none";
      }, 3000);
    }
  }
  return b;
 }

在下面的例子中:

  • 所有内容都包含在 <form id='UI'> 中,并通过 .forms 属性.

    引用
    const UI = document.forms.UI;
    
  • 不使用内联属性事件,inline event handlers are garbage. Use onevent properties or .addEventListener(). If you have multiple <input>s, register events on an ancestor tag like <form>, <body>, document, or window. Read about events and event delegation

    onkeypress="return validateObj(this, event)" //
    

    .addEventListener(event, event handler, capture)

    UI.addEventListener('keydown', resetVal); //
    UI.addEventListener('keyup', valData, true); // 
    /* ☝ certain events require the capture phase instead of the bubbling phase
    (see previous link to "event") */
    

    或一个事件属性

    UI.onkeydown = resetVal; // 
    UI.onkeyup = valData; //  
    /* "keyup" events actually fire on the capture phase that's why 
    .addEventListener() is recommended */
    
  • 要始终引用用户当前正在输入的 <input>,请使用 Event.target 属性.

    const inp = e.target; // Refers >inp< as the <input> the user is typing into
    if (inp.matches('input')) {... // Delegate event to >inp< only
    
  • .value<input> 是一个字符串,正在验证 <input>[pattern] 属性,它是 RegExp。

    <input id='test1' pattern='\d{8}'>
    
    const data = inp.value;
    const error = inp.nextElementSibling;
    const pattern = inp.pattern;
    const rgx = new RegExp(pattern, 'gm');
    const match = rgx.test(data);
    
  • 所有样式均来自 class via .classList 属性.

    if (!match) {
      inp.classList.add('red');
      error.classList.add('flash');
    } else {
      inp.classList.remove('red');
      error.classList.remove('flash');
    }
    

这个例子几乎可以容纳无限数量的 <input>(静态和动态),稍作修改也可以接受来自 <textarea>contenteditable 的标签([data-pattern] 属性和 .textContent.dataset 属性)。 注意: 闪烁的错误消息并不是很好的用户体验,因此我添加了红色文本作为持续提醒用户该文本仍然无效。

const UI = document.forms.UI;

UI.addEventListener('keydown', resetVal);
UI.addEventListener('keyup', valData, true);

function resetVal(e) {
  const inp = e.target;
  if (inp.matches('input')) {
    inp.nextElementSibling.classList.remove('flash');
    if (inp.value.length < 1) {
      inp.classList.remove('red');
    }
  }
};

function valData(e) {
  const inp = e.target;
  if (inp.matches('input') && inp.value.length > 0) {
    const data = inp.value;
    const error = inp.nextElementSibling;
    const pattern = inp.pattern;
    const rgx = new RegExp(pattern, 'gm');
    const match = rgx.test(data);
    if (!match) {
      inp.classList.add('red');
      error.classList.add('flash');
    } else {
      inp.classList.remove('red');
      error.classList.remove('flash');
    }
  }
};
label {
  display: block;
}

.error {
  display: block;
  width: 30ch;
  margin: 3px 0 6px 0;
  visibility: hidden;
  text-align: center;
}

.flash {
  visibility: visible;
  opacity: 1;
  animation: fade 3s forwards;
}

@keyframes fade {
  0%,
  100% {
    opacity: 0
  }
  50% {
    opacity: 1
  }
}

.red {
  color: red;
}
<form id='UI'>
  <label>Test 1 <input id="test1" pattern='\d{8}'>
<output class="error">
  Must have 8 numeric digits
</output></label>

  <label>Test 2 <input id="test2" pattern='^[a-zA-Z]+$'>
<output class="error">
  Must only have letters 
</output></label>

  <label>Test 3 <input id="test3" pattern='^[^\-\^\\]()@#$%&*_+=~;:]+$'>
<output class="error">
  Cannot have special characters
</output></label>
</form>