Я использую функцию document.addEventListener("DOMContentLoaded",() чтобы принудительно ввести шаблон ввода (сначала должна быть буква, затем не допускать последовательных пробелов и т. д.)
Теперь я хочу создать вторую функцию document.addEventListener("DOMContentLoaded",() для электронного письма. (Я хочу предотвратить несколько . и предотвратить более 1 @)
Вот мой код для обоих вышеперечисленных пунктов, но он не работает, он только пишет электронную почту с заглавной буквы (я оставил эту опцию включенной, чтобы проверить, работает ли эта часть, что она и делает, но больше ничего не работает.)
Вот первая часть (я пробовал еще кое-что, удалив первую }); в document.addEventListener("DOMContentLoaded", function () в начале второго числа, как я слышал, это должно работать, но это тоже не сработало.
document.addEventListener("DOMContentLoaded", function() {
// Function to handle all keypress events
function handleKeyPress(event) {
const input = event.target;
const char = String.fromCharCode(event.which);
// Prevent first character from being a space
if (input.selectionStart === 0 && event.code === "Space") {
event.preventDefault();
return;
}
// Prevent first character from being a non-letter
if (input.selectionStart === 0 && !/^[a-zA-Z]$/.test(char)) {
event.preventDefault();
return;
}
// Prevent consecutive spaces
const lastChar = input.value.charAt(input.selectionStart - 1);
if (char === " " && lastChar === " ") {
event.preventDefault();
return;
}
}
// Attach event listeners to input fields
const inputs = document.querySelectorAll("input[name='real_name'], input[name='display_name']");
inputs.forEach(input => {
input.addEventListener("keypress", handleKeyPress);
// Set text-transform to capitalize to force capitalization of each word
input.style.textTransform = "capitalize";
});
});
document.addEventListener("DOMContentLoaded", function() {
// Function to handle all keypress events
function handleKeyPress2(event) {
const input = event.target;
const char = String.fromCharCode(event.which);
// Prevent first character from being a space
if (input.selectionStart === 0 && event.code === "Space") {
event.preventDefault();
return;
}
// Prevent consecutive spaces
const lastChar = input.value.charAt(input.selectionStart - 1);
if (char === "@" && lastChar === "@") {
event.preventDefault();
return;
}
var key = event.keyCode || event.charCode || event.which;
if (key == 32) {
return false;
} else {
return key;
}
}
// Attach event listeners to input fields
const inputs = document.querySelectorAll("input[name='email']");
inputs.forEach(input => {
input.addEventListener("keydown", handleKeyPress2);
// Set text-transform to capitalize to force capitalization of each word
input.style.textTransform = "capitalize";
});
});
Проблема, вероятно, не в двойной привязке к событию DOMContentLoaded
, а скорее в том, что вы дважды привязываетесь к событию keypress
для всех этих полей - и я предполагаю, что комбинация event.preventDefault();
и return;
, вероятно, не позволяет ему даже выполнить второй назначенный обработчик нажатия клавиши. . Для начала вам лучше попытаться сделать все эти вещи в одном обработчике нажатия клавиш.
1) Вам не нужно несколько обработчиков DOMContentLoaded
. Вы можете поместить всю свою логику в одну. 2) Является ли поле электронной почты type = "email"
? У него немного другая модель событий на основе ключей, чем у элемента type = "text"
, что может объяснить вашу проблему. 3) Не используйте text-transform
на элементе input
. Он неточно отражает то, что пользователь ввел в форму, и может вызвать путаницу. Например, они вводят foo
, но видят Foo
, а ваш сервер все равно получит foo
, поэтому это повлияет на любые проверки на достоверность/сравнение.
Я не смог воспроизвести проблему, все работало нормально. Пожалуйста, добавьте HTML-файл. Как создать минимальный воспроизводимый пример
Также вам обязательно нужно посмотреть делегирование событий. Имейте ОДИН обработчик событий в ближайшем статическом контейнере для входных данных.
1. не знаю, как все это собрать воедино. 2. type = "email" 3. нет преобразования текста
Вам не нужно подключать несколько обработчиков событий DOMContentLoaded
. Вы можете связать один и поместить в него все обработчики событий для ваших HTML-элементов.
Однако причина вашей проблемы в том, что вы используете событие keydown
на input
из type = "email"
. Как вы обнаружили, это поведение несовместимо с входными данными type = "text"
.
Учитывая вашу цель, самым простым подходом было бы использование встроенных валидаторов HTML, поскольку это гарантирует, что всем полям будет присвоено значение при отправке, а также будет гарантировать, что поле электронной почты имеет правильный формат. Это дает дополнительное преимущество: оно работает независимо от того, включен ли в браузере пользователя Javascript.
Вот рабочий пример:
function nameInputRestrictor(event) {
const input = event.target;
const char = String.fromCharCode(event.which);
// Prevent first character from being a space
if (input.selectionStart === 0 && event.code === "Space") {
event.preventDefault();
return;
}
// Prevent first character from being a non-letter
if (input.selectionStart === 0 && !/^[a-zA-Z]$/.test(char)) {
event.preventDefault();
return;
}
// Prevent consecutive spaces
const lastChar = input.value.charAt(input.selectionStart - 1);
if (char === " " && lastChar === " ") {
event.preventDefault();
return;
}
}
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("input[name='real_name'], input[name='display_name']").forEach(input => {
input.addEventListener("keypress", nameInputRestrictor);
});
});
label {
display: block;
}
<form>
<label>
Real name: <input type = "text" name = "real_name" required />
</label>
<label>
Display name: <input type = "text" name = "display_name" required />
</label>
<label>
Email: <input type = "email" name = "email" required />
</label>
<button type = "submit">Submit</button>
</form>
Также обратите внимание, что использование text-transform
в элементе input
— крайне плохая практика. Это связано с тем, что тогда поле не будет точно соответствовать тому, что ввел пользователь. Например, они могут подумать, что они ввели Foo
, но на самом деле они ввели foo
, и ваша серверная логика получит foo
при отправке формы, это не то, что, по мнению пользователя, они предоставили вам.
Как сделать две отдельные системы? Один для просмотра и изменения имен, а другой для работы с электронной почтой отдельно?
Добавьте к нему прослушиватель событий отдельно, вот так: jsfiddle.net/RoryMcCrossan/217fucLs. Однако, как я уже упоминал выше, вам не нужно этого делать при использовании валидаторов HTML.
Здесь не показано, как создать две отдельные системы. Электронная почта ничего не делает. Куда вы вставляете коды для почты?
Я думал, это очевидно — вы поместили это там, где я написал «обработать ввод электронной почты здесь…»
это не то же самое. Я попытался добавить что-то, как вы, для имен, но оно туда не помещается, я получаю красные ' и ) в коде Visual Studio (если только там не нужно что-то еще).... можете ли вы что-нибудь добавить там вроде как предотвратить более 1 @ и подряд . чтобы я мог посмотреть, пожалуйста?
Тогда ты сделал это неправильно. Я бы посоветовал задать новый вопрос по этому поводу, если у вас возникли проблемы, хотя, честно говоря, это очень простой синтаксис JS. Возможно, поищите несколько руководств
Спасибо за помощь, но повторная публикация того же вопроса без каких-либо изменений не принесет мне никакой пользы. Думаю, я найму кого-нибудь для написания кода.
Во-первых, даже не обязательно нужен обработчик 'DOMContentLoaded'
для работы с событиями, связанными с входными элементами 'keypress'
, если запрос элемента для регистрации последнего начинается после того, как целевой элемент/ы стали доступными в DOM.
Во-вторых, независимо от того, регистрируется ли обработка событий в 'DOMContentLoaded'
, всегда следует использовать делегирование событий для обработки событий, связанных с входными элементами 'keypress'
.
Можно было бы зарегистрировать прослушиватель событий в ближайшем доступном родительском элементе всех задействованных входных элементов. Затем основному обработчику просто нужно проверить и различить соответствующие входные элементы, чтобы перенаправить обработку, специфичную для типа элемента/имени элемента, в связанную, более специализированную функцию-обработчик целевого элемента.
Редактировать
Описанный выше и реализованный ниже подход (делегирование событий) достигает именно того, о чем недавно просил ФП в одном из комментариев...
«Как сделать две отдельные системы? Одна для просмотра и изменения имен, а другая для работы с электронной почтой отдельно?» Антарктида-НЛО // Комментарий: 1 час назад
function handleNameFieldKeypress(target, evt) {
console.info('handleNameFieldKeypress ... target ...', target);
const char = String.fromCharCode(evt.which);
const { selectionStart } = target;
const isNotValid = (selectionStart === 0 && (
evt.code === 'Space' ||
!/^[a-zA-Z]$/.test(char)
)) || (
char === ' ' &&
target.value.charAt(selectionStart - 1) === ' '
);
if (isNotValid) {
evt.preventDefault();
}
}
function handleEmailFieldKeypress(target, evt) {
console.info('handleEmailFieldKeypress ... target ...', target);
const { selectionStart } = target;
const isNotValid =
(selectionStart === 0 && evt.code === 'Space') || (
String.fromCharCode(evt.which) === '@' &&
target.value.charAt(selectionStart - 1) === '@'
);
if (isNotValid) {
evt.preventDefault();
return;
}
const key = evt.keyCode || evt.charCode || evt.which;
return (key !== 32) && key;
}
function handleInputFieldKeypress(evt) {
const { target } = evt;
let result;
if (target.matches('input[name = "real_name"], input[name = "display_name"]')) {
result = handleNameFieldKeypress(target, evt);
} else if (target.matches('input[name = "email"]')) {
result = handleEmailFieldKeypress(target, evt);
}
return result;
}
document
.addEventListener('DOMContentLoaded', () => {
document
.querySelector('form')
.addEventListener('keypress', handleInputFieldKeypress);
});
body { margin: 0; }
form { width: 32%; }
fieldset { margin: 0 0 8px 0; }
label, label > span { display: block; }
label > span { margin: 4px 0 2px 0; }
/*
input[name = "email"],
input[name = "real_name"],
input[name = "display_name"] { text-transform: capitalize; }
*/
.as-console-wrapper { left: auto!important; width: 66%; min-height: 100%; }
<form>
<fieldset>
<legend>User Data</legend>
<label>
<span>Real Name</span>
<input type = "text" name = "real_name" />
</label>
<label>
<span>Display Name</span>
<input type = "text" name = "display_name" />
</label>
</fieldset>
<fieldset>
<label>
<span>E-mail Address</span>
<input type = "email" name = "email" />
</label>
</fieldset>
</form>
<!--
<script>
// - one does not even need a 'DOMContentLoaded' event listener
// for dealing with input-element related 'keypress' events,
// as long as the element-query starts after the targeted
// element/s have been made accessible within the DOM.
function handleNameFieldKeypress(target, evt) {
console.info('handleNameFieldKeypress ... target ...', target);
const char = String.fromCharCode(evt.which);
const { selectionStart } = target;
const isNotValid = (selectionStart === 0 && (
evt.code === 'Space' ||
!/^[a-zA-Z]$/.test(char)
)) || (
char === ' ' &&
target.value.charAt(selectionStart - 1) === ' '
);
if (isNotValid) {
evt.preventDefault();
}
}
function handleEmailFieldKeypress(target, evt) {
console.info('handleEmailFieldKeypress ... target ...', target);
const { selectionStart } = target;
const isNotValid =
(selectionStart === 0 && evt.code === 'Space') || (
String.fromCharCode(evt.which) === '@' &&
target.value.charAt(selectionStart - 1) === '@'
);
if (isNotValid) {
evt.preventDefault();
return;
}
const key = evt.keyCode || evt.charCode || evt.which;
return (key !== 32) && key;
}
function handleInputFieldKeypress(evt) {
const { target } = evt;
let result;
if (target.matches('input[name = "real_name"], input[name = "display_name"]')) {
result = handleNameFieldKeypress(target, evt);
} else if (target.matches('input[name = "email"]')) {
result = handleEmailFieldKeypress(target, evt);
}
return result;
}
document
.querySelector('form')
.addEventListener('keypress', handleInputFieldKeypress);
</script>
//-->
@Антарктида-НЛО ... посмотри мой ответ выше. Его подход и реализация достигают именно того, о чем вы спрашивали час назад в одном из своих комментариев... "Как мне сделать две отдельные системы? Одна для просмотра и изменения имен, а другая для работы с электронной почтой отдельно?" Антарктида-НЛО
Вау, спасибо! Мне нужно всего лишь еще 2 вещи из этого сейчас! Как разрешить только один символ @ во всем электронном письме. И заставить имена начинаться с 1 заглавной буквы, за которой следуют все строчные буквы, специальные символы или цифры в этом слове (второе слово в имени подчиняется тем же правилам, но первая буква пишется с заглавной буквы...). После этого я закончил со всеми своими формами :) Еще раз спасибо Петр Селигер, ты гений!
В дополнение вы задаете еще одну задачу (или две), не связанную с проблемой, которую вы описали в этой теме. Поскольку вы предоставили подход, который обрабатывает то, о чем вы просите, все остальное необходимо описать и свести в пример в другой теме. Я не против предложить решение, когда требования внутри потока меняются или суммируются. Я почти всегда оказываю помощь немедленно. Но я сейчас в отпуске. Никакого кодирования для SO в ближайшие недели.
Пожалуйста, нажмите изменить, прокрутите вниз и нажмите «изменить фрагмент выше» и добавьте соответствующие HTML, CSS и фреймворки, которые вы используете, из CDN.