Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Странное поведение readonly (https://javascript.ru/forum/dom-window/45762-strannoe-povedenie-readonly.html)

ArtemKrass 15.03.2014 14:41

Странное поведение readonly
 
Всем доброго дня!

Использую плагин jQuery Text Change Event http://zurb.com/playground/jquery-te...e-custom-event для отслеживания событий...

Имеем два текстовых поля:
<input type="text" id="1" name="1" value="" size="12" maxlength="10" class="form-text required">
        <br />
<input type="text" id="2" name="2" value="" size="12" maxlength="10" class="form-text required">


и код:

jQuery('#1:not(.disabled)').bind('textchange', function (event, previousText) {
    if (jQuery(this).hasClass("disabled") == false) {
    if (jQuery(this).val().length > 0) {
          jQuery('#2').addClass('disabled').attr("readonly","readonly");
    }
    else   jQuery('#2').removeClass('disabled').removeAttr("readonly", "readonly" );
  jQuery('#2').val(jQuery(this).val());
    }
});



jQuery('#2:not(.disabled)').bind('textchange', function (event, previousText) {
alert ('Hello');    
});


В первое поле что-нибудь вводим... Второму полю добавляется класс disabled и атрибут readonly.

Вроде бы все правильно, НО:

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

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

Вот готовый код:

http://jsfiddle.net/kjv7a/

ArtemKrass 15.03.2014 15:12

Как сделать так, чтобы событие textchange вызывалось во втором поле только при условии что у поля отсутствует класс disabled?

jQuery('#2:not(.disabled)') как видно из моего кода не помогает... А почему?

NeoN 15.03.2014 15:59

есть вариант сделать так

jQuery('#1:not(.disabled)').bind('textchange', function (event, previousText) {
    if (jQuery(this).hasClass("disabled") == false) {
		if (jQuery(this).val().length > 0) {
		      jQuery('#2').addClass('disabled').attr("readonly","readonly").unbind('textchange');

		}
		else   jQuery('#2').removeClass('disabled').removeAttr("readonly", "readonly" ).bind('textchange', function (event, previousText) {
			alert ('Hello');    
		});

  		jQuery('#2').val(jQuery(this).val());
    }

});
jQuery('#2:not(.disabled)').bind('textchange', function (event, previousText) {
	alert ('Hello');    
});

NeoN 15.03.2014 16:15

или так... наверное, еще лучше)

jQuery('#1:not(.disabled)').bind('textchange', function (event, previousText) {
    if (jQuery(this).hasClass("disabled") == false) {
    if (jQuery(this).val().length > 0) {
          jQuery('#2').addClass('disabled').attr("readonly","readonly");
    }
    else   jQuery('#2').removeClass('disabled').removeAttr("readonly", "readonly" );
  jQuery('#2').val(jQuery(this).val());
    }
});


jQuery('#2').on('textchange',':not(.disabled)', function (event, previousText) {
	alert ('Hello');    
});



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

при использовании on() функция прикрепляется к элементу только после срабатывания нужного события.

вывод: использование on() предпочтительней в данном случае. но нужен jquery версии не ниже 1.7

danik.js 15.03.2014 16:29

А нельзя понастоящему дизейблить? .prop('disabled', true)
Вместо работы с атрибутами нужно делать так:
.prop('readOnly', true), .prop('readOnly', false)

ArtemKrass 15.03.2014 16:37

К сожалению дизейблить нельзя, так как данные из полей потом нужно использовать...

рони 15.03.2014 17:53

ArtemKrass,
а можно узнать зачем вам плагин и что должен делать ваш код, из ваших описаний я плохо понял

рони 15.03.2014 18:08

ArtemKrass,
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <script type='text/javascript' src='http://code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript'>
 $(function () {
      $("body").on('input', '#1:not(.disabled)',
          function () {
              if (this.value.length > 0) {
                  $('#2').addClass('disabled').prop("readonly", true);
              } else $('#2').removeClass('disabled').prop("readonly", false);
              jQuery('#2').val(this.value)
          }

      ).on('input', '#2:not(.disabled)', function () {
          alert('Hello');
      });
  });
</script>
</head>

<body>
<input type="text" id="1" name="1" value="" size="12" maxlength="10" class="form-text required">
        <br />
<input type="text" id="2" name="2" value="" size="12" maxlength="10" class="form-text required">
</body>

</html>

ArtemKrass 15.03.2014 18:14

Есть три текстовых поля
площадь
общая цена
цена за 1м

Плагин отслеживает все события ввода, в том числе и paste мышью и т.д.

Так вот, мне нужно чтобы при вводе пользователем площади и какой-нибудь из цен автоматически просчитывалась бы другая...

Поэтому при вводе в одну из цен, вторую мне нужно делать readonly...
Но если пользователь удалил цену, то возвращать все в первоначальное положение.

Не знаю, может я все усложнил... Есть ли способы попроще? За намек буду премного благодарен...

рони 15.03.2014 18:19

ArtemKrass,
удалил цену == 0, нет цены цена ноль так разве не проще -- нет площади площать ноль

ArtemKrass 15.03.2014 18:31

Пусть ноль, но мне нужно запретить пользователям ставить в оба поля цену. Одна из них подставляется автоматом....

рони 15.03.2014 18:40

Простейший калькулятор
 
Цитата:

Сообщение от ArtemKrass
Одна из них подставляется автоматом....

тогда как они поставят цену если она автоматом. снова непонимаю вас.
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <script type='text/javascript' src='http://code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript'>
 $(function () {
      var inputs = $('#1, #2,#3');
      $("body").on('input', inputs, function () {
              var area = parseFloat(inputs[0].value)||0,
              price = parseFloat(inputs[1].value)||0,
              summ = area * price;
              inputs[2].value = summ.toFixed(2)
          });
  });
</script>
</head>

<body>
<label for="1">площадь
<input type="text" id="1" name="1" value="" size="12" maxlength="10" class="form-text required"></label>
       <br />
<label for="2">цена за 1м
<input type="text" id="2" name="2" value="" size="12" maxlength="10" class="form-text required"></label>
       <br />
<label for="3">общая цена
<input type="text" id="3" name="2" value="" size="12" maxlength="10" class="form-text required" readonly="readonly"></label>
</body>

</html>

ArtemKrass 15.03.2014 18:45

Вся проблема в том, что изначально пользователь может выбрать какую цену ему вводить, либо за 1 м, либо общую... Как только он ввел цену в какое-то из полей, другое нужно делать readonly.

У меня получилась огромная портянка из условий. Но толком не работает.

рони 15.03.2014 19:11

Цитата:

Сообщение от ArtemKrass
Как только он ввел цену в какое-то из полей, другое нужно делать readonly

:-?
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <script type='text/javascript' src='http://code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript'>
 $(function () {
      var inputs = $('#1, #2, #3');
      $("body").on('input', '#1:not(.disabled), #2:not(.disabled), #3:not(.disabled)', function () {
                if (this.value.length > 0) {
                inputs.not(this).addClass('disabled').prop("readonly", true);
              }
              else {inputs.removeClass('disabled').prop("readonly", false)};
          });
  });
</script>
</head>

<body>
<label for="1">площадь
<input type="text" id="1" name="1" value="" size="12" maxlength="10" class="form-text required"></label>
       <br />
<label for="2">цена за 1м
<input type="text" id="2" name="2" value="" size="12" maxlength="10" class="form-text required"></label>
       <br />
<label for="3">общая цена
<input type="text" id="3" name="2" value="" size="12" maxlength="10" class="form-text required" ></label>
</body>

</html>

ArtemKrass 15.03.2014 19:48

Все ли браузеры поддержат такой код? Спасибо большущее за помощь...

рони 15.03.2014 20:27

Цитата:

Сообщение от ArtemKrass
Все ли браузеры поддержат такой код?

кроме ie ниже 9 http://learn.javascript.ru/events-change#событие-input

ArtemKrass 20.03.2014 09:07

рони,
Огромное Спасибо! С меня +++

danik.js 20.03.2014 11:12

Цитата:

Сообщение от рони
кроме ie ниже 9

Если писать $("body").on('input propertychange') то должно и в IE8 сработать.


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