如何启发式发现Javascript输入自动完成键*事件

问题描述 投票:0回答:1

我最近需要在 HTML 输入字段中强制使用正确的大小写。 CSS Text-Transform:大写为 90%,但没有小写多个大写。所以我写了下面的Javascript。

令我惊讶的是,您会看到自动完成输入(用户单击自动完成选项之一)会导致失去任何“键”属性的 keyup 和 keydown 事件:-( 正如您在代码中也可以看到的,我必须在事件中搜索“密钥”,如果它不存在,我认为它是自动完成的。

有更好/有记录的方法吗?自动完成肯定更像是“粘贴”事件吗?有人有规范的指示吗?

    <!DOCTYPE html>
    <html>
    <head>
    <script type="application/javascript">
        'use strict';
        
            document.addEventListener("DOMContentLoaded", isDOMIsGood);
    
            function isDOMIsGood() 
            {
                // Handle autocomplete
                document.body.addEventListener('keyup',
                    (e) => {
                        
                        if (e.target.tagName.toUpperCase()  != "INPUT"      || 
                            e.target.type.toUpperCase()     != "TEXT"       ||
                            getComputedStyle(e.target).textTransform.toUpperCase() 
                                                            != "CAPITALIZE" ||
                            (
                            "transform" in e.target.dataset                 &&
                            e.target.dataset.transform.toLowerCase()
                                                            == "standard"   
                            ))                                              
                            return true;
                            
                        if ("key" in e) // not autocomplete
                            return true;
    
                        e.target.value = e.target.value.toLowerCase();
                        
                        return true;
                    }
                );
                // Handle normal keyboard input         
                document.body.addEventListener('keydown',
                    (e) => {
                    
                        const WORD_DELIMS = ".,& -:";  // Needs work
                        
                        if (e.target.tagName.toUpperCase()  != "INPUT"      || 
                            e.target.type.toUpperCase()     != "TEXT")
                            return true;
                            
                        if (!("key" in e)) // autocomplete
                            return true;
                            
                        if (e.key.length                    >  1            || 
                            e.altKey                                        || 
                            e.ctrlKey                                       || 
                            e.isComposing                                   || 
                            e.metaKey                                       ||
                            e.target.value.length           ==  0           || 
                            e.target.selectionStart         ==  0           || 
                            e.key                           >  "Z"          || 
                            e.key                           <  "A"          ||
                            (
                            "transform" in e.target.dataset                 &&
                            e.target.dataset.transform.toLowerCase()
                                                            == "standard"   
                            )                                               ||
                            getComputedStyle(e.target).textTransform.toUpperCase() 
                                                            != "CAPITALIZE" ||
                            WORD_DELIMS.indexOf(e.target.value.substr(e.target.selectionStart - 1, 1)) != -1)           
                            return true;
                        
                        let   cursorPos         = e.target.selectionStart;
                        
                        e.target.value          = e.target.value.substring(0, cursorPos)        +
                                                  String.fromCharCode(e.key.charCodeAt(0) + 32) + 
                                                  e.target.value.substring(cursorPos);
                        e.target.selectionStart = ++cursorPos;
                        e.target.selectionEnd   = cursorPos;
                                        
                        e.preventDefault();
                        e.stopPropagation();
                        return false;
                    }
                );
                // Handle paste          
                document.body.addEventListener("paste", 
                    (e) => {
                        const WORD_DELIMS = ".,& -:";   // Needs work
                        
                        if (e.target.tagName.toUpperCase()  != "INPUT"      || 
                            e.target.type.toUpperCase()     != "TEXT"       ||
                            getComputedStyle(e.target).textTransform.toUpperCase() 
                                                            != "CAPITALIZE" ||
                            (
                            "transform" in e.target.dataset                 &&
                            e.target.dataset.transform.toLowerCase()
                                                            == "standard"   
                            ))                                              
                            return true;
    
                        let paste = (e.clipboardData || window.clipboardData).getData('text');
                        if (paste.length == 0)
                            return true;
                        
                        e.target.value = (e.target.value.substring(0, e.target.selectionStart) + 
                                            paste + e.target.value.substring(e.target.selectionStart)).toLowerCase();
    
                        e.preventDefault();
                        e.stopPropagation();
                        return true;
                    }
                    
                );
                // Allow the user, config file, etc set the enforcement level          
                document.getElementById("properRules").addEventListener("click", 
                    (e) => {
                        
                        if (e.target.tagName.toLowerCase() == "input" && 
                            e.target.type.toLowerCase()    == "radio" &&
                            e.target.name == "properCase")
                        {
                            var enhanced = document.getElementById("enhanced");
                            enhanced.dataset.transform = e.target.value;
                            
                            if (enhanced.dataset.transform == "none")
                                enhanced.style.textTransform = "none";
                            else
                                enhanced.style.textTransform = "capitalize";
                        }   
                        
                        return true;
                    }
                ); 
            }
    </script>
    <style type="text/css">
    input[type=radio]:checked {
        accent-color: lightblue;;
    }
    </style>
    </head>
    <body>
    <h1>Supplementing CSS Text-Transform: Capitalize</h1>
    <h2>How to enforce "Proper Case" on HTML input?</h2>
    
    <p>CSS Text-Transform will upcase each word if all lower case but not downcase multiple consecutive caps</p>
    <div id="outer">
        <div>
            <label for="enhanced">Enhanced Capitalize:</label>
            <input id="enhanced" type="text" style="text-transform: capitalize; background-color: lightblue;"
                autocomplete="new-password" autofocus spellcheck="false" >
            <br><br>
        </div>
        <div id="properRules">
          <p>"Proper Case" enforcement level:</p>
          <input type="radio" id="pc1" name="properCase" value="strict" checked=checked >
          <label for="pc1">Strict</label><br>
          <input type="radio" id="pc2" name="properCase" value="standard">
          <label for="pc2">Relaxed</label><br>
          <input type="radio" id="pc3" name="properCase" value="none">
          <label for="pc3">None</label><br>
        </div>
    </div>
    </body>
    </html>
javascript css autocomplete keyboard-events capitalize
1个回答
0
投票

以下是无需更改 html 即可完成此操作的方法。但我建议更好的方法是为用户提供输入或粘贴文本的输入,以及根据单选按钮选择转换文本的输出。



HTML

<h1>Supplementing CSS Text-Transform: Capitalize</h1>
<h2>How to enforce "Proper Case" on HTML input?</h2>

<p>CSS Text-Transform will upcase each word if all lower case but not downcase multiple consecutive caps</p>
<div id="outer">
  <div>
    <label for="enhanced">Enhanced Capitalize:</label>
    <input id="enhanced" type="text" style="background-color: lightblue;" autocomplete="new-password" autofocus spellcheck="false">
    <button id="copy">Copy</button>
    <br><br>
  </div>
  <div id="properRules">
    <p>"Proper Case" enforcement level:</p>
    <input type="radio" id="pc1" name="properCase" value="strict" checked=checked>
    <label for="pc1">Strict</label><br>
    <input type="radio" id="pc2" name="properCase" value="standard">
    <label for="pc2">Relaxed</label><br>
    <input type="radio" id="pc3" name="properCase" value="none">
    <label for="pc3">None</label><br>
  </div>
</div>

CSS

input[type=radio]:checked {
  accent-color: lightblue;
}

.capitalize {
  text-transform: capitalize;
}

JS

const textCopy = document.getElementById("copy");
const textInput = document.getElementById("enhanced");
const radioStrict = document.getElementById("pc1");
const radioRelaxed = document.getElementById("pc2");
const radioNone = document.getElementById("pc3");

textCopy.addEventListener('click', () => {
    textInput.select();
    const range = document.getSelection();
    const value = range.toString();
    navigator.clipboard.writeText( value );
    console.log( value );
    alert( value );
});

textInput.addEventListener('input', () => {
  if (radioStrict.checked) {
    textInput.value = textInput.value.toLowerCase();
    textInput.classList.add('capitalize');
    return true;
  }

  if (radioRelaxed.checked) {
    textInput.classList.add('capitalize');
    return true;
  }

  if (radioNone.checked) {
    textInput.classList.remove('capitalize');
    return true;
  }
});

radioStrict.addEventListener('input', () => {
  textInput.value = textInput.value.toLowerCase();
  textInput.classList.add('capitalize');
});

radioRelaxed.addEventListener('input', () => {
  textInput.classList.add('capitalize');
});

radioNone.addEventListener('input', () => {
  textInput.classList.remove('capitalize');
});
© www.soinside.com 2019 - 2024. All rights reserved.