如何在JavaScript中按优先级对列表进行排序?

5

如何按优先级对列表项进行排序?这是一个待办事项清单。用户可以输入项目,选择优先级,并添加到列表中。

这是我的HTML表单:

<input id="task" type="text"/>

<select id="priority">
    <option id="Normal">Normal</option> 
    <option id="Urgent">Urgent</option>
    <option id="Critical">Critical</option>
    <option id="If You Can">If You Can</option>
</select>

<button onclick="amitFunction()">Add</button>

<hr/>

<table>
    <tr>
        <th id="result"></th>
        <th id="priorit"></th>
    </tr>
<table>

这是我的JS代码:

 function amitFunction() {    
    /* Define vars and values  */
    var lia = document.createElement("p");
    var lib = document.createElement("p");
    var item = document.getElementById('task').value;
    var pro = document.getElementById('priority').value;
    var pro_array = ['Urgent','Critical','Normal'];
    var item_list = document.createTextNode(item);
    var item_pro = document.createTextNode(pro);

    lia.appendChild(item_list);
    lib.appendChild(item_pro);

    /*  Check if text is less than 6 chars or more than 42 chars  */
    if (item.length<6) {
        alert('Your text must have a least 6 chars');
    } else if (item.length>42) {
        alert('Your text must have less than 42 chars');
    } else {
        document.getElementById("result").appendChild(lia);
        document.getElementById("priorit").appendChild(lib);
        document.getElementById('task').value='';
    }

    /*  Change text color base on priority  */
    if (pro==pro_array[0]) {
        $("p:last-child").css('color','red');
    }
    if (pro==pro_array[1]) {
        $("p:last-child").css('color','orange');
    }
    if (pro==pro_array[2]) {
        $("p:last-child").css('color','green');
    }

    /*  Delete text when user clicks on it  */
    $([lia,lib]).click(function(){
        $([lia,lib]).css('color','gray');
        $([lia,lib]).css("text-decoration", "line-through");
    });
}

我需要的是,在用户添加新项目时,它将按优先级顺序排序。
  1. 第一:紧急
  2. 第二:关键
  3. 第三:普通
  4. 第四:如果可以
每个用户添加的新项目都应该按照这样的顺序排序。我该如何做到这一点?
这是完整的脚本(JSBin),以了解我需要什么。

你可以创建4个 div 并将它们定位到所需的“排序”顺序中,然后根据所选优先级将任务添加到它们中... 如果这些 div 保持其“排序”位置,它们看起来就像正在被排序一样。同时,这些 div 的 display : none; 属性可以隐藏它们。 - DIEGO CARRASCAL
我会实现自己的排序函数并将其应用于项目集合。有关更多信息,请参见Mozilla Developer Network的Array.sort页面。 您可以假设选项是字符串,并使用switch语句告诉JavaScript顺序,或者使用整数值使用自然数(这是更好的方法)。 - Sumi Straessle
2个回答

4

首先,我建议你在创建TODO任务时每次创建一个新表格行,但是我决定尽可能保留你的代码并实现你要求的功能。我承认这不是最好的决定,并且可以进行很多优化,但是我将其保留为原样,仅因为代码中可能会有许多有趣的情况,这可能会教给你一些新知识。排序已经实现。希望这会有所帮助 :)

你的HTML代码保持原样:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>

</head>
<body>
    <script src="https://code.jquery.com/jquery-3.1.0.js"></script>

<input id="task" type="text"/>
<select id="priority">
 <option id="Normal">Normal</option> 
<option id="Urgent">Urgent</option>
<option id="Critical">Critical</option>
<option id="If You Can">If You Can</option>
 </select>

<button onclick="amitFunction()">Add</button>

<hr/>
<table>
  <tr>
    <th id="result"></th>
<th id="priorit"></th>
  </tr>
<table>
</body>
</html>

和编辑后的JS代码:

//creating a global collection to hold your todo list in memory
var todo_list = [];

function amitFunction() {

        var item = document.getElementById('task').value;

        /*  Check if text is less than 6 chars or more than 42 chars 
            and return if validation is not passed */
        if(item.length<6){
             alert('Your text must have a least 6 chars');
             return;
        }else if(item.length>42){
            alert('Your text must have less than 42 chars');
            return; 
        }

        var pro = document.getElementById('priority').value;

        //keep this for colors
        var pro_array = ['Urgent','Critical','Normal'];

        //map string priorities to numeric values
        var priorities = 
            {
              'Urgent' : 0, 
              'Critical' : 1,
              'Normal' : 2,
              'If You Can' : 3
            }

        //push each new task in the todo list
        todo_list.push(
          {
            priority : pro,
            task : item
          }
        );

        //Now this here is perhaps the most important part,
        //this is where you sort your todo list based on the
        //mapped to numeric values priorities
        todo_list.sort(function (task1, task2) {
          return priorities[task1.priority] - priorities[task2.priority];
        });

        //clear the containers holding your list
        var resultNode = document.getElementById("result");

        while (resultNode.firstChild) {
          resultNode.removeChild(resultNode.firstChild);
        }

        var priorityNode = document.getElementById("priorit");

        while (priorityNode.firstChild) {
          priorityNode.removeChild(priorityNode.firstChild);
        }

        //recreate the DOM based on the todo_list collection
        for(var i =0; i < todo_list.length; i++)
          {
            var lia = document.createElement("p");
            var lib = document.createElement("p");

            var item_list = document.createTextNode(todo_list[i].task);
            var item_pro = document.createTextNode(todo_list[i].priority);

            lia.appendChild(item_list);
            lib.appendChild(item_pro);

            document.getElementById("result").appendChild(lia);
            document.getElementById("priorit").appendChild(lib);
            document.getElementById('task').value='';

              /*  Change text color base on priority  */
            if(todo_list[i].priority == pro_array[0]){
                 $("p:last-child").css('color','red');
               }
            if(todo_list[i].priority == pro_array[1]){
                 $("p:last-child").css('color','orange');
               }
             if(todo_list[i].priority == pro_array[2]){
                 $("p:last-child").css('color','green');
               }

         }

         //reinitialize the click handlers
         var resultNode = document.getElementById("result");
         var priorityNode = document.getElementById("priorit");

        for(var i =0; i< resultNode.childNodes.length; i++) (function(i){ 
          resultNode.childNodes[i].onclick = function() {
            $([resultNode.childNodes[i],priorityNode.childNodes[i]]).css('color','gray');
            $([resultNode.childNodes[i],priorityNode.childNodes[i]]).css("text-decoration", "line-through");
          }
          priorityNode.childNodes[i].onclick = function() {
            $([resultNode.childNodes[i],priorityNode.childNodes[i]]).css('color','gray');
            $([resultNode.childNodes[i],priorityNode.childNodes[i]]).css("text-decoration", "line-through");
          }
        })(i);

  }

这里有一个可行的实例:

https://jsbin.com/kudipacexi/edit?html,js,output

实际上,有很多方法可以实现这个功能。另一种方法是不使用全局集合来存储您的列表,而是直接使用DOM元素进行排序,但是您仍然需要保留某种数字表示来按优先级对它们进行排序。还可能是一个好主意,为每个元素订阅一个单独的点击处理函数,然后根据调用者添加删除线样式。我建议的另一件事是,如果您正在使用jQuery而不只是专注于原始JS,请尽量使用jQuery进行大部分DOM操作。


2
++ 用于增强学习过程和重构而非重新开始。 - Bimbonkens

1
因为您有一个表格,我建议将其用作输出。
您可以重新排列选择项,以便为每个选项添加优先级数字和颜色属性,例如:
<option value="2" color="green">Normal</option>

表格可以包含第一列作为当前行的优先级。这一列将被隐藏。
每次需要添加新行时,都会对表格行执行排序过程。
代码片段:

$('button').on('click', function (e) {
    var priorityValue = $('#priority option:selected').val();
    var priorityText = $('#priority option:selected').text();
    var colorVal = $('#priority option:selected').attr('color');
    var taskValue = $('#task').val();
    if (taskValue.length < 6) {
        $('#errMsg').text('Your text must have a least 6 chars');
        return;
    } else if (taskValue.length > 42) {
        $('#errMsg').text('Your text must have less than 42 chars');
        return;
    }
    $('#errMsg').text('');

    //
    // create the new table row...
    //
    var newRow = $('<tr/>', {style: 'color:' + colorVal})
            .append($('<td/>', {style: "display: none", text: priorityValue}))
            .append($('<td/>', {text: taskValue}))
            .append($('<td/>', {text: priorityText}));


    //
    // enlarge current table rows with the current one and sort elements
    //
    var tableRowsSorted = $('#result tbody').append(newRow).find('tr').get().sort(function(a, b) {
        var p1 = +$(a).find('td:first').text();
        var p2 = +$(b).find('td:first').text();
        return p1 - p2;
    });

    //
    // append/replace the taable body
    //
    $('#result tbody').append(tableRowsSorted);

    //
    // reset input text
    //
    $('#task').val('');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>



<input id="task" type="text"/><span id="errMsg" style="color: red;"></span>
<select id="priority">
    <option value="2" color="green">Normal</option>
    <option value="0" color="red">Urgent</option>
    <option value="1" color="orange">Critical</option>
    <option value="3" color="black">If You Can</option>
</select>

<button>Add</button>

<hr/>
<table id="result">
    <thead>
    <tr>
        <th style="display: none">priority</th>
        <th>result</th>
        <th>priority</th>
    </tr>
    </thead>
    <tbody>

    </tbody>
</table>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接