JavaScript - обнаружение изменений в текстовой области - PullRequest
4 голосов
/ 20 сентября 2009

Я бы хотел, чтобы значение двух текстовых полей всегда было одинаковым. Прослушивания события 'change' недостаточно, потому что я хочу, чтобы эти поля были равны, даже если у кого-то есть фокус. Прослушивание нажатия клавиши также не работает, так как это событие вызывается до того, как значение поля обновляется новой буквой, поэтому я не уверен, есть ли хороший способ получить текущее значение поля с помощью обработчика нажатия клавиши чтобы скопировать его в другое поле. Есть идеи?

Ответы [ 5 ]

4 голосов
/ 20 сентября 2009

Как насчет события keyup?

2 голосов
/ 29 марта 2012

У меня та же проблема ...

Значение текстовой области может быть изменено многими способами ... Я упомяну только те, которые я не знаю, как обнаружить:

  • Мышь контекстная вставка
  • Клавиатура контекстного меню Вставить
  • Перетаскивание из другого приложения, объекта и т. Д.
  • Shift Drag & Drop из того же текста (дублирует выбранный контент в другой позиции)
  • Выполнение Ctrl + Вставка - Shift + Вставка (еще один способ копирования и вставки)

Я пытался создать обработчик событий для каждого события, которое я знаю (onkeyup, onkeydown, onmouseup, onmousedown и т. Д.), Но с некоторыми из предыдущих способов сделать вставку, никто не запускается, поэтому нет способа контролировать, когда происходит.

Я не вижу другого решения, кроме установки таймера.

Ах! содержимое также может меняться без фокуса ... случаи перетаскивания.

И не говоря уже о том, может ли также быть изменен JavaScript, самая страшная вещь для dected ... никакой метод не запускается !!!

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

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

С таймерами, которые вы всегда должны ставить на разгрузку страницы, поэтому деактивируйте или уничтожайте, когда страница убита, например, когда вы переходите на другую страницу.

Подобные вещи усложняют гораздо больше, чем необходимо, и ужасно обновлять в будущем.

Чтобы гарантировать, что таймеры не выйдут из строя, я делаю такую ​​уродливую вещь, как первое предложение: clearTimeout(MyTimer);

И если мне нужно, чтобы таймер повторял каждые X миллисекунд ... внутри функции я делаю setTimeout(function(){MyFunction();)

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

Кроме того, в каждом предложении внутри функции MyFunction должна контролироваться ошибка ... любой используемый объект должен быть уверен, что существует ... в каждом предложении ... это невозможно сделать ... так что попытка catch должна быть добавлено.

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

Чтобы убедиться, что Таймер не запущен ... Единственное, что я знаю, это обслуживать тело при загрузке ... но некоторые уродливые браузеры не запускают его (чтобы программист не позволил вам перейти на другую страницу) .. ... поэтому я должен делать вещи так, как будто onunload не существует ... чтобы таймер можно было вызывать при уничтожении объектов ... ошибки могут возникать всегда ...

Слишком сложно, чтобы при использовании таймеров не появлялись окна ошибок:

var MyTimer;
function MyTimer_Handler(){
 try{
  clearTimeout(TemporizadorCapaLogin);
  try{
   // Do whatever the timer must do
  }Catch(theError){
   // Your own code to control errors, but have in mind that while running the lines you write here can also cause error because while running this the objects get destroyed, so better not to put anything
  }
  MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);
 }Catch(theError){}
}
try{MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);}Catch(theError){}

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

Ну, это еще хуже, чтобы действительно убедиться, что вы попробуете это:

var MyTimer;
function MyTimer_Handler(){
 try{
  clearTimeout(TemporizadorCapaLogin);

  try{
   // Do only one sentence at a time
  }Catch(theError){} // Ther is no way to ensure any line on Catch part can not cause an error because objects can have being destroyed before and while running this part

  try{
   // Do only one sentence at a time
  }Catch(theError){} // Ther is no way to ensure any line on Catch part can not cause an error because objects can have being destroyed before and while running this part

  // Repeat for each sentence

  MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);
 }Catch(theError){}
}
try{MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);}Catch(theError){}

Но такая защита Try {} Catch {} такая же, как группировка всех по одному ... так что никакой выгоды ... как вы можете видеть, таймеры очень болезненны для использования ... просто потому, что нет никакого способа чтобы гарантировать отсутствие ошибок.

Причина заключается в последовательности событий в некоторых браузерах:

  1. Пользователь запрашивает страницу
  2. Страница загружена
  3. Страница активации таймера
  4. Пользователь нажимает на ссылку или просто закрывает вкладку ... это приводит к разгрузке страницы
  5. Браузер начинает уничтожать объект за объектом
  6. Прежде чем все уничтожат таймер и сработают
  7. Код по таймеру запущен, но некоторые объекты не существуют, были уничтожены
  8. Пока работает такой код, браузер продолжает уничтожать больше объектов (Одновременно)

Например, пока выполняется любая строка кода внутри таймера, менеджер JavaScript может быть уничтожен в некоторых браузерах, и поэтому он не будет работать, и браузер отобразит модальное окно, сообщающее, что ваша страница плохо закодирована, предложение также может быть так просто: alert('bla bla bla');

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

var MyTimer;
function MyTimer_Handler(){
 try{
  clearTimeout(TemporizadorCapaLogin);
  try{
   // Do whatever the timer must do
  }Catch(theError){}
  MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);
 }Catch(theError){}
}
try{MyTimer=setTimeout(function(){try{MyTimer_Handler()}Catch(theError){}},theIntervalToRepeatInMiliseconds);}Catch(theError){}

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

Но так как иногда, кое-что нужно делать через некоторое время ... не имея лучшего / идеального решения, это лучшее, что я могу сделать !!

Лично я ненавижу такие плохо закодированные браузеры (одним из них является IE), но я должен их поддерживать !!!

0 голосов
/ 08 февраля 2011

Keyup не работает правильно при использовании shift + letter, но работает нормально, если вы привязываете его к объекту window.

Вот плагин jQuery, который использует его:

$.fn.edited = function(callback) {
  this.each(function() {

    var that = $(this);
    var active = false;

    that.focusin(function() {
      active = true;
    });

    that.focusout(function() {
      active = false;
    });

    $(window).keyup(function(e) {
      if (active) {
        callback(e);
      }
    });

  });
};   

Использование:

$("textarea").edited(function(){
    ...
});
0 голосов
/ 20 сентября 2009

//

function clonekeyup(e){
 var e= window.event || e;
 var who= e.target || e.srcElement;
 var val= who.value;
 var tem, temp, TA= document.getElementsByTagName('textarea'), L= TA.length;
 while(L){
  tem= TA[--L];
  if(tem.onchange== arguments.callee && tem.value!= val) tem.value= val;
 }
}

Назначьте функции onkeyup и onchange текстовым областям, которые вы хотите отобразить друг другу. Например, это присваивает обработчику все текстовые области.

var tem, TA= document.getElementsByTagName('textarea'), L= TA.length;
while(L){
 tem= TA[--L];
 tem.onkeyup= tem.onchange= clonekeyup;
}
0 голосов
/ 20 сентября 2009

Методы, специфичные для браузера, обсуждались здесь: onpropertychange для текстового поля в Firefox?

Однако после различных экспериментов я обнаружил, что единственным кросс-браузерным методом было использование window.setInterval () для проверки изменений (например, каждые 20 миллисекунд). Не элегантно, но очень эффективно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...