【问题标题】:Sorting Divs in jQuery by Custom Sort Order通过自定义排序顺序在 jQuery 中对 div 进行排序
【发布时间】:2012-03-28 16:22:36
【问题描述】:

我正在尝试通过比较重新排序标签 input 的子元素 他们的类别属性在 Javascript 中的类别顺序 变量category_sort_order。然后我需要删除其类别属性的div 没有出现在category_sort_order中。

预期的结果应该是:

任何
产品1
产品2
下载

代码:

<div id="input">
<div category="download">download</div>
<div category="video">video1</div>
<div category="video">video2</div>
<div category="product">product1</div>
<div category="any">any</div>
<div category="product">product2</div>
</div>

<script type="text/javascript">
var category_sort_order = ['any', 'product', 'download'];
</script>

我什至不知道从哪里开始这项任务,但如果您能提供任何帮助,我将不胜感激。

【问题讨论】:

    标签: javascript jquery sorting


    【解决方案1】:

    我写了一个 jQuery 插件来做这种事情,可以很容易地适应你的用例。

    The original plugin is here

    这是一个针对你的问题的改进

    (function($) {
    
    $.fn.reOrder = function(array) {
      return this.each(function() {
    
        if (array) {    
          for(var i=0; i < array.length; i++) 
            array[i] = $('div[category="' + array[i] + '"]');
    
          $(this).empty();  
    
          for(var i=0; i < array.length; i++)
            $(this).append(array[i]);      
        }
      });    
    }
    })(jQuery);
    

    并像这样使用

    var category_sort_order = ['any', 'product', 'download'];
    $('#input').reOrder(category_sort_order);
    

    这一次恰好为产品获得了正确的顺序,因为 product1 在原始列表中出现在 product2 之前,但可以很容易地更改为先对类别进行排序,然后再放入数组并附加到 DOM。此外,如果将其用于多个元素,则可以通过一次性追加数组中的所有元素来改进它,而不是遍历数组并一次追加一个。对于DocumentFragments,这可能是一个很好的例子。

    【讨论】:

      【解决方案2】:

      请注意,

      由于有 jQuery 1.3.2,排序很简单,无需任何插件:

      $('#input div').sort(CustomSort).appendTo('#input');
      function CustomSort( a ,b ){
           //your custom sort function returning -1 or 1
           //where a , b are $('#input div') elements
      }
      

      这将对所有作为 id="input" 元素的子元素的 div 进行排序。

      【讨论】:

        【解决方案3】:

        这里是如何做到这一点。我用这个SO question 作为参考。

        我测试了这段代码,它适用于您的示例:

        $(document).ready(function() {
            var categories = new Array();
            var content = new Array();
            //Get Divs
            $('#input > [category]').each(function(i) {
                //Add to local array
                categories[i] = $(this).attr('category');
                content[i] = $(this).html();
            });
        
            $('#input').empty();
        
            //Sort Divs
            var category_sort_order = ['any', 'product', 'download'];
            for(i = 0; i < category_sort_order.length; i++) {
                //Grab all divs in this category and add them back to the form
                for(j = 0; j < categories.length; j++) {
                    if(categories[j] == category_sort_order[i]) {
                        $('#input').append('<div category="' + 
                                   category_sort_order[i] + '">' 
                                   + content[j] + '</div>');
                    }
                };
            }
        });
        

        工作原理

        首先,此代码需要 JQuery 库。如果你目前没有使用它,我强烈推荐它。

        代码首先获取包含类别属性的输入 div 的所有子 div。然后它将它们的 html 内容和它们的类别保存到两个单独的数组中(但在同一位置。

        接下来清除输入div下的所有div。

        最后,它会按照您在数组中指定的顺序遍历您的类别,并以正确的顺序附加匹配的子 div。

        For 循环部分

        @eyelidlessness 很好地解释了 for 循环,但我也会尝试一下。在这段代码的上下文中。

        第一行:

        for(i = 0; i < category_sort_order.length; i++) {
        

        表示后面的代码(大括号 { code } 内的所有内容)将重复多次。尽管格式看起来很古老(而且有点过时),但它说:

        1. 创建一个名为 i 的数字变量并将其设置为零
        2. 如果该变量小于 category_sort_order 数组中的项目数,则执行括号中的内容
        3. 括号结束后,将变量 i 加一(i++ 表示加一)
        4. 然后它重复第二步和第三步,直到 i 最终大于该数组中的类别数。

        A.K.A 括号中的内容将为每个类别运行一次。

        继续... 对于每个类别,都会调用另一个循环。这个:

        for(j = 0; j < categories.length; j++) {
        

        遍历我们刚刚从屏幕上删除的 div 的所有类别。

        在这个循环中,if 语句检查屏幕上的任何 div 是否与当前类别匹配。如果是,他们正在追加,如果不是,则循环继续搜索,直到遍历每个 div。

        【讨论】:

        • 感谢您的帮助。我是 javascript 新手,虽然我了解您的代码的第一部分,但我对第二部分感到困惑。 i=0 和 j=0 行是干什么用的?我经常看到这些,无法理解。再次感谢。
        • hnovic,这些是迭代器变量。它们对应于它们迭代的Array 的数字键。 for 循环(通常)将第一个语句作为初始键,第二个语句作为最终键,其最终语句将指令从初始键移动到最终键(通常是 i++i--) .
        • 这样做的好处是不会过多地操作 dom,但它确实使用了内联 html,这有点令人讨厌,尤其是当事情开始发生变化时。
        • 非常感谢。你很好地解释了这一点。
        【解决方案4】:

        再次附加(或前置)DOM 节点实际上会按照您想要的顺序对它们进行排序。

        使用 jQuery,您只需按照您想要的顺序选择它们,然后再次将它们附加(或预先添加)到它们的容器中。

        $(['any', 'product', 'video'])
            .map(function(index, category)
            { 
                 return $('[category='+category+']');
            })
            .prependTo('#input');
        

        抱歉,错过了您想要删除不在您的类别列表中的节点。这是修正后的版本:

        // Create a jQuery from our array of category names, 
        // it won't be usable in the DOM but still some 
        // jQuery methods can be used
        var divs = $(['any', 'product', 'video'])
        // Replace each category name in our array by the
        // actual DOM nodes selected using the attribute selector
        // syntax of jQuery.
            .map(function(index, category)
            { 
                // Here we need to do .get() to return an array of DOM nodes
                return $('[category='+category+']').get();
            });
        // Remove everything in #input and replace them by our DOM nodes.
        $('#input').empty().append(divs);
        
        // The trick here is that DOM nodes are selected 
        // in the order we want them in the end.
        // So when we append them again to the document,
        // they will be appended in the order we want.
        

        【讨论】:

        • 感谢您的帮助。这是如何运作的!?你能解释一下吗。再次感谢
        • 很好地使用了map()。数组中的最后一项应该是 download :)
        • 我喜欢。这是一个非常优雅的解决方案。
        【解决方案5】:

        我认为这是一个非常有趣的问题,这是我想出的一个简单但性能不高的排序解决方案。

        你可以在这里查看jsbin上的测试页面:http://jsbin.com/ocuta

        function compare(x, y, context){
          if($.inArray(x, context) > $.inArray(y, context)) return 1; 
        }
        function dom_sort(selector, order_list) {
         $items = $(selector);
         var dirty = false;
         for(var i = 0; i < ($items.length - 1); i++) {
          if (compare($items.eq(i).attr('category'), $items.eq(i+1).attr('category'), order_list)) {
           dirty = true;
           $items.eq(i).before($items.eq(i+1).remove());
          }
         }
         if (dirty) setTimeout(function(){ dom_sort(selector, order_list); }, 0); 
        };
        dom_sort('#input div[category]', category_sort_order);
        

        请注意,setTimeout 可能不是必需的,但感觉更安全。您的来电。

        您可以通过存储对父级的引用并每次只获取子级来清理一些性能,而不是重新运行选择器。不过,我是为了简单。您每次都必须调用选择器,因为排序中的顺序会发生变化,而且我不会在任何地方存储对父级的引用。

        【讨论】:

        • 这也会将排序顺序数组中未找到的类别放在列表的前面。如果您希望它们放在最后,请检查 $.inArray 函数上的 -1。
        【解决方案6】:

        对这个使用sort 方法似乎相当直接:

        var category_sort_order = ['any', 'product', 'download'];
        
        // select your categories
        $('#input > div')
        
          // filter the selection down to wanted items
          .filter(function(){
            // get the categories index in the sort order list ("weight")
            var w = $.inArray( $(this).attr('category'), category_sort_order );
            // in the sort order list?
            if ( w > -1 ) {
              // this item should be sorted, we'll store it's sorting index, and keep it
              $( this ).data( 'sortindex', w );
              return true;
            }
            else {
              // remove the item from the DOM and the selection
              $( this ).remove();
              return false;
            }
          })
        
          // sort the remainder of the items
          .sort(function(a, b){
            // use the previously defined values to compare who goes first
            return $( a ).data( 'sortindex' ) - 
                   $( b ).data( 'sortindex' );
          })
        
          // reappend the selection into it's parent node to "apply" it
          .appendTo( '#input' );
        

        如果你碰巧使用的是旧版本的 jQuery (1.2),它没有 sort 方法,你可以添加它:

        jQuery.fn.sort = Array.prototype.sort;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-29
          • 1970-01-01
          • 2016-11-01
          • 2010-12-21
          • 2021-12-01
          • 1970-01-01
          相关资源
          最近更新 更多