jQuery遍历顺序 - 深度优先

时间:2011-04-22 13:18:31

标签: javascript jquery html dom

我有一堆嵌套的复选框。我想选择所有复选框,并在该集合中首先使用“最深”元素。请考虑以下html:

<div id="selection"></div>
<div>
    <label>A: <input id="a" type="checkbox" /></label><br/>
    <div>
        <label>B: <input id="b" type="checkbox" /></label><br/>
        <label>C: <input id="c" type="checkbox" /></label><br/>
    </div>
    <label>D: <input id="d" type="checkbox" /></label><br/>
    <label>E: <input id="e" type="checkbox" /></label><br/>
    <div>
        <label>F: <input id="f" type="checkbox" /></label><br/>
        <label>G: <input id="g" type="checkbox" /></label><br/>
        <div>
            <label>H: <input id="h" type="checkbox" /></label><br/>
            <label>I: <input id="i" type="checkbox" /></label><br/> 
        </div>
    </div>
    <label>J: <input id="j" type="checkbox" /></label><br/>
</div>

我正在使用一些jQuery来打印选择顺序:

var x = '';

$('input').each(function(){
    x += $(this).attr('id') + ' - ';
});

$('#selection').text(x.substr(0, x.length - 3)); 

结果是:a - b - c - d - e - f - g - h - i - j

我希望订单或所选元素为 I, H, G, F, C, B, J, E, D, A H, I, B, C, F, G, A, D, E, J 。如何重新排序选择以与我想要的兼容?或者他们是按照我想要的方式进行初始选择的方法吗?

噢......对你们所有的小提琴手来说:http://jsfiddle.net/hze3M/4/!发疯! :d

4 个答案:

答案 0 :(得分:5)

var x = '';
var ar = [];
$('input').each(function(){
    ar.push({length: $(this).parents().length, elmt: $(this)});
});

ar.sort(function(a,b) {
    if (a.length - b.length > 0) {
        return -1;
    }

    if (a.length - b.length < 0) {
        return 1;
    }

    return 0;
});

for (var i=0; i<ar.length; i++) {
    x += (ar[i].elmt.attr("id")) + ' - ';
};    

$('#selection').text(x);

Jsfiddle:http://jsfiddle.net/hze3M/7/

编辑:

这里是另一种解决方案:

$.fn.sortByDepth = function() {
    var ar = this.map(function() {
            return {length: $(this).parents().length, elt: this}
        }).get(),
        result = [],
        i = ar.length;


    ar.sort(function(a, b) {
        return a.length - b.length;
    });

    while (i--) {
        result.push(ar[i].elt);
    }
    return $(result);
};


var x = $('input').sortByDepth().map(function() {
    return this.id;
}).get().join(' - ');

$('#selection').text(x);

致谢:Create a jQuery object collection from separate jQuery objects

答案 1 :(得分:1)

$(document).ready(function() {
    var a = new Array();
    $('input').each(function(){
        var $this = $(this);
        a.push({id:$this.attr('id'),level:$this.parents('div').length});
    });
    a.sort(sortByLevel);
    /*for(var i=0; i<a.length; i++){
        console.log('id: '+a[i].id+'; level:'+a[i].level);
    }*/
});

function sortByLevel(a,b){
    return b.level - a.level;
}

编辑:

$(document).ready(function() {
    var sorted = $('input').sortByDepth();
    sorted.each(function(){
        console.log($(this).attr('id') );
    });
});

(function( $ ){
    $.fn.sortByDepth = function() {
        return $(this).sort(function(a,b){
            return $(b).parents('div').length - $(a).parents('div').length;
        });
    };
})( jQuery );

答案 2 :(得分:0)

这是@ alexi的答案(相同的基本想法)的一个功能jQuery重型变体:

var $sorted = $('input:checkbox').sort(function(cb1, cb2) {
  return $(cb2).parents().length - $(cb1).parents().length();
});

这会给你一个jQuery对象,复选框按你想要的顺序排列。请注意,深度比较是“向后”完成的,因为您首先需要最深的比较。据我所知,JavaScript排序似乎是稳定的,所以当深度相等时,自然会保留预先存在的DOM排序。

编辑 - 可能很明显,但如果您想查看“id”值列表,您只需执行此操作:

var idList = $sorted.map(function() { return this.id }).get().join(' - ');

答案 3 :(得分:0)

这里显示结果:i - h - g - f - c - b - j - e - d - a

var x = '';
function getDepth(n) {
    var i = 0;
    while(n != document.body) {
        n = n.parentNode;
        i++;
    }
    return i;
}
var list = $('input');

list.sort(function (a, b) {
    var a1 = getDepth(a), b1 = getDepth(b);
    if (a1 != b1)
        return b1 - a1;
    else
        return $(list).index(b) - $(list).index(a);
});
$(list).each(function(){
    x += $(this).attr('id') + ' - ';
});

$('#selection').text(x.substr(0, x.length - 3));

您也可以尝试this jsFiddle file