LINUX.ORG.RU

JavaScript: поставить onkeydown через function(){...}


0

0

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

Скрипт, в общем, уже готов, но есть небольшие проблемы с красотой.

Я хочу, чтобы по инициализации формы обработчики onkeydown и onSubmit ставились автоматически. Делаю это так:

document.getElementById(formId).onSubmit = function(){return ENFlag;};
document.getElementById(formId).onkeydown = function(event){return ENNext(event);};

Ошибок JS не выдаёт, но... ничего не работает. И даже event в функцию не передаётся. Если же поставить onSubmit и onkeydown дедовским способом — прямо в тэге FORM — всё работает идеально.

Что можно ещё попробовать?


Ответ на: комментарий от archimag

Добавил вот такой код:

if (thisForm.attachEvent) {
thisForm.attachEvent(«onsubmit», function(){ return KFN.submit(); });
} else if (document.forms[0].addEventListener) {
thisForm.addEventListener(«submit», function() { return KFN.submit(); }, false);
}
...
submit : function () {
alert ('HERE!');
return false;
}
...

Однако он ни разу не работает. Целью перехвата было предотвращение субмита формы по нажатию Enter в Opera.

Реально Enter не отрабатывается вообще, а если нажать на кнопку субмита формы вручную, браузер покажет алерт «HERE!» и... таки субмитит форму несмотря на возвращаемое false.

Ritz
() автор топика
Ответ на: комментарий от Ritz

> таки субмитит форму несмотря на возвращаемое false.

Гы, может стоит подучить JavaScript? Он немного сложнее, чем кажется на первый взгляд ;)

А по теме, таки юзай jquery и плагин jquery.form - будет самый простой и быстрый вариант.

archimag ★★★
()
Ответ на: комментарий от archimag

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

Про jquery — я с тобой согласен. Наверное, соберусь как-нибудь с духом и освою.

Ritz
() автор топика
Ответ на: комментарий от Ritz

Возможно вы имели в виду

var thisForm = document.getElementById("f");
if (thisForm.addEventListener) {
    thisForm.addEventListener("submit", function(e) { e.preventDefault(); }, false);
} else if (thisForm.attachEvent) {
    thisForm.attachEvent("onsubmit", function(e){ e.preventDefault(); });
};

?

Deleted
()
Ответ на: Возможно вы имели в виду от Deleted

Спасибо, это сработало. Однако, почему-то, только для этого конкретного случая. Следующими моими шагами было разрешить submit с кнопок, добавить autocomplete=off для форм и добавить onkeydown=«return MyFunc(event)».

Я попытался перенести код с addEventListener — но безо всякого успеха. Попробовал тогда вот так:

if (e[i].type == «submit») {
  e[i].submit = function(){ this.form.submit(); };
}

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

e[i].hasFocus=false;
e[i].onfocus=function(){this.hasFocus=true;};
e[i].onblur =function(){this.hasFocus=false;};

У такое такое ощущение, что function(){...} работает по какому-то хитровыдуманному алгоритму, который я понимаю неправильно.

PS: А как правильно называется тэг [code] на LOR?

Ritz
() автор топика
Ответ на: комментарий от Ritz

e.submit =

«e.onsubmit =»?

Я попытался перенести код с addEventListener — но безо всякого успеха

<div>
	<form id="f" action="#">
		<input type="text" name="t"/>
		<input type="submit"/>
	</form>
</div>
var thisForm = document.getElementById("f");
if(window.addEventListener){
	thisForm.addEventListener("submit", function(e) { alert("Moo"); e.preventDefault(); }, false);
	thisForm.addEventListener("keydown", function(e) { alert("alert"); }, false);
}else{
	if(window.attachEvent){
		// Не помню как там в IE, наверное так...
		thisForm.attachEvent("onsubmit", function(e) { alert("Moo"); e.preventDefault(); });
		thisForm.attachEvent("onkeydown", function(e) { alert("alert"); });
	}else{
		// Too bad...
	};
};

А как правильно называется

Так и называется :) Просто если хочешь подсветку, то надо указывать тип, т.е. «code=css» или, там, «code=javascript» (без кавычек). Ну и режим сообщения LORCODE выбрать.

Deleted
()
Ответ на: комментарий от Deleted

Спасибо. Теперь работает почти всё и во всех браузерах. Кроме субмита формы по нажатию мышкой на кнопку.

onsubmit и onpress попробовал: не помогло. На всякий случай, вот мой код:

/**
*
*  Keyboard Form Navigation
*  Использование: в конце документа исполните KFN.init ('form1');
*  В самой форме укажите параметр autocomplete="off"
*
**/

// Фокусируется на элементе
function setFocus(id) {
  document.getElementById(id).focus();
  setTimeout("document.getElementById('"+id+"').select();", 100);
}

// Возвращает случайный ID, не присутствующий ещё в документе
function randomId (){
  do {
    var newId = "rnd" + Math.floor((Math.random() * 1000000));
  }
  while (document.getElementById(newId) != null);
  return newId;
}

var KFN = {

  // Список полей формы, по которым надо перемещаться стрелками
  _elements : [],

  // Форма субмиттится только если _flag == true
  _opera_allow : true,

  // Субмитит форму. Нужен, чтобы форма не субмитилась в Опере по каждому энтеру
  submit : function () {
    if (!this._opera_allow)
      return false;
  },

  // Инициализирует форму для работы со стрелками и Enter
  // Меняет onFocus у всех полей формы.
  init : function (formId) {
    var thisForm = document.getElementById(formId);
    if (thisForm.addEventListener) { 
      thisForm.addEventListener("submit", function(e) { e.preventDefault(); }, false); 
      thisForm.addEventListener("keydown", function(e) { KFN.next(e); }, false);
    } else if (thisForm.attachEvent) { 
      thisForm.attachEvent("onsubmit", function(e) { e.preventDefault(); }); 
      thisForm.attachEvent("onkeydown", function(e) { KFN.next(e); }); 
    }
    for (var i = 0 , e = thisForm.elements, len = e.length; i < len; i++ ) {
      if (/text|password|file|checkbox|radio|select/.test (e[i].type)) {
        // Если у поля нет id, ставим какой-нибудь
        if (!e[i].id) e[i].id = randomId();
        this._elements.push (e[i].id);
        // Без этих самодельных обработок мы бы не узнали, на каком элементе фокус
        e[i].hasFocus=false;
        e[i].onfocus=function(){this.hasFocus=true;};
        e[i].onblur =function(){this.hasFocus=false;};
      } else if (e[i].type == "submit") {
        e[i].onPress = function(){ this.form.submit(); };
      }
    }
    // Фокусируемся на первом поле формы
    setFocus (this._elements[0]);
  },

  // Переходит к следующему полю формы
  next: function (input) {
    // Обрабатываем только три клавиши. 13: Enter, 38: Up, 40: Down
    if ((input.keyCode != 13) && (input.keyCode != 38) && (input.keyCode != 40))
      return true;
    // Находим текущий элемент (по фокусу)
    for (var i=0; i<this._elements.length; i++)
      if (document.getElementById(this._elements[i]).hasFocus)
        var current = i;
    // Перемещаем фокус
    switch (input.keyCode) {
      case 13: // Enter
        if ((current + 1) < this._elements.length) {
          this._opera_allow = false // Субмиттить не надо
          setFocus (this._elements[1+current]);
        } else {
          this._opera_allow = true;
          document.getElementById(this._elements[current]).form.submit();
        }
        break;
      case 38: // Вверх
        current--;
        if (current < 0) current = 0;
        setFocus (this._elements[current]);
        break;
      case 40: // Вниз
        current++;
        if (current == this._elements.length) current = this._elements.length - 1;
        setFocus (this._elements[current]);
        break;
    }
    return false;
  }
}

Форма:

<form action="something.cgi" id="form1" autocomplete="off")>
  Логин: <input name="login"><br>
  Пароль: <input type="password" name="password"><br>
  <input type="submit" value="Войти в систему">
</form>

<script>
KFN.init('form1');
</script>
Ritz
() автор топика
Ответ на: комментарий от Deleted

А в каком браузере? У меня FireFox 3.6.3. не работает. Опера и Ослик тоже не хотят.

То есть, по Enter и стрелочкам всё путём, а мышкой не давится, хоть клавишу сломай.

Ritz
() автор топика
Ответ на: комментарий от Ritz

В Опере же. Документ весь здесь? Хмм… выложи куда-нибудь на pastebin полный, если нет и если не секретный :}

Deleted
()
Ответ на: комментарий от Deleted

Вот мой секретный документ целиком:

<html>
<head>
  <title>KFN тест</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script src="KFN.js" type="text/javascript"></script>
</head>
<body>
<form action="something.cgi" id="form1" autocomplete="off"> 
  Логин: <input name="login"><br> 
  Пароль: <input type="password" name="password"><br> 
  <input type="submit" value="Войти в систему"> 
</form> 
 
<script> 
  KFN.init('form1'); 
</script>
</body>
</html>

Опера 10.51. При нажатии на кнопку мышью визуально нажимается кнопка и… больше не происходит ничего. Алсо Ослик внезапно нашёл какие-то ошибки, чем сильно меня расстроил.

Про keyCode буду сейчас читать.

Ritz
() автор топика
Ответ на: комментарий от Ritz

Капитан очевидность снова с вами:

Поскольку ты сделал thisForm.addEventListener(«submit», function(e) { e.preventDefault(); }, false); то форма засабмитится только из кода :)

А вообще, ты делаешь велосипед, да ещё такой страшненький :} Лучше научи пользователей волшебным сочетаниям Tab и shift + Tab.

Deleted
()

Еврейский способ ☺

Добавляешь в init после var thisForm = document.getElementById(formId);

var go_button = document.getElementById(formId + "-go");
go_button.type = "button";

Плюс в обработчиках поставишь:

go_button.addEventListener("click", function(e) { thisForm.submit(); }, false); 

и соответственный ему вариант с attachEvent().

Ставишь на сабмит-кнопку id=«from1-id» и вперёд. Если не хочется id, то тогда придётся обойти все элементы формы и найти те, у которых type == «submit» и на них повесить обработчик.

Deleted
()
Ответ на: комментарий от Deleted

Там у меня целая история с пользователями, привыкшими к магии Excel. Если вкратце, попросили сделать именно стрелочки и Enter, и я решил, что самой малой кровью будет такой метод.

Буду пробовать сегодня твой рецепт.

Ritz
() автор топика
Ответ на: Еврейский способ ☺ от Deleted

Твой рецепт сработал, хоть и не сразу.

1. Как выяснилось, обработчик click срабатывает при каждом нажатии Enter, поэтому пришлось ставить дополнительно проверку: есть ли на субмит-клавише фокус.

2. Оказалось, что Ослику вместо «click» надо писать «onclick», а вместо event.preventDefault(); надо ставить event.returnValue = false;

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

(Правда, я так и не понял, как поставить autocomplete=off на форму из javascript, но, думаю, это уже мелочи).

Ritz
() автор топика
Ответ на: комментарий от Ritz

Несовместимость DOM'ов это те ещё породы дерева сами по себе %)

как поставить autocomplete=off на форму из javascript


setAttribute() не работает?

Deleted
()
Ответ на: комментарий от Deleted

Однако. Убрал «autocomplete=off», а ненужный autocomplete внезапно не появился.

Так что оставлю пока подсказанное тобой решение в таком виде, для будущих поколений:

// thisForm.setAttribute("autocomplete", "off")

В любом случае, сбылась мечта бесчисленных поколений. После 8 часов браузероёбства функция родилась ровно в том виде, в каком я хотел.

Ritz
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.