Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   в input с цифрой добавить текст со склонением (https://javascript.ru/forum/misc/72704-v-input-s-cifrojj-dobavit-tekst-so-skloneniem.html)

the_little 20.02.2018 16:03

в input с цифрой добавить текст со склонением
 
Вложений: 1
Всем привет.

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

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

Например
1 комната
2 комнаты
5 комнат

Это первый вопрос.

Есть второй... Таких полей на странице много. И у разных полей этот текст после цифры разный. Вариантов всего 5 (комната, санузел, час, шт. и никакого текста). Можно как то эти тексты в самих инпутах прописать или еще как то, чтобы скрипт был один. Или придется делать несколько скриптов под каждое слово после числа.

Выводится сейчас это все на бутстрапе.
<div class="input-group">
                  <span class="input-group-btn">
                      <button type="button" class="btn btn-default btn-number btn-minus" disabled="disabled" data-type="minus" data-field="quant[1]">
                          <i class="material-icons">remove</i>
                      </button>
                  </span>
                  <input type="text" name="quant[1]" class="form-control input-number" value="1" min="1" max="30">
                  <span class="input-group-btn">
                      <button type="button" class="btn btn-default btn-number btn-plus" data-type="plus" data-field="quant[1]">
                          <i class="material-icons">add</i>
                      </button>
                  </span>
              </div>


И скрипт который за это отвечает.
//plugin bootstrap minus and plus
//http://jsfiddle.net/laelitenetwork/puJ6G/
$('.btn-number').click(function(e){
    e.preventDefault();

    fieldName = $(this).attr('data-field');
    type      = $(this).attr('data-type');
    var input = $("input[name='"+fieldName+"']");
    var currentVal = parseInt(input.val());
    if (!isNaN(currentVal)) {
        if(type == 'minus') {

            if(currentVal > input.attr('min')) {
                input.val(currentVal - 1).change();
            }
            if(parseInt(input.val()) == input.attr('min')) {
                $(this).attr('disabled', true);
            }

        } else if(type == 'plus') {

            if(currentVal < input.attr('max')) {
                input.val(currentVal + 1).change();
            }
            if(parseInt(input.val()) == input.attr('max')) {
                $(this).attr('disabled', true);
            }

        }
    } else {
        input.val(0);
    }
});
$('.input-number').focusin(function(){
   $(this).data('oldValue', $(this).val());
});
$('.input-number').change(function() {

    minValue =  parseInt($(this).attr('min'));
    maxValue =  parseInt($(this).attr('max'));
    valueCurrent = parseInt($(this).val());

    name = $(this).attr('name');
    if(valueCurrent >= minValue) {
        $(".btn-number[data-type='minus'][data-field='"+name+"']").removeAttr('disabled')
    } else {
        alert('Sorry, the minimum value was reached');
        $(this).val($(this).data('oldValue'));
    }
    if(valueCurrent <= maxValue) {
        $(".btn-number[data-type='plus'][data-field='"+name+"']").removeAttr('disabled')
    } else {
        alert('Sorry, the maximum value was reached');
        $(this).val($(this).data('oldValue'));
    }

});
$(".input-number").keydown(function (e) {
        // Allow: backspace, delete, tab, escape, enter and .
        if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 190]) !== -1 ||
             // Allow: Ctrl+A
            (e.keyCode == 65 && e.ctrlKey === true) ||
             // Allow: home, end, left, right
            (e.keyCode >= 35 && e.keyCode <= 39)) {
                 // let it happen, don't do anything
                 return;
        }
        // Ensure that it is a number and stop the keypress
        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
            e.preventDefault();
        }
    });


Буду благодарен за помощь.
Моих знаний хватает, чтобы просто добавить там еще один объект (див или спан), выставить его так, чтобы выглядело что это в инпуте, считывать значение с инпута и выводить туда текст со склонением.
И я бы так и сделал, но есть нюанс. Поскольку числа могут быть и с 1 символом и с 2, то текст мой будет фиксированное положение иметь, и для маленьких чисел будет большой пробел оставаться между числом и текстом.

Но наверное есть вариант другой?

j0hnik 20.02.2018 16:06

Обсуждалось недавно, вот почитайте темку.
https://javascript.ru/forum/misc/725...it-skript.html

ksa 20.02.2018 16:17

Вот готовые решения...

the_little 20.02.2018 16:37

Спасибо!
Сами функции склонения я видел и даже применял как-то))
Я не понимаю как это вставить в мой скрипт в нужное поле.

Например
input.val(currentVal - 1).change();

Как я понимаю тут уменьшается на 1 значение currentVal
Я же не могу тут написать
input.val(currentVal - 1 + " " + myvar).change();

the_little 20.02.2018 16:47

И там же например текущее значение
var currentVal = parseInt(input.val());


По идее я и туда должен добавить свою текстовую переменную.

var currentVal = parseInt(input.val() + " " + myvar);

Хотя var currentVal должен в результате все равно вернуть число.

j0hnik 20.02.2018 17:10

Не вникал во весь скрипт просто добавил две функции, посмотрите как устроено
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
	<div class="input-group">
		<span class="input-group-btn">
			<button type="button" class="btn btn-default btn-number btn-minus" disabled="disabled" data-type="minus" data-field="quant[1]">
				<i class="material-icons">remove</i>
			</button>
		</span>
		<input type="text" name="quant[1]" class="form-control input-number" value="1" min="1" max="30">
		<span class="input-group-btn">
			<button type="button" class="btn btn-default btn-number btn-plus" data-type="plus" data-field="quant[1]">
				<i class="material-icons">add</i>
			</button>
		</span>
	</div>

	<div id="res"></div>

	<script>

		f=(n, arr) => n+" "+arr[(n%100>4 && n%100<20)?2:[2, 0, 1, 1, 1, 2][(n%10<5)?n%10:5]];  
		var mass = ['комната', 'комнаты', 'комнат'];
		s=(val)=>$('#res').text(f(val, mass));

		//plugin bootstrap minus and plus
//http://jsfiddle.net/laelitenetwork/puJ6G/
$('.btn-number').click(function(e){
	e.preventDefault();

	fieldName = $(this).attr('data-field');
	type      = $(this).attr('data-type');
	var input = $("input[name='"+fieldName+"']");
	var currentVal = parseInt(input.val());
	if (!isNaN(currentVal)) {
		if(type == 'minus') {

			if(currentVal > input.attr('min')) {
				input.val(currentVal - 1).change();
			}
			if(parseInt(input.val()) == input.attr('min')) {
				$(this).attr('disabled', true);
			}

		} else if(type == 'plus') {

			if(currentVal < input.attr('max')) {
				input.val(currentVal + 1).change();
			}
			if(parseInt(input.val()) == input.attr('max')) {
				$(this).attr('disabled', true);
			}

		}
	} else {
		input.val(0);
	}
});
$('.input-number').focusin(function(){
	$(this).data('oldValue', $(this).val());
});
$('.input-number').change(function() {

	minValue =  parseInt($(this).attr('min'));
	maxValue =  parseInt($(this).attr('max'));
	valueCurrent = parseInt($(this).val());

	var mass = ['комната', 'комнаты', 'комнат'];

s(valueCurrent);

	name = $(this).attr('name');
	if(valueCurrent >= minValue) {
		$(".btn-number[data-type='minus'][data-field='"+name+"']").removeAttr('disabled')
	} else {
		alert('Sorry, the minimum value was reached');
		$(this).val($(this).data('oldValue'));
	}
	if(valueCurrent <= maxValue) {
		$(".btn-number[data-type='plus'][data-field='"+name+"']").removeAttr('disabled')
	} else {
		alert('Sorry, the maximum value was reached');
		$(this).val($(this).data('oldValue'));
	}

});
$(".input-number").keydown(function (e) {
        // Allow: backspace, delete, tab, escape, enter and .
        if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 190]) !== -1 ||
             // Allow: Ctrl+A
             (e.keyCode == 65 && e.ctrlKey === true) ||
             // Allow: home, end, left, right
             (e.keyCode >= 35 && e.keyCode <= 39)) {
                 // let it happen, don't do anything
               return;
             }
        // Ensure that it is a number and stop the keypress
        if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
        	e.preventDefault();
        }
      });



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

the_little 20.02.2018 17:28

Цитата:

Сообщение от j0hnik (Сообщение 478637)
Не вникал во весь скрипт просто добавил две функции, посмотрите как устроено

Спасибо! Только вот вопрос можно ли сделать так, чтобы это выводилось непосредственно в инпуте? Или нужно все-таки этот див накладывать сверху?

j0hnik 20.02.2018 17:46

Конечно можно!
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<button>-</button><input type="text"><button>+</button><br>
	<button>-</button><input type="text"><button>+</button><br>
	<button>-</button><input type="text"><button>+</button><br>
	<script>

		var sklon = (n, arr) => n+" "+arr[(n%100>4 && n%100<20)?2:[2, 0, 1, 1, 1, 2][(n%10<5)?n%10:5]],
		ap = (val,n) => inp[n].value = sklon(val, arr[n]);

		var arr = [['комната', 'комнаты', 'комнат'],['санузел', 'санузла', 'санузлов'],['час', 'часа', 'часов']],
		inp = document.querySelectorAll('input');
		inp.forEach((el, i)=>{
			el.value = 0;
			var val;
			el.previousElementSibling.onclick = e => {
				val = parseInt(el.value);
				if (val > 0) val--;
				ap(val,i);
			};
			el.nextElementSibling.onclick = e => {
				val = parseInt(el.value);
				val++;
				ap(val,i);
			};
			el.onchange = e => {
				val = el.value;
				ap(parseInt(el.value),i);
			}
		});

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

Dilettante_Pro 20.02.2018 18:00

j0hnik,
Только input теперь не input - в него вводить нельзя, только кнопочками

j0hnik 20.02.2018 18:07

Dilettante_Pro,
теперь можно
Это обработчик oninput не давал вводить, перебивал на лету =(

Dilettante_Pro 20.02.2018 18:18

j0hnik,
При чередовании вводов и плюсов в какой-то момент получается
NaN комнат
Не понял пока, с чем связано - отвлекают.

j0hnik 20.02.2018 18:25

Dilettante_Pro,
Видимо пытались текст вводить а не цифры

рони 20.02.2018 19:09

j0hnik,
val--; за ноль уходит и ap выдаёт -1 undefined

Dilettante_Pro 20.02.2018 19:14

j0hnik,
При плюсе или минусе после редактирования значения без очистки поля - менять только цифры - выдает ошибку.
Немного помогает - при сохранении пробела
el.onchange = e => {
val = el.value.split(" ")[0];
ap(parseInt(el.value),i);
}
А вообще нужен регексп по прочистке значения

Все, пока убежал.

j0hnik 20.02.2018 19:15

рони,
if (val > 0) добавил проверку

j0hnik 20.02.2018 19:25

Dilettante_Pro,
Исправил.

the_little 20.02.2018 20:31

так, сейчас буду разбираться.
1 вопрос. Допустим у меня на странице 30 инпутов. Одни обычные текстовые для личных данных и адреса. И 15 инпутов в которых нужно применять вот этот скрипт с плюсами, минусами и выводом текста.
Как теперь указать скрипту те инпуты, в которые ему нужно лезть, а в какие не нужно?
2 вопрос. Допустим идет 3 инпута в которых склоняется одно слово, потом 2 инпута в которых склоняется другое слово. Скрипт получается идет сверху вниз по всем инпутам и в них делает подстановки? Т.е. нужно в массиве просто 3 раза подряд прописать одно и тоже?

j0hnik 20.02.2018 20:32

Один ответ на 2 вопроса, присвоить определенные классы и использовать их!

и в массиве 3 раза прописывать не надо. не гуд это.

the_little 20.02.2018 21:24

Цитата:

Сообщение от j0hnik (Сообщение 478668)
Один ответ на 2 вопроса, присвоить определенные классы и использовать их!

и в массиве 3 раза прописывать не надо. не гуд это.

Ну по поводу перебора инпутов как я понял нужно где-то тут
inp = document.querySelectorAll('input');

добавить что только инпуты с определенным классом.

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

j0hnik 20.02.2018 21:52

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
		<button>-</button><input type="text"><button>+</button><br>
	<button>-</button><input type="text" class="san"><button>+</button><br>
	<button>-</button><input type="text" class="san"><button>+</button><br>
	<button>-</button><input type="text" class="kom"><button>+</button><br>
	<button>-</button><input type="text"><button>+</button><br>
	<button>-</button><input type="text" class="chas"><button>+</button><br>
	<button>-</button><input type="text"><button>+</button><br>
	<script>

		var sklon = (n, obj) => n+" "+obj[(n%100>4 && n%100<20)?2:[2, 0, 1, 1, 1, 2][(n%10<5)?n%10:5]];

		var obj = {kom:['комната', 'комнаты', 'комнат'],
							san:['санузел', 'санузла', 'санузлов'],
							chas:['час', 'часа', 'часов']},
		inp = document.querySelectorAll('.san, .kom, .chas');
		inp.forEach((el, i)=>{
			el.value = 0;
			var val, cl = el.className;
			el.previousElementSibling.onclick = e => {
				val = parseInt(el.value);
				if (val > 0) val--;
				el.value = sklon(val, obj[cl]);
			};
			el.nextElementSibling.onclick = e => {
				val = parseInt(el.value);
				val++;
				el.value = sklon(val, obj[cl]);
			};
			el.onchange = e => {
				val = parseInt(el.value);
				e.target.value = sklon(val, obj[cl]);
			};
		});

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


вместо класса можно использовать любые другие доступные атрибуты.

the_little 20.02.2018 22:43

Цитата:

Сообщение от j0hnik (Сообщение 478689)

вместо класса можно использовать любые другие доступные атрибуты.

вот это круть. Спасибо огромное!

понял. теперь и фильтруют только инпуты с нужными классами и текстовые вставки делаются в зависимости от класса.

the_little 21.02.2018 08:48

Помогите пожалуйста.

Вставил скрипт и инпуты на сайт. Работают как надо.
Но потом увидел, что в форме ниже при нажатии на плюс или минус срабатывает проверка на правильность заполнения полей. И все загорается красным (потому что еще не заполнено.

Если я убираю скрипт, который за это отвечает - то перестает работать инпут новый. На плюс нажимаю, +1 происходит, и потом возвращается обратно на 0.

Что не так делаю?

// Example starter JavaScript for disabling form submissions if there are invalid fields
    (function() {
      'use strict';
      window.addEventListener('load', function() {
        // Fetch all the forms we want to apply custom Bootstrap validation styles to
        var forms = document.getElementsByClassName('needs-validation');
        // Loop over them and prevent submission
        var validation = Array.prototype.filter.call(forms, function(form) {
          form.addEventListener('submit', function(event) {
            if (form.checkValidity() === false) {
              event.preventDefault();
              event.stopPropagation();
            }
            form.classList.add('was-validated');
          }, false);
        });
      }, false);
    })();


    var sklon = (n, obj) => n+" "+obj[(n%100>4 && n%100<20)?2:[2, 0, 1, 1, 1, 2][(n%10<5)?n%10:5]];

  		var obj = {kom:['комната', 'комнаты', 'комнат'],
  							san:['санузел', 'санузла', 'санузлов'],
  							chas:['час', 'часа', 'часов']},
  		inp = document.querySelectorAll('.san, .kom, .chas');
  		inp.forEach((el, i)=>{
  			el.value = 0;
  			var val, cl = el.className;
  			el.previousElementSibling.onclick = e => {
  				val = parseInt(el.value);
  				if (val > 0) val--;
  				el.value = sklon(val, obj[cl]);
  			};
  			el.nextElementSibling.onclick = e => {
  				val = parseInt(el.value);
  				val++;
  				el.value = sklon(val, obj[cl]);
  			};
  			el.onchange = e => {
  				val = parseInt(el.value);
  				e.target.value = sklon(val, obj[cl]);
  			};
  		});

the_little 21.02.2018 11:01

А как в этих инпутах отслеживать изменения и получать из них значения.

я попробовал в инпуте прописать onchange="alert(this.value)", но он никак не реагирует на изменения в инпуте.

ksa 21.02.2018 11:20

Цитата:

Сообщение от the_little
я попробовал в инпуте прописать onchange="alert(this.value)", но он никак не реагирует на изменения в инпуте.

Дело в том, что onchange наступает после потери фокуса на твоем инпуте. Т.е. нужно "покинуть" поле, тогда сработает событие.

Dilettante_Pro 21.02.2018 11:51

the_little,
Обработчик события change уже прописан в вашем скрипте - строки 40-43 в примере пост№22.
Так что не надо ничего вписывать в инпут - вписывайте в этот обработчик.
Там и значение уже есть.

the_little 21.02.2018 11:55

Цитата:

Сообщение от Dilettante_Pro (Сообщение 478711)
the_little,
Обработчик события change уже прописан в вашем скрипте - строки 40-43 в примере пост№22.
Так что не надо ничего вписывать в инпут - вписывайте в этот обработчик.
Там и значение уже есть.

В инпут я вписывал для проверки.
У меня каждый инпут имеет свой id.
И я пытался получить для одного значение val, но ничего не получалось.


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