使用两个组在JQuery中按字母顺序排序

时间:2015-07-04 19:27:49

标签: javascript jquery sorting

我有一个待办事项列表。每行都有一个可以点击的星形图标,就像gmail一样。这里的区别在于,如果您点击星号,它应该排在最前面(更高的优先级),但也可以通过升序alpha在星号组中重新排序。 Unstarred项目排序如下,也按升序alpha排序。除了alpha排序之外,一切都按预期工作。下面是我正在做的那个排序函数。我已经验证一切都在下面工作,除了 //按alpha位排序数组...

排序失败:

function sortTasks(currList) {
    var starredTasks = [];
    var unstarredTasks = [];
    //create arrays
    $('li.task').each(function(){
        if ($(this).children('img.star').attr('src') == "images/star_checked.gif") {
            starredTasks.push($(this));
        } else {
            unstarredTasks.push($(this));
        }
    });
    //sort the arrays by alpha
    starredTasks.sort( function(a,b){ ($(a).children('p.task-name').text().toUpperCase() > $(b).children('p.task-name').text().toUpperCase()) ? 1 : -1;});
    unstarredTasks.sort( function(a,b){ ($(a).children('p.task-name').text().toUpperCase() > $(b).children('p.task-name').text().toUpperCase()) ? 1 : -1;});
    //draw rows starred first, unstarred second
    $(currList).empty();
    for (i=0; i < starredTasks.length; i++) {
        $(currList).append(starredTasks[i]);
    }
    for (i=0; i < unstarredTasks.length; i++) {
        $(currList).append(unstarredTasks[i]);
    }
}

此数组已按照最初绘制的顺序填充了任务行。数据渲染得很好,但基本上保持不变。

示例任务行:

<div id="task-container" class="container">
    <form name="enter-task" method="post" action="">
        <input id="new-task" name="new-task" type="text" autofocus>
    </form>
    <h2 id="today">today</h2>
        <ul id="today-list">
            <li id="457" class="task">
               <img class="star" src="images/star_checked.gif">
               <p class="task-name" contenteditable>buy milk</p>
               <p class="task-date"> - Wednesday</p>
            </li>
        </ul>
    <h2 id="tomorrow">tomorrow</h2>
        <ul id="tomorrow-list">
        </ul>
    <h2 id="future">future</h2>
        <ul id="future-list">
        </ul>
    <h2 id="whenever">whenever</h2>
        <ul id="whenever-list">
        </ul>
</div>

starredTasks数组中的每个项目都是整个任务行。我假设$(a)$(li)的级别相同?

这是触发排序的函数:

$('body').on('click', 'img.star', function(){
    var thisList = '#' + $(this).parent('li').parent('ul').attr('id');
    if ($(this).attr('src') == 'images/star_checked.gif') {
        $(this).attr('src', 'images/star_unchecked.gif');
    } else {
        $(this).attr('src', 'images/star_checked.gif');
    }   
    sortTasks(thisList);        
});

另外,我怀疑它值得一提,但数据存储在mySQL中并通过php预先填充。

我不确定如何直接在.sort()上使用$('li')而不将其拆分为单独的数组......

有人看到我的蠢事吗?

1 个答案:

答案 0 :(得分:2)

我没有看到您将排序列表添加回DOM的位置。如果你不是,那就是问题所在。对元素数组进行排序根本不会更新DOM。

此外,您的分类非常昂贵。最好映射具有与实际值配对的元素的对象数组进行排序。

最后,您似乎在页面上多次使用相同的ID。那是错的。它可能适用于jQuery的.children(selector)过滤器,但它仍然是错误的。你需要改变它。

这里我映射了一个对象数组,这些对象包含一个text属性,其中包含要排序的文本和一个包含该元素的task属性。

我将p#task-name更改为p.task-name,因此您应该将其更改为class="task-name"元素。

然后我使用.localeCompare()进行排序,返回一个数值。

最后,.forEach()循环将元素附加到DOM。

var data = starredTasks.map(function(t) {
    return {  task: t, 
              text: $(t).children('p.task-name').text().toUpperCase()
           };
}).sort(function(obj_a, obj_b) {
    obj_a.text.localeCompare(obj_b.text);

}).forEach(function(obj) {
    original_container.append(obj.task);
});

这假设starredTasks是一个实际的数组。如果它是一个jQuery对象,那么执行starredTasks.toArray().map(func...

original_container表示jQuery对象,它是task元素的直接父对象。