【问题标题】:How to order divs by id in javascript?如何在javascript中按id排序div?
【发布时间】:2012-03-19 22:29:32
【问题描述】:

我有这个 HTML 代码:

<div id="main">
  <div id="dv_7">...</div>
  <div id="dv_1">...</div>
  <div id="dv_8">...</div>
  <div id="dv_4">...</div>
  <div id="dv_11">...</div>
  <div id="dv_2">...</div>
</div>

如何使用 javascript 对 maindiv 中的 div 进行排序?我不知道:(

提前致谢,

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    怎么样:

    var main = document.getElementById( 'main' );
    
    [].map.call( main.children, Object ).sort( function ( a, b ) {
        return +a.id.match( /\d+/ ) - +b.id.match( /\d+/ );
    }).forEach( function ( elem ) {
        main.appendChild( elem );
    });
    

    现场演示: http://jsfiddle.net/ZEKrH/6/

    (您需要为 IE8 填充这些数组方法。)

    【讨论】:

    • 你能设置一个 NodeList 作为 IE8 中 Array 方法的调用上下文吗? ...或者我想这无关紧要,因为它们被填充了! :P
    • @amnotiam 是的。添加 ES5-shim 将使我的演示在 IE8 中工作:jsfiddle.net/ZEKrH/1
    • @jfriend00 .children 确实存在于 IE6-8 中,但它也包括注释节点(这在此应用程序中应该不是问题)。 IE7 只剩下 3-5% 了,应该很快就会死掉。如果需要 IE7 支持,则应使用跨浏览器库。手动填充该浏览器是不可行的(因为要修复的东西太多了)。
    • @amnotiam 啊,当然。不需要 DOM 选择,因为我们已经在 main.children 中拥有所有引用。我进一步简化了代码。
    • @amnotiam 是的,你是对的。 [].slice.call( nodeList ) 在 IE7/8 中不起作用。 [].map.call(main.children, Object) 在这些浏览器中确实有效 - 这是一个不错的 hack。
    【解决方案2】:

    希望这会有所帮助。更新了 id 以考虑字母顺序 1 和 11。

    <div id="main">
      <div id="dv_07">7...</div>
      <div id="dv_01">1...</div>
      <div id="dv_08">8...</div>
      <div id="dv_04">4...</div>
      <div id="dv_11">11...</div>
      <div id="dv_02">2...</div>
    </div>​
    

    jQuery 选项:

    var mylist = $('#main');
    var listitems = mylist.children('div').get();
    listitems.sort(function(a, b) {
        var compA = $(a).attr('id').toUpperCase();
        var compB = $(b).attr('id').toUpperCase();
        return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
    })
    $.each(listitems, function(idx, itm) {
        mylist.append(itm);
    });​
    

    Javascript 选项:

    var mylist = document.getElementById('main');
    var divs = mylist.getElementsByTagName('div');
    var listitems = [];
    for (i = 0; i < divs.length; i++) {
            listitems.push(divs.item(i));
    }
    listitems.sort(function(a, b) {
        var compA = a.getAttribute('id').toUpperCase();
        var compB = b.getAttribute('id').toUpperCase();
        return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
    });
    for (i = 0; i < listitems.length; i++) {
        mylist.appendChild(listitems[i]);
    }​
    

    【讨论】:

    • 这是 jQuery。 OP 没有要求 jQuery。
    • 感谢 jfriend00 指出这一点。更新以添加 javascript 版本。
    • getElementsByTagName('div') 只会返回 div 元素,所以 nodeType 测试是多余的。
    【解决方案3】:

    对于适用于任意数量的任意数量的子 div 且数字在任何范围内的解决方案,您可以使用这样的函数(它实际上解析我们的 ID 的数量并对其进行真正的数字排序):

    function sortChildrenDivsById(parentId) {
        var parent = document.getElementById(parentId);
        // get child divs
        var children = parent.getElementsByTagName("div");
        var ids = [], obj, i, len;
        // build an array of objects that has both the element 
        // and a parsed div number in it so we can sort
        for (i = 0, len = children.length; i < len; i++) {
            obj = {};
            obj.element = children[i];
            obj.idNum = parseInt(children[i].id.replace(/[^\d]/g, ""), 10);
            ids.push(obj);
        }
        // sort the array
        ids.sort(function(a, b) {return(a.idNum - b.idNum);});
        // append in sorted order
        for (i = 0; i < ids.length; i++) {
             parent.appendChild(ids[i].element);
        }
    }
    

    这里的工作示例:http://jsfiddle.net/jfriend00/v9mCM/

    仅供参考,这是跨浏览器的纯 JavaScript,甚至可以在没有 shims 的旧浏览器中使用。


    这是另一种使用稍微少一点的代码的方法:

    function sortChildrenDivsById(parentId) {
        var parent = document.getElementById(parentId);
        var children = parent.getElementsByTagName("div");
        var ids = [], i, len;
        for (i = 0, len = children.length; i < len; i++) {
            ids.push(parseInt(children[i].id.replace(/^.*_/g, ""), 10));
        }
        ids.sort(function(a, b) {return(a - b);});
         for (i = 0, len = ids.length; i < len; i++) {
             parent.appendChild(document.getElementById("dv_" + ids[i]));
         }
    }
    

    工作示例:http://jsfiddle.net/jfriend00/TqJVb/

    所有的ids nums被解析出来并放入一个排序的数组中,然后通过id查找每个对象并按排序顺序重新插入。这不会像第一个那么快,但它的代码更少。

    【讨论】:

      【解决方案4】:

      以下可能有效:

      var main = document.getElementById("main");
      for(var i = 11; i > -1; i--) {
          var div = document.getElementById("dv_" + i);
          if(div != null)
              main.appendChild(div);
      }
      

      【讨论】:

      • 应该有if(div != null)
      • 我认为还有document.getElementById("main");
      • 作用域查询表现更好:var div = main.querySelector("#dv_" + i);
      • 这假定文档中的其他任何地方都没有 dv_nn id,并且它需要对数字的上限进行硬编码,而不是仅仅对那里的项目进行排序,无论有多少。跨度>
      【解决方案5】:

      以下内容与 IE 5 及类似版本的浏览器兼容,没有 shims 或库。排序功能可以修改为数字排序,目前它会将div排序为1、11、2、4等。更改它并不难,所以它们是1、2、4、... 11。

      function sortDivs(div) {
        var divs = div.getElementsByTagName('div');
        var a = [];
        for (var i=0, iLen=divs.length; i<iLen; i++) { 
          a[i] = divs[i];
        }
        a.sort(function(a, b) {
          return a.id < b.id? -1 : a.id == b.id? 0 : 1;
        });
        while (iLen--) {
          div.insertBefore(a[iLen], div.firstChild);
        }
      }
      
      window.onload = function() {
        sortDivs(document.getElementById('main'));
      }
      

      编辑

      极简版本,适合那些认为 cmets 和数字排序很重要的人。

      function sortDivs(div) {
        var divs = div.getElementsByTagName('div');
      
        // Convert divs collection to an array
        for (var i=0, iLen=divs.length, a=[]; i<iLen; i++) a[i] = divs[i];
      
        // Sort the array numerically
        a.sort(function(a, b) {
          return a.id.split('_')[1] - b.id.split('_')[1]; 
        });
      
        // Move elements to sorted order
        while (iLen--) div.insertBefore(a[iLen], div.firstChild);
      }
      

      【讨论】:

        【解决方案6】:

        2021年答案

        function sortChildren(parent, comparator) {
            parent.replaceChildren(...Array.from(parent.children).sort(comparator));
        }
        

        这就是你所需要的。示例:

        const main = document.getElementById('main');
        sortChildren(main, (a, b) => +a.id.match( /\d+/ ) - +b.id.match( /\d+/ ));
        

        【讨论】:

          【解决方案7】:
          <div id="main">
            <div id="dv_7" data-order=7>7</div>
            <div id="dv_1" data-order=1>1</div>
            <div id="dv_8" data-order=8>8</div>
            <div id="dv_4" data-order=4>4</div>
            <div id="dv_11" data-order=11>11</div>
            <div id="dv_2" data-order=2>2</div>
          </div>
          
          <button onclick="sort()">
          Sort
          </button>
          
          function sort() {
          
            var main = document.getElementById( 'main' );
          
            [].map.call( main.children, Object ).sort( function ( a, b ) {
          console.log(a.dataset.order);
                return +a.dataset.order - +b.dataset.order;
            }).forEach( function ( elem ) {
                main.appendChild( elem );
            });
          
          }
          

          更新了@Šime Vidas 答案以支持带有按钮和数据属性的动态顺序

          http://jsfiddle.net/hbe4w90s/

          【讨论】:

            猜你喜欢
            • 2018-05-04
            • 2015-06-30
            • 1970-01-01
            • 1970-01-01
            • 2012-06-07
            • 2020-08-28
            • 2016-04-17
            • 1970-01-01
            • 2010-10-28
            相关资源
            最近更新 更多