LoginSignup
16
15

More than 5 years have passed since last update.

HTMLの<table>内をソートできるjQueryプラグイン

Last updated at Posted at 2015-07-15

jQueryプラグインとして作ってはみたものの、sortableという名前がいろいろとかぶっていることに気づいたので、github公開はよしてこっちに

使い方

  • <table> に sortable クラスを付与
  • ソートしたい <thead><th> に sort_number または sort_number_attr クラスを付与
  • <th> に sort_number_attr クラスを付与した列の <td> には、sort-value 属性でソート順の数値を指定
  • ソートアルゴリズムはマージソートなので安定ソート
  • ソートのキーにした列の <td> には sort_by_asc および sort_by_desc クラスが付与されるので、cssで色をつけたりできる

コード

jquery.sortable.js

;(function($) {
    $.fn.sortableInit = function(){
        var elements = this;

        var sortKeyClass = [
            'sort_number',
            'sort_number_attr'
        ];

        elements.each(function(){
            $(this).find('thead').find('tr:last').find('th').each(function(index){
                var self = this;
                // 対象クラスを持たない列にはソートボタンを表示しない
                if(!sortKeyClass.some(function(v){
                    return $(self).hasClass(v);
                })) return this;

                var func = null;
                var isAttr = null;
                // 数値型
                if ($(this).hasClass('sort_number')) {
                    func = mergeSortNumber;
                    isAttr = false;
                }
                // 属性数値型
                else if ($(this).hasClass('sort_number_attr')) {
                    func = mergeSortNumber;
                    isAttr = true;
                }

                var ascObj = $('<span>').html('').click(function(){
                    $(this).sortable(index, true, func, isAttr);
                }).css({"cursor":"pointer"});
                var descObj = $('<span>').html('').click(function(){
                    $(this).sortable(index, false, func, isAttr);
                }).css({"cursor":"pointer"});
                $(this).append($('<div>').addClass('sort_cursor').append(ascObj).append(descObj));
            });
        });

        return this;
    };

    $.fn.sortable = function(index, isAsc, func, isAttr){
        var element = this;

        var tbody = element.closest('table').find('tbody');
        // 色付けクラス削除
        tbody.find('td').removeClass('sort_by_asc sort_by_desc');
        var trs = [];
        tbody.find('tr').each(function(i){
            trs[i] = this;
        });
        trs = func(trs, index, isAsc, isAttr);
        tbody.empty().append(trs);
        // 色付けクラス追加
        tbody.find('tr').each(function(){
            $(this).find('td').eq(index).addClass(isAsc ? 'sort_by_asc' : 'sort_by_desc');
        });
        return this;
    };

    function mergeSortNumber(a, index, isAsc, isAttr) {
        var split = function(array) {
                if (array.length < 2) {
                    return array;
                }
                var a, b, mid = array.length / 2 | 0;
                a = split(array.slice(0, mid));
                b = split(array.slice(mid, array.length));

                return merge(array, a, b);
            },
            merge = function(array, a, b) {
                if (b === void 0) {
                    return array;
                }
                var c = [],
                    i, j;
                while (a.length > 0 && b.length > 0) {
                    if (isAttr) {
                        i = getValueAttr(a[0], index);
                        j = getValueAttr(b[0], index);
                    }
                    else {
                        i = getValueHtml(a[0], index);
                        j = getValueHtml(b[0], index);
                    }

                    if (isAsc) {
                        if (i <= j) {
                            c.push(a.shift());
                        } else {
                            c.push(b.shift());
                        }
                    } else {
                        if (i >= j) {
                            c.push(a.shift());
                        } else {
                            c.push(b.shift());
                        }
                    }
                }
                if (a.length === 0) {
                    c = c.concat(b);
                } else if (b.length === 0) {
                    c = c.concat(a);
                }
                return c;
            }
        return split(a);
    }

    function getValueHtml(tag, index) {
        return 1 * $(tag).find('td').eq(index).html();
    } 
    function getValueAttr(tag, index) {
        return 1 * $(tag).find('td').eq(index).attr('sort-value');
    } 
})(jQuery);

使用例

HTML

html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="jquery.sortable.js"></script>
<script>
$().ready(function(){
    $('.sortable').sortableInit();
});
</script>
<style>
.sort_by_asc {
    background-color: #ff9999;
}
.sort_by_desc {
    background-color: #9999ff;
}
</style>
</head>
<body>

<center>

<table class="sortable" border="1">

<thead>
<tr>
    <th class="sort_number">アラビア数字</th>
    <th class="sort_number_attr">漢字</th>
    <th>content</th>
</tr>
</thead>

<tbody>
<tr>
    <td>1</td>
    <td sort-value="1"></td>
    <td>漢字も数字も1番</td>
</tr>
<tr>
    <td>2</td>
    <td sort-value="3"></td>
    <td>漢字では3番</td>
</tr>
<tr>
    <td>3</td>
    <td sort-value="2"></td>
    <td>漢字では2番</td>
</tr>
</tbody>


</table>

</center>

</body>
</html>

元の状態

スクリーンショット 2015-07-15 13.01.30.png

漢字の昇順を押した

スクリーンショット 2015-07-15 13.14.45.png

アラビア数字の降順を押した

スクリーンショット 2015-07-15 13.14.33.png

16
15
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15