Копейки, уверяю. Я не знаю как делается запрос на сервере и что возвращает, но принцип должен быть следующим - запрос должен возвращать записи, которые отсортированы по родителю. Вот пример, где объект, это возвращенный сервером запрос в базу. name_group - это имя группы (в ответе может быть и id группы, если нужен, в дальнейшем можно и по нему расклад делать, но это не столь важно), два остальных параметра, это параметры опций.
Ну и собственно само построение списка:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
var s = [
{
name_group : 'name 1',
id_option : 2,
name_option : 'option 1'
},
{
name_group : 'name 1',
id_option : 3,
name_option : 'option 2'
},
{
name_group : 'name 1',
id_option : 4,
name_option : 'option 3'
},
{
name_group : 'name 2',
id_option : 5,
name_option : 'option 4'
},
{
name_group : 'name 2',
id_option : 6,
name_option : 'option 5'
},
{
name_group : 'name 2',
id_option : 7,
name_option : 'option 6'
}
], sel, grp, name;
$(function() {
sel = $('<select/>').appendTo('body');
$.each(s, function() {
if(this.name_group != name) {
name = this.name_group;
grp = $('<optgroup label="'+name+'"/>').appendTo(sel);
}
grp.append('<option value="'+this.id_option+'">'+this.name_option+'</option>')
});
});
</script>
</head>
<body>
</body>
</html>
Здесь работа с DOM, правда в среде jQuery, собственно и просто на JS будет тоже самое, суть, ну чуть больше строк кода будет.
Ваш же код подготавливает строку описывающую html-код списка, и так же нужно было бы поступать и на сервере. И если поступать так, то чуть изменится суть, но принцип будет тот же. Сперва в строку открывающие теги списка и группы, а далее сравнение переменной с текущей группой, и если не равно, то присвоить ей текущую группы, и добавить в строку закрывающий и открывающий теги группы. А теги опций последовательно после условия. После цикла закрывающий тег группы и списка.
Это разве сложно?