nepp95
nepp95

Reputation: 146

jQuery sort cards with up/down arrows

I am using Bootstrap cards on a page, where I want those cards to be sorted using up and down arrows. Every card has arrows in its header, to move it up or down in the layout. But of course, when it gets moved to the top, the up arrow should be gone, likewise for when it hits the bottom.

I've tried using if statements in this style:

// Result: Is never executed.
if(!$(card).find('.sort-down')) {}

// Result: Is always executed.
if($(card).not(':has(.sort-down)') {}

Where $(card) is the div containing the complete card that is being moved. For example, my complete "move down" code block.

$(document).on('click', '.sort-down', function(e) {
    e.preventDefault();
    let card = $(this).closest('.card');
    let sort_id = $(card).attr('data-sort');
    let next_sort_id = Number(sort_id) + 1;

    $('[data-sort]').each(function(index, value) {
        if($(value).attr('data-sort') == next_sort_id) {
            $(value).after($(card));
            $(value).attr('data-sort', sort_id);
            $(card).attr('data-sort', next_sort_id);

            // Change buttons
            if($(card).attr('data-sort') == sortCount - 1) {
                $(card).find('.sort-down').remove();
                if(!$(card).find('.sort-up')) {
                    // Insert up arrow
                }
            } else {
                if(!$(card).find('.sort-up')) {
                    // Insert up arrow
                }
                if(!$(card).find('.sort-down')) {
                    // Insert down arrow
                }
            }

            if($(value).attr('data-sort') == 0) {
                $(value).find('.sort-up').remove();
                if(!$(value).find('.sort-down')) {
                    // Insert down arrow
                }
            } else {
                if(!$(value).find('.sort-down')) {
                    // Insert down arrow
                }
                if(!$(value).find('.sort-up')) {
                    // Insert up arrow
                }
            }

            return false;
        }
    });
});

A little bit of the HTML so you can get an idea what classes/attributes my jQuery is selecting.

<div class="card mb-3" data-sort="0">
    <div class="card-header">
        Tekstveld
        <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-down"><i data-feather="arrow-down" width="16" height="16"></i></button>
    </div>
    <div class="card-body p-0">
        <div id="editor"></div>
    </div>
</div>

As I usually overcomplicate things, and get the result of it not even working, I'm hoping you could help me with either a simple or more advanced working solution of getting this done.

Upvotes: 0

Views: 2614

Answers (1)

Bilel
Bilel

Reputation: 1429

Using data-sort attribute as a sorting index could be more useful for "Global" sorting or filtering. Like when we click on one button to sort them all based on that property value.

But here, a less complicated alternative is to use jQuery default methods like : next(),prev(),closest(),insertAfter(),insertBefore()

$( document ).ready(function() {
setButtons();
$(document).on('click', '.sort-down', function(e) {
var cCard = $(this).closest('.card');
var tCard = cCard.next('.card');
cCard.insertAfter(tCard);
setButtons();
resetSort();
});

$(document).on('click', '.sort-up', function(e) {
var cCard = $(this).closest('.card');
var tCard = cCard.prev('.card');
cCard.insertBefore(tCard);
setButtons();
resetSort();

});


function resetSort(){
var i=0;
$('.card').each(function(){
//$(this).data('sort',i);
$(this).attr("data-sort", i);
i++;
});

}

function setButtons(){
    $('button').show();
    $('.card:first-child  button.sort-up').hide();
    $('.card:last-child  button.sort-down').hide();
}



function resetSort(){
var i=0;
$('.card').each(function(){
//$(this).data('sort',i);
$(this).attr("data-sort", i);
i++;
});
}

});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="card mb-3" data-sort="0">
    <div class="card-header">
        Tekstveld
        <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-down"><i class="fas fa-caret-down"></i></button>
        <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-up"><i class="fas fa-caret-up"></i></button>      
    </div>
    <div class="card-body p-0">
        <div class="editor"></div>
    </div>
</div>
<div class="card mb-3" data-sort="1">
    <div class="card-header">
        Voorbeeld
            <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-down"><i class="fas fa-caret-down"></i></button>
        <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-up"><i class="fas fa-caret-up"></i></button>     
    </div>
    <div class="card-body p-0">
        <div class="editor"></div>
    </div>
</div>
<div class="card mb-3" data-sort="2">
    <div class="card-header">
        Lorem ipsum
              <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-down"><i class="fas fa-caret-down"></i></button>
        <button type="button" class="btn btn-sm btn-primary float-right mr-1 sort-up"><i class="fas fa-caret-up"></i></button>    
    </div>
    <div class="card-body p-0">
        <div class="editor"></div>
    </div>
</div>
</div>

[UPDATE] : The setButtons() function would hide the non functional buttons when the div reach the limit.

Notice that I added another function resetSort() to reorder those data-sort values. Just in case, you need it for global sorting.

Upvotes: 2

Related Questions