Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Для нескольких input одна функция (https://javascript.ru/forum/events/51847-dlya-neskolkikh-input-odna-funkciya.html)

klk.pma 21.11.2014 19:15

Для нескольких input одна функция
 
Добрый день! Я начинающий, поэтому если можно "пинайте" с примерами.
Возникла такая проблема:
есть несколько input
<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">

В них должны вноситься только цифры, а все остальное не должно даже отображаться в них.

Если есть один input, то это можно реализовать через это:
document.getElementById("digit").onkeypress = function (e) {
	return !(/[^0-9]/.test(String.fromCharCode(e.charCode)));
}

<input id="digit" type="text" maxlength="8" name="ot" value="">


А как реализовать с помощью классов, так чтобы одна функция подходила для всех элементов с определенным классом?

danik.js 21.11.2014 19:24

Цитата:

Сообщение от klk.pma
В них должны вноситься только цифры

Этот инпут больше подойдет:
<input type="number" max="99999999">

Но вводить позволяет не только числа. Но форма все равно не отправится если значение неверное.

klk.pma 21.11.2014 19:33

Цитата:

Сообщение от danik.js (Сообщение 342222)
Этот инпут больше подойдет:
<input type="number" max="99999999">

Но вводить позволяет не только числа. Но форма все равно не отправится если значение неверное.

Я знаю про number, но этот вариант не подходит. Самый подходящий вариант это JS

klk.pma 21.11.2014 19:45

Хотя бы подскажите, как правильно обращаться к классам, чтобы менять их значение. Пробовал через getElementsClassName("digit"), но все тшетно

krutoy 21.11.2014 19:52

<!DOCTYPE HTML>
<html>
  <head><meta charset="windows-1251" /> </head>
  <body>

<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">

    <script>
digits=document.getElementsByClassName("digit")
filter=function () {
   if(/\D+/g.test(this.value)) this.value=this.value.replace(/\D+/g, "")
}
for(i in digits){if(/\d+/.test(i)) digits[i].oninput=filter}




    </script>
  </body>
</html>

klk.pma 21.11.2014 20:01

Спасибо, то что надо!
Кстати, первый раз увидел такой перебор цикла for(i in digits). Такое только в JS возможно?

krutoy 21.11.2014 20:04

Цитата:

Сообщение от klk.pma
Такое только в JS возможно?

Я в питоне кажется видел такое. Еще где-то. Да не, во многих яп есть подобное, я думаю.

klk.pma 21.11.2014 20:07

Цитата:

Сообщение от krutoy (Сообщение 342229)
<!DOCTYPE HTML>
<html>
  <head><meta charset="windows-1251" /> </head>
  <body>

<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">

    <script>
digits=document.getElementsByClassName("digit")
filter=function () {
   if(/\D+/g.test(this.value)) this.value=this.value.replace(/\D+/g, "")
}
for(i in digits){if(/\d+/.test(i)) digits[i].oninput=filter}
    </script>
  </body>
</html>

Пожалуйста, подскажите, а есть вариант реализовать подобную задачу через событие клавиатуры? Интересуюсь на будущее, для других похожих задач

krutoy 21.11.2014 20:10

Цитата:

Сообщение от klk.pma
Пожалуйста, подскажите, а есть вариант реализовать подобную задачу через событие клавиатуры? Интересуюсь на будущее, для других похожих задач

Можно, а почему нет. Какая разница.
<!DOCTYPE HTML>
<html>
  <head><meta charset="windows-1251" /> </head>
  <body>

<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">

    <script>
digits=document.getElementsByClassName("digit")
filter=function (e) {
   console.log(e.keyCode)
   if(/\D+/g.test(this.value)) this.value=this.value.replace(/\D+/gi, "")
}
for(i in digits){if(/\d+/.test(i)) digits[i].onkeyup=filter}




    </script>
  </body>
</html>

Только притормаживает немного у меня в FF

klk.pma 21.11.2014 20:19

krutoy, а этот скрипт должен быть только после всех инпутов или его можно размещать в подключаемый файл в head?

krutoy 21.11.2014 20:24

Цитата:

Сообщение от klk.pma (Сообщение 342237)
krutoy, а этот скрипт должен быть только после всех инпутов или его можно размещать в подключаемый файл?

Вообще, я думаю, все скрипты работающие с контентом лучше размещать в конце body. А подключаемый ли он из внешнего файла, или инлайн -- это, вроде, не особо важно. Он инициализируется в нужное время, все равно.

devote 21.11.2014 20:25

Цитата:

Сообщение от klk.pma
первый раз увидел такой перебор цикла for(i in digits)

Увидели, а теперь забудьте... Это очень плохая практика перебирать коллекции таким образом. А перед тем как перенять опыт, подумайте, может не зря этот человек krutoy, имеет в карме сплошной минус. А я поясню, ему еще самому многому надо поучиться перед тем как давать советы другим.

Памятка!
JavaScript хороший и динамичный язык, многое может делать разными вариантами в этом есть и плюсы и минусы. А минусы в том, что каждый день большая часть квалифицированных разработчиков бьются над производительностью кода. А подобные конструкции:
Цитата:

Сообщение от krutoy
for(i in digits){if(/\d+/.test(i)) digits[i].oninput=filter}

не ускоряют процесс а лишь затормаживают, во вторых этот подход сложно читаемый. Например вот этот код:
for(var index = digits.length; index--;) {
  digits[index].oninput=filter;
}
как минимум будет работать в 100 раз быстрее, намного приятнее и легко читается. Во вторых переменные нужно инициализировать, как можно меньше использовать регулярные выражения, особенно там где от них нет проку и т.д.

danik.js 21.11.2014 20:28

Цитата:

Сообщение от klk.pma
Кстати, первый раз увидел такой перебор цикла for(i in digits)

Он больной на голову, не используй такой перебор. В будущем будет for .. of ну а пока нужно использовать перебор по индексу.
Кстати что мешает применить скрипт к number типу? Я вот ща с мобилы - так мне клава числовая открылась. Я не могу туда букву ввести даже без скрипта.

krutoy 21.11.2014 20:31

devote,
ко-ко-ко. Над производительностью бьются мартышки. инженер пишет прототип и оптимизирует узкие места.

krutoy 21.11.2014 20:48

Цитата:

Сообщение от devote
как минимум будет работать в 100 раз быстрее

А заодно я солью тебя в говнецо, раз уж ты высунулся
<!DOCTYPE HTML>
<html>
  <head><meta charset="windows-1251" /> </head>
  <body>

<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">

    <script>
get=function(){
  var el=document.createElement("input")
  el.setAttribute("class", "digit")
  document.body.appendChild(el)
}
count=1000
while(count--) get() 
digits=document.getElementsByClassName("digit")
func1=function(){alert(1)}
func2=function(){alert(2)}

console.time("for in")
for(i in digits){if(/\d+/.test(i)) digits[i].onkeyup=func1}
console.timeEnd("for in")

console.time("for")
for(var index = digits.length; index--;) {
  digits[index].oninput=func2;
}
console.timeEnd("for")

//FF:
//for in: timer started start_page.html:22
//for in: 0ms start_page.html:24
//for: timer started start_page.html:26
//for: 16ms
    </script>
  </body>
</html>

Другой, нижеотписавшийся "мастер" вообще не стоит внимания.

klk.pma 21.11.2014 20:50

Цитата:

Сообщение от danik.js (Сообщение 342242)
Он больной на голову, не используй такой перебор. В будущем будет for .. of ну а пока нужно использовать перебор по индексу.
Кстати что мешает применить скрипт к number типу? Я вот ща с мобилы - так мне клава числовая открылась. Я не могу туда букву ввести даже без скрипта.

Number не во всех браузерах работает

klk.pma 21.11.2014 20:52

Если представленный вариант неправильный, можете показать корректный вариант?

krutoy 21.11.2014 20:55

klk.pma,
Да не, они просто домохались до for in, якобы, он медленный (у дебилов он действительно может быть медленным, но в целом -- это гон, см тест выше), замени на for, если хочешь, и все.
<!DOCTYPE HTML>
<html>
  <head><meta charset="windows-1251" /> </head>
  <body>
 
<input class="digit" type="text" maxlength="8" name="ot" value="">
<input class="digit" type="text" maxlength="8" name="do" value="">
 
    <script>
digits=document.getElementsByClassName("digit")
filter=function () {
   if(/\D+/g.test(this.value)) this.value=this.value.replace(/\D+/g, "")
}

//for(i in digits){if(/\d+/.test(i)) digits[i].oninput=filter}


for(var i = digits.length; i--;) {
  digits[i].oninput=filter;
}
    </script>
  </body>
</html>

devote 21.11.2014 21:33

krutoy, я не знаю что у тебя за ФФ такой, который за никакое время умудряется выполнить код, но у меня результаты иные. Конечно про 100 раз я говорил образно, но как минимум в 2-4 раза точно быстрее..

Chrome:
for in: 4.000ms
for: 1.000ms

IE 11:
for in: 9.8345 мс
for: 5.8308 мс

FF:
for in: таймер запущен showhtml:21
for in: 5.17мс showhtml:23
for: таймер запущен showhtml:25
for: 2.53мс

Цитата:

Сообщение от krutoy
у дебилов он действительно может быть медленным, но в целом -- это гон, см тест выше

А это тебе предупреждение от меня, еще одно оскорбление и пойдешь в самый долгий бан. Я не припоминаю что бы я тебя оскорбил, дык вот будь добр разговаривать адекватно.

krutoy 21.11.2014 21:47

devote,
Я извиняюсь за резкие слова, но то слово относилось не к тебе лично, а к абстрактному дебилу в вакууме, как-бы, так что не принимай на свой личный счет.

Что касаемо for-in, мифы о его медлительности, как мне кажется, рождены из-за его кривого использования. Он итеритует объект вместе со всей цепочкой прототипов, поэтому, если вовремя не выйти из цикла, он будет заниматься перебором бесполезных полей. Его смело можно применять, как правило, если место не суперузкое, только с умом.

devote 21.11.2014 21:52

Цитата:

Сообщение от klk.pma
Если представленный вариант неправильный, можете показать корректный вариант?

представленный вариант не учитывает сдвиг курсора при вводе данных, а так же конечно кроссбраузерность, например в ИЕ9 нажатие клавиши backspace не вызывает событие oninput. И прочие мелочи, что бы все это учеть нужно намного больше написать. Либо использовать уже существующие решения, например вот этой:
<script type="text/javascript" src="http://devote.github.io/files/letjs/let.js"></script>
<input data-let-input="/^\d+$/" class="digit" type="text" maxlength="8" name="ot" value="">
<input data-let-input="/^\d+$/" class="digit" type="text" maxlength="8" name="do" value="">

devote 21.11.2014 21:55

Цитата:

Сообщение от krutoy
Его смело можно применять, как правило, если место не суперузкое, только с умом.

в том то и дело что его можно и нужно применять там, где без его применения иного способа нет. Я этого не по наслышке а по собственному опыту говорю, когда писал CSS-селектор, именно там производительность играла огромную роль. А использование конструкции for...in мне вставляло камни под колеса.

krutoy 21.11.2014 21:56

Цитата:

Сообщение от devote
сдвиг курсора при вводе данных

А какое он имеет значение?
Цитата:

Сообщение от devote
нажатие клавиши backspace не вызывает событие oninput

И что? по бекспейсу печатается нецифровой символ?

krutoy 21.11.2014 22:00

Цитата:

Сообщение от devote
именно там производительность играла огромную роль

Вот где играет, там и не надо писать. Я об этом уже сказал. Если так параноить над каждой строкой кода, совершенству нет предела, будешь до конца жизни один скрипт оптимизировать. forEach, например, тоже работает ОЧЕНЬ медленно.

devote 21.11.2014 22:01

Цитата:

Сообщение от krutoy
А какое он имеет значение?

курсор ввода, всегда должен оставаться там где его оставил пользователь. А когда меняешь свойство .value у текстового поля, курсор уходит в конец текстового поля. Что не совсем правильно.
Цитата:

Сообщение от krutoy
И что? по бекспейсу печатается нецифровой символ?

Ничего не печатается, а удаляется символ находящийся перед курсором ввода. Но, на это действие ИЕ9 никак не реагирует и не вызывает событие oninput (это просто Баг ИЕ9). Другие события, такие как keypress, keydown и т.д отрабатывают корректно.

krutoy 21.11.2014 22:02

devote,
Кстати, насчет теста я не соврал. В хроме у меня for отработал, в среднем, процентов на 20 быстрей. Видимо, жедезо и ось играет роль.

devote 21.11.2014 22:02

Цитата:

Сообщение от krutoy
forEach, например, тоже работает ОЧЕНЬ медленно.

ну было бы странно если бы он работал быстрее.. Он же на каждую итерацию вызывает функцию, а вызов функции пожирает большие ресурсы.

krutoy 21.11.2014 22:06

Цитата:

Сообщение от devote
Ничего не печатается, а удаляется символ находящийся перед курсором ввода. Но, на это действие ИЕ9 никак не реагирует и не вызывает событие oninput (это просто Баг ИЕ9)

но в данном случае оно и не нужно.

krutoy 21.11.2014 22:09

Цитата:

Сообщение от devote
Другие события, такие как keypress, keydown и т.д отрабатывают корректно.

Я, кстати, протестил события, они работают на порядок медленней oninput в FF и V8. А V8 вообще тормозной при работе с текстовыми полями, я уже который раз замечаю.

krutoy 21.11.2014 22:21

Цитата:

Сообщение от devote
не учитывает сдвиг курсора при вводе данных

А нет ли способа для контроля положения курсора? А то, можно было бы и обработать, (хотя это мелочь, в данном случае, это произойдет только если пользователь сдвинет курсор что-то исправлять и введет при этом нецифровой символ --можно забить на это)

devote 21.11.2014 22:29

вот в этом посте я привел в пример библиотеку, которая все это учитывает, более подробно о ней можно почитать тут: http://javascript.ru/forum/project/3...rea-input.html

krutoy 21.11.2014 22:40

Цитата:

Сообщение от devote
ну было бы странно если бы он работал быстрее.. Он же на каждую итерацию вызывает функцию, а вызов функции пожирает большие ресурсы.

Навряд ли в этом дело. Скорей, в кривости реализации.
Array.prototype.foreach=function(f){
   for(var i=0; i<this.length; i++) f(this[i])
}

arr=[]
i=10000
while(i--){arr.push(i)}

tst=function(x){return x + 1}
console.time("forEach")
arr.forEach(tst)
console.timeEnd("forEach")
console.time("foreach")
arr.foreach(tst)
console.timeEnd("foreach")

// forEach: 58ms
// foreach: 1ms

devote 22.11.2014 00:07

Цитата:

Сообщение от krutoy
Скорей, в кривости реализации.

не в кривости а в требованиях, оригинальная реализация выглядит примерно так:
Array.prototype.foreach = function (callback, thisArg) {

  var T, k;

  if (this == null) {
    throw new TypeError(' this is null or not defined');
  }

  // 1. Положим O равным результату вызова ToObject passing the |this| value as the argument.
  var O = Object(this);

  // 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
  // 3. Положим len равным ToUint32(lenValue).
  var len = O.length >>> 0;

  // 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
  // Смотрите: [url]http://es5.github.com/#x9.11[/url]
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }

  // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
  if (arguments.length > 1) {
    T = thisArg;
  }

  // 6. Положим k равным 0
  k = 0;

  // 7. Пока k < len, будем повторять
  while (k < len) {

    var kValue;

    // a. Положим Pk равным ToString(k).
    //   Это неявное преобразование для левостороннего операнда в операторе in
    // b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
    //   Этот шаг может быть объединён с шагом c
    // c. Если kPresent равен true, то
    if (k in O) {

      // i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
      kValue = O[k];

      // ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
      // списком аргументов, содержащим kValue, k и O.
      callback.call(T, kValue, k, O);
    }
    // d. Увеличим k на 1.
    k++;
  }
  // 8. Вернём undefined.
};
 
arr=[]
i=10000
while(i--){arr.push(i)}
 
tst=function(x){return x + 1}
console.time("forEach")
arr.forEach(tst)
console.timeEnd("forEach")
console.time("foreach")
arr.foreach(tst)
console.timeEnd("foreach")

//  Chrome: 
//    forEach: 1.000ms
//    foreach: 1.000ms

danik.js 22.11.2014 09:30

Цитата:

Сообщение от klk.pma
Number не во всех браузерах работает

Во всех. Даже в IE5.5 :)
Цитата:

Сообщение от krutoy
Да не, они просто домохались до for in, якобы, он медленный

Дело не в скорости. Дело в говнистости кода ) Говнокодерам без разницы как писать.

Для наитупейшего обхода элементов массива задействовать машину регулярных выражений - это победа :victory: .

klk.pma 22.11.2014 10:25

Цитата:

Сообщение от danik.js (Сообщение 342304)
Во всех. Даже в IE5.5 :).

С каких это пор html5 работает в ie5 и уж тем более в ie 5.5 ))

kostyanet 23.11.2014 10:38

Цитата:

Сообщение от klk.pma
Если есть один input, то это можно реализовать через это:

Через это

form.addEventListener('input',validate);

и вперде

в инпуте есть тип - тот самый number. Если брауз - копенгаген, то все само будет работать, а если туп - то вы берете getAttribute('type') и получаете number и, соответственно, проверяете по своему любимому паттерну.

Это геморройный способ сугубой сраной оптимизации. Легкая избыточность данных существенно все облегчает - х на type, он вообще может быть любым - пишите в pattern свой паттерн и JS вам проверит все что угодно по этому паттерну. Ну, если бразуер тупит.

kostyanet 23.11.2014 10:47

Так вот, у меня тоже есть вопрос - а возможно ли перевести взад на человеческий язык криптографию регулярного выражения?

Например

if(len && input.pattern && !new RegExp(input.pattern).test(value))
	throw 'Здесь '+input.errmsg;


Чтобы сообщить что-то осмысленное, а не просто типа "введите перпендикулярно", приходится в том же месте откуда берутся паттерны задавать сообщения об ошибках проверки по паттерну - errmsg.

А было бы круто чтобы программа сама, разобралась в требованиях шаблона проверки и написала, типа: Здесь минимум 3 символа, которые должны быть все печатными.

kostyanet 23.11.2014 10:58

Цитата:

Сообщение от krutoy
и введет при этом нецифровой символ

Это признак слабости ума разраба - вписывать юзера в свою историю болезни. Не понимая что делать с ошибочным вводом, не имея налаженной системы прерываний по ошибкам - разраб бросается на амбразуру всем телом пытаясь перекрыть кислородо юзеру.

Понятно откуда ноги воняют? На фронтире, типа, усе сразу получить _правильно_ и тогда налаживать обратную связь и не надо. Лафа!

Так вот вполне понятно что без всякого текстового поля можно обойтись и захерачить ему какие хочешь нахуй буквы вместо цифр и посмотреть как сервер чмокнет.

ЗЫ Не должен js заниматься санитарией. Потому что обойти его ленточки - как два пальца об асфальт. Вся санитария будет только на сервере, который и сообщит что юзер ввел не перпедикулярно. JS может только проверить и написать что ввели хуйню, по сему факту задизаблить сабмит формы и все такое. Но корежить данные - не должен. Что отправилось - на то сервер только отвечает.


Часовой пояс GMT +3, время: 13:33.