2015-09-25 6 views
1

У меня есть древовидный список, который можно сворачивать и разворачивать пользователемОбновить существующий список, чтобы соответствовать новому списку

<ul> 
    <li class="exp"> 
    ... 
    </li> 
    <li> 
    ... 
    </li> 
</ul> 

Содержания, если этот список ленивый загружен, поскольку он может быть большим, но и потому, что он может измениться в зависимости от того, что еще делает пользователь на странице.

Ленивая загрузка работает нормально, но обновление после удаления/добавления элементов в список является проблемой

То, как я делаю это сейчас, как это:

var old_i = 0, 
    new_v = []; 

new_li.each(function(i, li){ 
    new_v.push(node.dataset.value); 

    // new li at the end 
    if(!old_li.get(old_i)){ 
    old_ul.append(li); 
    return; 
    } 

    // existing li 
    if(li.dataset.value == old_li.get(old_i).dataset.value){  
    old_i++; 
    return; 
    } 

    // new li before the end 
    $(li).insertBefore(old_li.get(old_i));   
}); 

// remove non-existing 
old_i.each(function(idx, li){ 
    if(new_v.indexOf(li.dataset.value) < 0) 
    $(li).remove(); 
}); 

Но когда Я удаляю li, который предшествует последнему, последний дублируется. Я думаю, что проблема близка к insertBefore, но я не знаю, что вызывает ее.

Еще одна вещь, которую я не знаю, как это сделать, - это пересортировать старый список, чтобы он соответствовал заказу нового списка.

Я знаю, что я могу просто заменить список, чтобы упростить задачу, но тогда я потеряю состояние расширения пользователя. И не только классы состояний, но и контент, потому что ответ ajax возвращает только то, что нужно обновить, то есть содержание активных li (прямых детей). Но пользователь может расширить ребенок или внук его, и содержание тех, будет потерян на с заменить

ответ

0

Я думаю, что дублирует получить создал что-то, как показано ниже:

Если ваш старый список был: а, б , c, d и newlist: a, c, d:
Ваша петля отлично работает с.
Но когда ваш новый цикл списка находится в точке c, ваш old_li.get() возвращает b, вызывая insertBefore. oldlist теперь a, c, b, c, d.
Следующий проход, newlist возвращает d, и old_li.get() возвращает c (old_i не увеличивается). Это вызывает еще один insertBefore. oldlist - это a, d, c, b, c, d.

После удаления раунда значение c удаляется, оставляя новый список a, d, d, c, c.

В качестве альтернативного подхода, я хотел бы предложить:

var old_v; // array with only value strings from old state 
var new_v; // array with only value strings from new state 
var updatedLength=0; 

old_v.reverse().map((itemVal,i) => { 
    if (new_v.indexOf(itemVal) != -1) { 
    // remove item (i) from the old_li in DOM 
    // loop over old_v in reverse order so we don't mess up count 
    } else { 
    UpdatedLength++; 
    } 
} 
new_v.map((itemVal, i) => { 
    if (old_v.indexOf(itemVal) == -1) { 
    if (i >= updatedLength) { 
     // append item (i) from the new_li to DOM at the end 
    } else { 
     // insert item (i) before item at index updatedLength in DOM 
    } 
    updatedLength++; 
    } 
    return itemVal; 
} 

Надеется, что это работает!