Более быстрый способ заполнить <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"}
]