Более быстрый способ заполнить <select> с помощью Javascript
У меня есть два блока <select> в форме. Выбор элемента в первом поле <select> определяет, что должно появиться во втором <select> (Использование Ajax http_request).
В некоторых случаях во втором выборе могут быть большие 500 (предположения), и для IE в IE требуется время 5-10 секунд. Firefox отлично работает.
Интересно, есть ли более быстрый способ достичь этого. В настоящее время сервер создает строку, передающую ее клиенту, который затем разбивается и добавляет каждый элемент к выбору, создавая элемент option, а затем добавляя его в <select> .
Я попытался создать весь элемент select как строку на сервере и добавить его в форму, но по какой-то причине он не будет работать в Firefox (пропустил что-то?)
Спасибо
Ответы
Ответ 1
500 элементов не много, даже для IE. Вы должны делать что-то еще, чтобы вызвать отставание.
Я только что попробовал более 500 опций в IE6, IE7, FF2 и FF3, и все они были близки мгновенно. Я использовал этот код:
var data = [
{ text: 'foo', value: 'bar' },
// ...
{ text: 'foo', value: 'bar' }
];
var select = document.getElementsByTagName('select')[0];
select.options.length = 0; // clear out existing items
for(var i=0; i < data.length; i++) {
var d = data[i];
select.options.add(new Option(d.text, i))
}
Я бы предложил профилировать бит кода, который извлекает данные и заполняет их. Что-то еще может занять время. Например, проверьте, что код, который "разбивает" строковое значение, возвращаемое с сервера, является резким (похоже, что вы делаете свой собственный собственный синтаксический анализ).
Ответ 2
Первый код в порядке, но это работает лучше для меня:
var data = [
{ text: 'uno', value: '1' },
{text: 'dos', value: '2' }
];
var select = document.getElementById('select-choice-1');
select.options.length = 0; // clear out existing items
for (var i = 0; i < data.length; i++) {
var d = data[i];
select.options.add(new Option(d.text, d.value))
}
Ответ 3
Установка его с помощью SelectElement.innerHTML будет самой быстрой... но что FAILS в IE.
Последнее, что я проверил, вы можете сделать это в IE, если вы обернете все параметры в фиктивном теге <div> или установите весь .outerHTML списка выбора в IE.
Ответ 4
Проблема со всеми этими ответами с SelectElement.innerHTML заключается в том, что вы не можете сделать этот трюк с помощью SELECT. Решение состоит в том, чтобы использовать innerHTML в PARENT самого элемента SELECT. Таким образом, в вашем ajax/jquery/любом коде создайте строку, содержащую ВСЕ ВЫБОР HTML, а затем получите держатель (div или span или что-то еще) и установите innerHTML в строку, которую вы создали.
Вам нужно будет изолировать SELECT со страницы и предоставить ей явный родительский элемент (span или div), чтобы другие элементы html не были жертвами при уничтожении/восстановлении элемента SELECT.
Короткий ответ:
parentselectelement.removeChild(selectelement);
parentselectelement.innerHTML = "<select ...><options...></select>";
Ответ 5
Я бы создал целый select на сервере и ввел его на страницу. Этот подход обходит неудобства браузеров и снижает сложность клиентского кода.
Вы упоминали, что вы это пробовали, но он не работал в firefox. Я бы посоветовал настойчиво добиваться его работы, опубликования другого вопроса с просьбой о помощи по этой проблеме или редактирования вашего вопроса, чтобы показать нам, что вы сделали, что не работает в firefox.
Ответ 6
Не забудьте добавить к document.createDocumentFragment()
сначала, прежде чем добавить это к SELECT.
Ответ 7
Это поможет значительно увидеть ваш код.
ЕСЛИ вы создаете элемент <option>
и добавляете его на каждую итерацию, вы должны сразу создать все элементы <option>
, а затем добавить их все сразу.
Итак (в psuedocode):
// Don't do this:
for choice in choices:
option = new Options(choice)
select.append(option)
// Do this instead
var options = array()
for choice in choices:
options.append( new Options(choice) )
for option in options:
select.append(option)
// Or you might try building the select element off-screen and then appending to the DOM
var options = array()
var select = new SelectElement()
for choice in choices:
select.append( new Options(choice) )
dom_element.append(select)
Ответ 8
Когда я использую первую версию этого, он работает, но может быть очень медленным при обновлении второго выбора
<html>
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'>
<table>
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr>
<tr><td><select id='selectid'></select></td></tr>
</table>
</form>
</html>
<script type=\"text/javascript\">
function UPDATE( updatedata )
{
var itemid = document.getElementById('selectid');
var data = updatedata.split( '|' );
var len = data.length;
for( i=0; i < len; i ++ )
{
var opt = document.createElement('option');
opt.text = data[i];
try
{
itemid.add( opt, null );
}
catch(ex)
{
itemid.add( opt );
}
}
}
</script>
Эта версия работает в IE, но firefox, похоже, не публикует второй выбор данных. Я пропустил что-то с этим.
<html>
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'>
<table>
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr>
<tr><td><div id='addselect'></div></td></tr>
</table>
</form>
</html>
<script type=\"text/javascript\">
function UPDATE( updatedata )
{
// update data is full select html
var itemid = document.getElementById('addselect');
itemid.innerHTML = updatedata;
}
</script>
Ответ 9
Мне нравятся ответы Crescent Fresh и Kemal Fadillah, так как оба используют:
select.options.add(new Options(name, value))
Что касается объекта данных, я рекомендую небольшую настройку следующим образом:
var data = {
'uno': 1,
'dos': 2
};
var select = document.getElementById('select-choice-1');
select.options.length = 0; // clear out existing items
for (var i in data) {
select.options.add(new Option(i, data[i]));
}
Ответ 10
Если вы не против использования CoffeeScript, то следующий код заполняет список выбора данными JSON в нескольких строках.
HTML
<select id="clients"></select>
CoffeeScript
fillList=($list, url)=>
$.getJSON(url)
.success((data)->
$list
.empty()
.append("<option value=\"#{item.Id}\">#{item.Name}</option>" for item in data)
)
$ ->
fillList($('#clients'), '/clients/all')
Примечание. Цикл внутри append
генерирует всю строку html перед вызовом метода append
один раз. Это приятно и эффективно.
Пример JSON
[
{"Id":"1","Name":"Client-1"},
{"Id":"2","Name":"Client-2"}
]