
⚙️ Kuidas piirata soovimatute märkide sisestamist INPUT-is JavaScriptiga
Registreerimisvorm, telefoniväli, kataloogiotsing: kasutaja klõpsab INPUT-väljal ja trükib ükskõik mida. Tähti seal, kus ootad numbreid. Erimärke tellimuse numbris. Emoji e-posti väljal. Tulemus: andmebaasis on prügi, päringud katki, backend'i valideerimine ebaõnnestub veateatega.
Probleem lahendatakse frontend'is 15 koodireaga. Pole pluginaid, pole teeke, ainult puhas JavaScript või paar HTML-atribuuti. Allpool on kolm töötavat lähenemist: alates kiirest HTML5-st kuni peeneteralise filtreerimiseni keydown sündmusel, koos valmisnäidetega levinud stsenaariumite jaoks.
💡 Kiirülevaade:
- Vaatame, millal HTML-atribuutidest
pattern,inputmodejatypepiisab ning millal on vaja JavaScripti - Kirjutame „ainult numbrid" filtri jQuery's ja puhtas JS-is, mõlemad versioonid koos rea-realt selgitusega
- Lisame kaitse kleepimise vastu Ctrl+V ja kontekstimenüü kaudu
- Ehitame universaalse malli funktsiooni mis tahes piirangute jaoks: tähed, ladina tähed, kohandatud maskid
HTML5: mida saab teha ilma ühegi JavaScripti reata
Lihtsaim ja usaldusväärseim viis sisendi piiramiseks on öelda brauserile täpselt, mida sa väljal ootad. Kaasaegsed brauserid mõistavad kolme võtmeatribuuti, mis katavad enamiku levinud ülesandeid.
type, peamine filter. type="number" lubab ainult numbreid, miinust ja kümnenderaldajat. type="tel" kuvab mobiilseadmetes numbriklaviatuuri. type="email" kontrollib vormi saatmisel @ märgi olemasolu. type="url" nõuab protokolli. See ei blokeeri sisestust täielikult, kuid pakub õiget ekraaniklaviatuuri ja põhivalideerimist saatmisel.
pattern, regulaaravaldis väljal. Atribuut võtab vastu regulaaravaldise ja valideerib väärtuse vormi saatmisel:
1 <input type="text" pattern="[0-9]{6}" placeholder="Six digits" title="Exactly 6 digits">
Brauser blokeerib saatmise, kui väärtus ei vasta mustrile. Puudus: pattern ei takista keelatud märkide sisestamist; see ainult valideerib tulemuse. Kasutaja saab trükkida „abc" ja näeb viga alles siis, kui proovib vormi saata.
inputmode, õige klaviatuur mobiilis. inputmode="numeric" avab numbriklaviatuuri, kuid ei keela tähtede sisestamist. inputmode="decimal" lisab eraldaja. Kasulik koos JavaScripti filtriga: klaviatuur on juba õige ja JS tegeleb ülejäänuga.
Mida valida. Kui sul on vaja reaalajas keelatud märkide sisestamist tegelikult takistada, siis HTML-atribuutidest ei piisa. Liigume JavaScripti juurde.
JavaScript: klahvivajutuste blokeerimine keydown'i abil
keydown lähenemine püüab iga klahvivajutuse kinni enne, kui märk väljale ilmub. Kui klahv ei ole lubatute nimekirjas, tühistab event.preventDefault() selle.
Variant 1: jQuery, ainult numbrid
Kood seotakse INPUT-väljaga id järgi, lubab numbreid ja teenindusklahve (backspace, nooled, Tab) ning blokeerib kõik muu:
1 $(document).ready(function() { 2 $("#phone_input").keydown(function(event) { 3 // Service keys — let them through 4 if (event.keyCode === 46 || event.keyCode === 8 || 5 event.keyCode === 9 || event.keyCode === 27 || 6 (event.keyCode === 65 && event.ctrlKey === true) || 7 (event.keyCode >= 35 && event.keyCode <= 39)) { 8 return; 9 } 10 // Block everything except digits (main block and numpad) 11 if ((event.keyCode < 48 || event.keyCode > 57) && 12 (event.keyCode < 96 || event.keyCode > 105)) { 13 event.preventDefault(); 14 } 15 }); 16 });
Siin on, mis toimub rida-realt: keyCode 46 (Delete), 8 (Backspace), 9 (Tab), 27 (Escape), 65 + Ctrl (vali kõik), 35..39 (Home, End, nooled). Seejärel tulevad põhiploki numbrid 48..57 (0..9) ja numbriklaviatuuri 96..105. Kõik, mis nendesse vahemikesse ei kuulu, saab preventDefault.
Täielik klahvikoodide tabel Cambia Research'is.
Variant 2: puhas JavaScript, ainult numbrid
Sama asi ilma jQuery'ta, kasutades onkeypress. See versioon on kompaktsem ega too sisse teeki:
1 document.getElementById("phone_input").onkeypress = function(event) { 2 event = event || window.event; 3 if (event.charCode && (event.charCode < 48 || event.charCode > 57)) { 4 return false; 5 } 6 };
charCode kontrollib, et sündmusel on prinditav märk; teenindusklahvid (nooled, backspace) läbivad automaatselt, kuna nende charCode võrdub 0-ga. Numbrid: 48..57, kõik muu tagastab false.
Oluline: keyCode loetakse aegunuks. Kaasaegses koodis on parem kasutada event.key, mis tagastab stringi klahvi nimega ega sõltu klaviatuuripaigutusest:
1 element.addEventListener("keydown", function(event) { 2 // Allow digits, Backspace, Delete, arrows, Tab 3 const allowedKeys = [ 4 "Backspace", "Delete", "Tab", "Escape", 5 "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", 6 "Home", "End" 7 ]; 8 if (allowedKeys.includes(event.key)) return; 9 // Ctrl+A / Ctrl+C / Ctrl+V 10 if (event.ctrlKey) return; 11 // Only digits 12 if (!/^[0-9]$/.test(event.key)) { 13 event.preventDefault(); 14 } 15 });
event.key lähenemine on loetavam ega nõua numbriliste koodide päheõppimist. Kuid vanemate brauserite toetamiseks töötab ülaltoodud keyCode versioon endiselt.
Kleepimise blokeerimine: Ctrl+V ja kontekstimenüü püüdmine
keydown püüab klahvivajutused, kuid kasutaja saab teksti kleepida Ctrl+V või paremklõps → „Kleebi" kaudu. Ta kopeeris „abc123" ainult numbrite väljale ja pooled märgid pääsesid läbi.
Lahendus on input sündmus. See käivitub pärast IGAT välja väärtuse muutust: käsitsi sisestus, kleepimine, automaattäitmine, teksti lohistamine. Filtreerime lõpliku väärtuse regulaaravaldisega:
1 document.getElementById("digits_only").addEventListener("input", function(event) { 2 this.value = this.value.replace(/[^0-9]/g, ""); 3 });
See on kõik. Üks rida ja ükski mittenumber ei pääse väljast läbi, olenemata sellest, kuidas see sinna sattus. Tähtede jaoks: replace(/[^a-zA-Zа-яА-ЯёЁ]/g, ""). Ladina tähtede jaoks: replace(/[^a-zA-Z]/g, "").
Kombineeritud lähenemine (kuldne kesktee). keydown annab kohese tagasiside (klahv „ei vajutu"), samas kui input kaitseb kleepimise eest. Kasuta mõlemat töötlejat:
1 const field = document.getElementById("digits_only"); 2 3 field.addEventListener("keydown", function(event) { 4 const allowed = ["Backspace", "Delete", "Tab", "Escape", 5 "ArrowLeft", "ArrowRight", "Home", "End"]; 6 if (allowed.includes(event.key)) return; 7 if (event.ctrlKey) return; 8 if (!/^[0-9]$/.test(event.key)) event.preventDefault(); 9 }); 10 11 field.addEventListener("input", function() { 12 this.value = this.value.replace(/[^0-9]/g, ""); 13 });
Esimene töötleja lõikab keelatud klahvivajutused koheselt välja. Teine puhastab jäägid pärast kleepimist ja automaattäitmist.
Valmismall mis tahes piirangute jaoks
Ehitame funktsiooni, mis võtab INPUT-välja ja lubatud märkide regulaaravaldise. See töötab telefoninumbrite, postiindeksite, kasutajanimede, SKU otsingu jaoks:
1 function restrictInput(element, allowedPattern) { 2 element.addEventListener("keydown", function(event) { 3 const serviceKeys = [ 4 "Backspace", "Delete", "Tab", "Escape", 5 "ArrowLeft", "ArrowRight", "Home", "End" 6 ]; 7 if (serviceKeys.includes(event.key)) return; 8 if (event.ctrlKey && ["a", "c", "v", "x", "z"].includes(event.key.toLowerCase())) return; 9 if (!allowedPattern.test(event.key)) event.preventDefault(); 10 }); 11 12 element.addEventListener("input", function() { 13 // Build a global pattern from the provided one and clean 14 const globalPattern = new RegExp( 15 allowedPattern.source.replace("^", "").replace("$", ""), 16 "g" 17 ); 18 // Remove everything that does NOT match the pattern 19 const inverted = new RegExp( 20 "[^" + allowedPattern.source.slice(1, -1) + "]", "g" 21 ); 22 this.value = this.value.replace(inverted, ""); 23 }); 24 }
Kasutamine:
1 // Digits only 2 restrictInput(document.getElementById("phone"), /^[0-9]$/); 3 // Latin letters only without spaces 4 restrictInput(document.getElementById("login"), /^[a-zA-Z]$/); 5 // Letters and digits 6 restrictInput(document.getElementById("postal"), /^[a-zA-Z0-9]$/);
Funktsioon ei sõltu jQuery'st, töötab kõigis kaasaegsetes brauserites ja katab kolm stsenaariumi: käsitsi sisestus (keydown), kleepimine (input), automaattäitmine (input).
Märkus: keydown ei käivitu virtuaalsetel klaviatuuridel mõnedes mobiilseadmetes; seal jääb input ainsaks kaitsemeetmeks. Seetõttu ei ole kaks töötlejat koos mitte liiasus, vaid vajadus.
Ülaltoodud video on vormi valideerimise lahtiseletus puhtas JavaScriptis Web Dev Simplified'ilt. See käsitleb sisseehitatud Constraint Validation API-t, kohandatud veateateid ja vigaste väljade stiilimist, mis on siin kirjeldatud lähenemiste suurepärane täiendus.
⁉️🤔 Korduma kippuvad küsimused
Miks mitte lihtsalt kasutada type="number"?
type="number"lubab sisestadaejaE(eksponent), plussi, miinust ja punkti. Kõik need on ujukomaarvude ja eksponentsiaalse notatsiooni jaoks kehtivad märgid. Telefonivälja või postiindeksi jaoks on need üleliigsed. Lisaks käsitlevad brauserid mittenumbrilist sisendit erinevalt: mõni laseb selle vaikselt läbi, teine näitab viga alles saatmisel.
Kas Ctrl+V kaudu kleepimist saab täielikult blokeerida?
Kleepimise täielik blokeerimine on halb praktika. See rikub kasutajakogemust ega kaitse teiste kleepimismeetodite eest (kontekstimenüü, lohistamine). Õige lähenemine: luba kleepimine, kuid puhasta tulemus kohe
inputtöötleja abil, nagu ülaltoodud jaotises näidatud.
Aga brauseri automaattäitmine?
Automaattäitmine käivitub enne
keydownjainputsündmusi; brauser sisestab väärtuse otse.inputtöötleja püüab ka selle juhtumi kinni: väärtus ilmub väljale, seejärel filtreeritakse kohe. Kui automaattäitmine segab (sisestab tähti telefoniväljale), lisa INPUT-väljale atribuutautocomplete="off".
Kas see töötab mobiilseadmetes?
Jah, kuid mööndusega: virtuaalsed klaviatuurid ei genereeri alati
keydownsündmust oodatudkeyCodejakeyväärtustega.inputtöötleja töötab usaldusväärselt igal pool. Mobiilis määra INPUT-väljaleinputmode="numeric"võiinputmode="decimal"; kasutaja saab õige klaviatuuri isegi siis, kuikeydownfilter ei käivitu.
Kuidas keelata tühikuid?
Lisa tühik keelatud märgiklassi:
replace(/[^0-9a-zA-Z]/g, "")eemaldab kõik peale numbrite ja ladina tähtede, sealhulgas tühikud. Või selgesõnaliselt:this.value = this.value.replace(/\s/g, "")eemaldab kõik tühikud, tabeldusmärgid ja reavahetused.
Millist lähenemist oma ülesande jaoks valida

Kui vorm on lihtne ja paar valet märki ei põhjusta kriitilist kahju, kasuta HTML5: type, pattern ja inputmode katavad põhistsenaariumid ilma ühegi JS-i reata. Kiire, natiivne, sõltuvusteta.
Kui reaalajas kontroll ja kohene reaktsioon igale klahvivajutusele on oluline, kasuta keydown + input kombinatsiooni. Esimene blokeerib klahvivajutused, teine puhastab kleepimise tagajärjed. Ülaltoodud jaotise universaalne malli funktsioon kohandub iga väljaga minutiga.
Peamine reegel: ära blokeeri kleepimist täielikult. See ärritab kasutajaid ega paku tegelikku kaitset. Puhasta tulemus pärast kleepimist, selle asemel et seda keelata.



