How can I sort a parent element based on child element value?

I have a list of comments, each of which has a vote count (either positive or negative). I’m trying to pull out the top two comments (based on highest net votes, not vote count), copy their HTML, and add them to a new section titled “top ideas”

I want to duplicate the entire for the two comments with the highest number in the

Read More

HTML (an over simplified version)… this is repeated for each comment:

<div class="comment">
    <div class="thumbblock">
        <div class="ratingtext">
            <div>
                <span class="num-total" data-voteup="8" data-votedown="4">+4</span>
            </div><!-- END random div -->
        </div><!-- END ratingtext -->
    </div><!-- END thumbblock -->
    <p>comment text</p>
</div><!-- END comment -->

jQuery:

jQuery(document).ready(function($) {
    //number of top comments to show
    var showResults = 2;

    //loop through each total rating
    //only pull the top two (in this case)
    $('span.num-total').slice(0, showResults).each(function(index){

        //calculate the net vote total based on data-voteup and data-votedown
        var upVotes = $(this).data('voteup');
        var downVotes = $(this).data('votedown');
        var netVotes = upVotes - downVotes;

        //get the HTML for those comments
        var commentHTML = $(this).parents('.comment').html();

        //append that HTML to the top comment div
        $('div.top-comments').append('<div class="comment">' + commentHTML + '</div>');

    });
});

See the live copy here: http://jobelty.com/company/apple

The jQuery is coming from a file called top-comments.js

Related posts

Leave a Reply

3 comments

  1. You’re cutting the list down before sorting, so at best you’ll get the text of whichever two comments happen to be at the top.

    A version that grabs the full comment elements of the two highest-ranked comments, and copies those into .top-comments:

    jQuery(document).ready(function ($) {
        //number of top comments to show
        var showResults = 2;
    
        var ordered = [];
    
        // grab all the comments
        var comments = $('.commentlist .comment');
    
        $.each(comments,
    
        function (i, v) {
            // for each comment
            var cmt = $(v);
            var nums = cmt.find('.num-total');
            var upVotes = nums.data('voteup');
            var downVotes = nums.data('votedown');
            var netVotes = upVotes - downVotes;
    
            var pos = ordered.length;
    
            // find the first place in the ordered list it fits
            for (var j = 0; j < ordered.length; ++j) {
                if (ordered[j].votes < netVotes) {
                    pos = j;
                    break;
                }
            }
    
            // save element and count for later
            var vote = {
                'votes': netVotes,
                'cmt': cmt
            };
    
            ordered[pos] = vote;
        });
    
        var n = Math.min(2, ordered.length);
    
        // grab the first (up to) 2 and append to .top-comments    
        for (var i = 0; i < n; ++i) {
            ordered[i].cmt.clone().appendTo($('.top-comments'));
        }
    });
    
  2. From what I can tell you have everything working except for the part where you determine what the top two comments are. Here’s an approach based on sorting the comment elements first. Code is untested:

    jQuery(document).ready(function($) {
        //number of top comments to show
        var showResults = 2;
    
        var netVotes = function(domElm) {          
            var upVotes = domElm.data('voteup');
            var downVotes = domElm.data('votedown');
            return upVotes - downVotes;
        };
    
        var sortedComments = $('span.num-total').slice(0).sort(function(a,b) {
            return netVotes(a) - netVotes(b);
        });
    
        sortedComments.slice(0, showResults).each(function(index){
            var commentHTML = $(this).parents('.comment').html();
            $('div.top-comments').append('<div class="comment">' + commentHTML + '</div>');
        });
    });
    
  3. Try

    $(function(){
        var voteels = $('.comment .num-total');
    
        var array = voteels.get();
        array.sort(function(a1, a2){
            var v1 = ($(a1).data('voteup') || 0) - ($(a1).data('votedown') || 0);
            var v2 = ($(a2).data('voteup') || 0) - ($(a2).data('votedown') || 0);
    
            return v1 < v2;
        });
        $(array.slice(0, 2)).closest('.comment').clone().appendTo('#top')
    })
    

    Demo: Fiddle