2010-12-13 3 views
0

Я преобразовываю значения на основе единиц (км до м, от lb до g и т. Д.). У меня есть работа, за исключением одной ошибки, которую я не могу решить.Обработка клавиатуры в раскрывающемся списке

Вот функция, которая обрабатывает события (преобразование происходит в JQuery плагин):

function unitConversion() { 
    var from; 

    // Remember which unit was selected in the drop down list. 
    $('select.unit').live('click', function() { 
     from = $(this).find('option:selected').text(); 
    }); 

    // Now handle the conversion. 
    $('select.unit').live('change', function() { 
     // Get the from and to values. 
     // var from = $(this).prev().find('option:selected').text(); 
     var to = $(this).find('option:selected').text(); 

     // Change the text for each field that corresponds with this component. 
     var textBoxes = $(this).closest('div.data-group').find('input:text'); 
     textBoxes.each(function() { 
      var curValue = $(this).val(); 
      $(this).val($(this).unitConvert({ 
       value: curValue, 
       from: from, 
       to: to 
      })); 
     }); 
    }); 
} 

Это прекрасно работает (хотя, если у вас есть какие-либо усовершенствования этого кода, я всегда желая учиться). Однако первоначальная проблема, которую я испытывал, состояла в том, что я должен был помнить предыдущую выбранную единицу в раскрывающемся списке. Следовательно, событие «click», которое я делаю.

Это решение отлично работает ... до тех пор, пока человек использует мышь. Однако, если я вставляю в раскрывающийся список с клавиатурой и нажимаю клавиши со стрелками вверх/вниз, ничего не происходит. Я пробовал различные ключевые события *, и они тоже не работают. Что я должен делать здесь для ввода клавиатуры и мыши?

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

Update: Я хотел бы предоставить некоторые дополнительные разъяснения.

Если я использую событие фокуса, то преобразования становятся странными. Причина в том, что я только устанавливаю значение «from» в первый раз, когда получаю фокус. Если я хочу, чтобы преобразование выполнялось правильно каждый раз, я должен потерять фокус на раскрывающемся списке, а затем выполнить этот процесс. Не очень полезно.

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

ответ

1

Я бы внести два изменения в свой код.

Сначала убедитесь, что ваши варианты имеют как text и value:

<select> 
    <option value="km">KM</option> 
    ... 
</select> 

Тогда вместо того, чтобы делать $('select.unit').find('option:selected').text(); Вы можете просто написать:

$('select.unit').val(); 

Это также более правильно, как вы можете показать другой текст к значению, например, показывать «километры» пользователю, но все равно иметь значение «км» для работы с плагином.

Теперь на реальную проблему ...

Самый простой способ «помнить» предыдущее состояние приложить данные к самому элементу. Лучший способ сделать это, избегая утечек памяти и всех других проблем, заключается в использовании jQuery's data(). Просто дайте ему имя и значение, и он запомнит его по выбранному элементу по вашему выбору.

// Now handle the conversion. 
$('select.unit').live('change', function() { 
    // Get the from and to values. 
    var from = $(this).data("from"); 
    var to = $(this).val(); 

    // Remember the from value for next time 
    $(this).data("from", to); 

    // Change the text for each field that corresponds with this component. 
    var textBoxes = $(this).closest('div.data-group').find('input:text'); 
    textBoxes.each(function() { 
     var curValue = $(this).val(); 
     $(this).val($(this).unitConvert({ 
      value: curValue, 
      from: from, 
      to: to 
     })); 
    }); 
}); 

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

$(function() { 
    $('select.unit').each(function() { 
     $(this).data("from", $(this).val()); 
    }); 
}); 
+0

Отличный ответ! Спасибо. Я не понимал, что данные даже существуют. Угадайте, что это показывает, что всегда есть чему поучиться. Большое спасибо. – JasCav

0

Вместо того чтобы слушать click, вы должны просто посмотреть за focus. Это должно работать как для мыши, так и для клавиатуры.

+0

не работает. Дополнительную информацию см. В обновлении моего вопроса. Спасибо за помощь. – JasCav

0

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

Этот способ _from всегда будет удерживать ранее выбранное значение выпадающего списка.

Пример кода:

var _prevSelectedValues = new Array(); 
$(function() { 
    $("select").each(function(index) { 
     _prevSelectedValues[$(this).attr("id")] = $(this).val(); 
     $(this).change(function() { 
      var id = $(this).attr("id"); 
      alert("prev: " + _prevSelectedValues[id] + ", current: " + $(this).val()); 
      _prevSelectedValues[id] = $(this).val(); 
     }); 
    }); 
}); 

Тестовый пример: http://jsfiddle.net/TuHnB/

+0

Хорошая идея. Будет ли это работать, если у меня есть несколько выпадающих списков на странице (в частности $ ('select.unit'))? – JasCav

+0

@JasCav: в случае нескольких выпадающих списков make '_from' ключ/массив значений, например. 'from [" ddl1 "] =" last_val ";' и ключ будет идентификатором каждого раскрывающегося списка. –

+0

Хм ... Я не уверен, что знаю, как это сделать. Если бы вы могли привести пример в своем ответе, это было бы очень оценено. – JasCav

Смежные вопросы