16
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?