最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery traversing order - depth first - Stack Overflow

programmeradmin0浏览0评论

I have a bunch of nested checkboxes. I would like to make a selection of all checkboxes and have the 'deepest' elements first in that collection. Consider the following 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>

I'm using some jQuery to print the selection order:

var x = '';

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

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

The result is: a - b - c - d - e - f - g - h - i - j.

I would like the order or the selected elements to be I, H, G, F, C, B, J, E, D, A or H, I, B, C, F, G, A, D, E, J. How can I reorder the selection to be patible with what I want? Or is their a way to make the initial selection the way I want?

Ow... and for all you fiddlers out there: /! Go nuts! :D

I have a bunch of nested checkboxes. I would like to make a selection of all checkboxes and have the 'deepest' elements first in that collection. Consider the following 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>

I'm using some jQuery to print the selection order:

var x = '';

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

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

The result is: a - b - c - d - e - f - g - h - i - j.

I would like the order or the selected elements to be I, H, G, F, C, B, J, E, D, A or H, I, B, C, F, G, A, D, E, J. How can I reorder the selection to be patible with what I want? Or is their a way to make the initial selection the way I want?

Ow... and for all you fiddlers out there: http://jsfiddle/hze3M/4/! Go nuts! :D

Share Improve this question asked Apr 22, 2011 at 13:18 Kees C. BakkerKees C. Bakker 33.5k31 gold badges118 silver badges207 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6
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/hze3M/7/

EDIT:

here another solution:

$.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);

Credits here : Create a jQuery object collection from separate jQuery objects

$(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;
}

EDIT:

$(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 );

Here shows the result: 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));

You can also try this jsFiddle file.

Here's a functional jQuery-heavy variation on @alexi's answer (same basic idea):

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

That would give you a jQuery object with the checkboxes arranged in the order you want. Note that the depth parison is done "backwards" because you want the deepest ones first. The JavaScript sort appears to be stable, as far as I can tell, so when depth is equal the pre-existing DOM ordering will naturally be retained.

edit — probably obvious, but if you wanted to see the list of "id" values you'd just do:

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

评论列表(0)

  1. 暂无评论