2009-08-21 3 views
5

Я пытаюсь создать веб-страницу, которая загружается в зависимости от введенного ввода. В основном у меня возникают проблемы с тем, чтобы обернуть голову вокруг обработки событий в javascript. Исходя из python, если бы я хотел подождать ввода определенной клавиатуры, прежде чем переходить к следующему объекту для отображения, я бы создал цикл , а и положил в него прослушиватель клавиш.Обработка и управление событиями Javascript

Python:

def getInput(): 
    while 1: 
    for event in pygame.event.get(): #returns a list of events from the keyboard/mouse 
     if event.type == KEYDOWN: 
     if event.key == "enter": # for example 
      do function() 
      return 
     elif event.key == "up": 
      do function2() 
      continue 
     else: continue # for clarity 

В попытке найти способ реализовать это в DOM/JavaScript, я, кажется, просто врезаться страницу (я предполагаю, что из-за While Loop), но я полагаю, это происходит потому, что плохо обрабатывается обработка событий. Кроме того, регистрация обработчиков событий с помощью "element.onkeydown = function;" мне трудно оборачивать голову, а setInterval (foo(), interval] не принес мне большого успеха.

В принципе, я хочу, чтобы цикл «прослушивания» выполнял определенное поведение для ключа X, но для перерыв, когда клавиша Y ударил.

ответ

8

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

Таким образом, вы не можете иметь «прослушивающий» цикл. Браузер делает это для вас, давая вам событие и позволяя вам справиться с этим, но как только вы закончите обработку события, вы должны вернуться. Вы не можете вернуться в другой цикл. Это означает, что вы не можете писать пошаговый процедурный код; если у вас есть состояние, которое сохраняется между вызовами событий, вы должны его сохранить, например. в переменной.

Такой подход не может работать:

<input type="text" readonly="readonly" value="" id="status" /> 

var s= document.getElementById('status'); 
s.value= 'Press A now'; 
while (true) { 
    var e= eventLoop.nextKeyEvent(); // THERE IS NO SUCH THING AS THIS 
    if (e.which=='a') 
     break 
} 
s.value= 'Press Y or N'; 
while (true) { 
    var e= eventLoop.nextKeyEvent(); 
    if (e.which=='y') ... 

Шаг за шагом код должен быть вывернута наизнанку, так что браузер вызывает к вам, а не вы вызова в браузере:

var state= 0; 
function keypressed(event) { 
    var key= String.fromCharCode(event? event.which : window.event.keyCode); // IE compatibility 
    switch (state) { 
     case 0: 
      if (key=='a') { 
       s.value= 'Press Y or N'; 
       state++; 
      } 
      break; 
     case 1: 
      if (key=='y') ... 
      break; 
    } 
} 

s.value= 'Press A now'; 
document.onkeypress= keypressed; 

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

s.value= 'Press A now'; 
document.onkeypress= function(event) { 
    var key= String.fromCharCode(event? event.which : window.event.keyCode); 
    if (key=='a') { 
     s.value= 'Press Y or N'; 
     document.onkeypress= function(event) { 
      var key= String.fromCharCode(event? event.which : window.event.keyCode); 
      if (key=='y') ... 
     }; 
    } 
}; 
+1

Спасибо, bobince. Ваш комментарий о том, какой пошаговый процедурный код очень хорошо рассмотрел мою проблему. Хотел бы, чтобы у меня хватило репутации, чтобы укрепить тебя. – intelligencer

1

вы не должны использовать такие циклы в JavaScript. в основном вы не хотите, чтобы заблокировать браузер делать свою работу. Таким образом, вы работаете с событиями (OnKeyUp/вниз).

также вместо цикла вам следует использовать setTimeout, если вы хотите немного подождать и продолжить, если что-то произошло

вы можете сделать так:

<html> 
<script> 
var dataToLoad = new Array('data1', 'data2', 'data3'); 
var pos = 0; 
function continueData(ev) { 
    // do whatever checks you need about key 
    var ele = document.getElementById("mydata"); 
    if (pos < dataToLoad.length) 
    { 
    ele.appendChild(document.createTextNode(dataToLoad[pos])); 
    pos++; 
    } 
} 
</script> 
<body onkeyup="continueData()"><div id="mydata"></div></body></html> 

каждый раз, когда клавиша отпущена поле следующие данные добавляются

+0

Если вам нужно использовать объект события в обработчике, что 'ev' должен действительно быть' event', так как это имя, под которым он передается в функцию. IE, конечно, является «специальным» и назначает объект события глобальному «window.event», а не передает его функции обработчика событий в 'event'. – kangax

+0

true - вам, очевидно, нужно настроить код для работы с различными нажатиями клавиш/релизами. Я пытался продемонстрировать, как решить проблему while-loop. – Niko

0

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

Вы не можете иметь бесконечный цикл в javascript. Вместо этого присоедините прослушиватель событий к окну и укажите обработку в обработчике (подумайте об этом как о прерываниях вместо опроса).

Пример:

function addEventSimple(obj,evt,fn) { 
    if (obj.addEventListener) 
     obj.addEventListener(evt,fn,false); 
    else if (obj.attachEvent) 
     obj.attachEvent('on'+evt,fn); 
} // method pulled from quirksmode.org for cross-browser compatibility 

addEventSimple(window, "keydown", function(e) { 
    // check keys 
}); 
0
document.onkeydown = function(e) { 
    //do what you need to do 
} 

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

0

вы можете прикрепить прослушиватель события к объекту окна, как этот

window.captureEvents(Event.KEYPRESS); 
window.onkeypress = output; 
function output(event) { 
    alert("you pressed" + event.which); 
} 
0

Выезд ключ слушателя YUI

http://developer.yahoo.com/yui/docs/YAHOO.util.KeyListener.html

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

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

http://developer.yahoo.com/yui/examples/event/eventsimple.html

1

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

Для того, чтобы использовать их, вы должны иметь в виду 3 вещи:

  • Что DOM элемент, который вы хотите наблюдать
  • Что событие вы хотите, чтобы захватить
  • Какие действия триггера событий

Эти три очка являются взаимоисключающими, что означает, что вам необходимо позаботиться о 3 при написании кода.

Так иметь это в виду, используя прототип, вы можете сделать это:

Event.observe($('id_of_the_element_to_observe'), 'keypress', function(ev) { 
    // the argument ev is the event object that has some useful information such 
    // as which keycode was pressed. 
    code_to_run; 
}); 

Вот код более полезным, например, CharacterCounter (например, один нашел в Twitter, но, конечно, много менее надежны;)):

var CharacterCounter = Class.create({ 

    initialize: function(input, counter, max_chars) { 
    this.input = input; 
    this.counter = counter; 
    this.max_chars = max_chars; 
    Event.observe(this.input, 'keypress', this.keyPressHandler.bind(this)); 
    Event.observe(this.input, 'keyup', this.keyUpHandler.bind(this)); 
    }, 

    keyUpHandler: function() { 
    words_left = this.max_chars - $F(this.input).length; 
    this.counter.innerHTML = words_left; 
    }, 

    keyPressHandler: function(e) { 
    words_left = this.max_chars - $F(this.input).length; 
    if (words_left <= 0 && this.allowedChars(e.keyCode)) { 
     e.stop(); 
    } 
    }, 

    allowedChars: function(keycode) { 
    // 8: backspace, 37-40: arrow keys, 46: delete 
    allowed_keycodes = [ 8, 37, 38, 39, 40, 46 ]; 
    if (allowed_keycodes.include(keycode)) { 
     return false; 
    } 
    return true 
    } 

}); 
Смежные вопросы