Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   При клике на заголовок таблицы отсортировать таблицу (https://javascript.ru/forum/jquery/69798-pri-klike-na-zagolovok-tablicy-otsortirovat-tablicu.html)

Neo54213 18.07.2017 14:13

При клике на заголовок таблицы отсортировать таблицу
 
Дано: 4 заказа(массив массивов), в каждом по 5 пунктов(массив объектов)(ручка, карандаш, линейка и т.д.). В каждом пункте 4 параметра: номер пункта, название(ручка, карандаш...)(поля объекта). Данные я отрисовываю в таблицу. После клика по одному из заголовков таблицы(id, название...), нужно отсортировать таблицу по данному критерию. Но вот беда: если текст в заголовках("Номер", "Название"), а название полей в объекте: name, id. Как определить по какому параметру сортировать? Вот, допустим, я кликнул по столбцу "Имя". Как дать понять программе, что нужно сортировать по полю name в объекте?

Dilettante_Pro 18.07.2017 14:23

Neo54213,
Цитата:

Сообщение от Neo54213
Данные я отрисовываю в таблицу.

Цитата:

Сообщение от Neo54213
а название полей в объекте: name, id.

Вы уже нарисовали таблицу - зачем вам объект?
Сортируйте таблицу
https://learn.javascript.ru/task/sort-table

Neo54213 18.07.2017 14:45

Ну я написал код таким образом, что таблица отрисовывается и сортируется по имени. После по нажатию на заголовок столбца(th) нужно отсортировать таблицу по указанному критерию(т.е. нажали на th "Название" - сортируем по названию. Нажали на th с текстом "Номер" сортируем по id.

рони 18.07.2017 14:48

Neo54213,
на форуме масса примеров сортировки таблиц, и может вы покажите ваш код?

рони 18.07.2017 14:53

Neo54213,
сортировка таблицы по клику на ячейку первой строки

Neo54213 18.07.2017 15:04

var headers = ['Номер', 'Название', 'Количество', 'Цена'];
var fieldsNames = ['id', 'name', 'count', 'price'];
var orders = [
    [
        {
            id: 1,
            name: "Book",
            count: 3,
            price: 157
        },
        {
            id: 2,
            name: "Pen",
            count: 4,
            price: 85
        },
        {
            id: 3,
            name: "Phone",
            count: 1,
            price: 464
        },
        {
            id: 4,
            name: "Pencil",
            count: 65,
            price: 314
        },
        {
            id: 5,
            name: "Sharpener",
            count: 6,
            price: 96
        }
    ],
    [
        {
            id: 1,
            name: "Tape",
            count: 5,
            price: 543
        },
        {
            id: 2,
            name: "Textbook",
            count: 65,
            price: 314
        },
        {
            id: 3,
            name: "Pencil case",
            count: 35,
            price: 346
        },
        {
            id: 4,
            name: "Desk",
            count: 5,
            price: 4314
        },
        {
            id: 5,
            name: "Marker",
            count: 5,
            price: 145
        }
    ],
    [
        {
            id: 1,
            name: "Paper",
            count: 5,
            price: 87
        },
        {
            id: 2,
            name: "Chalk",
            count: 6,
            price: 435
        },
        {
            id: 3,
            name: "Clock",
            count: 8,
            price: 563
        },
        {
            id: 4,
            name: "Ruler",
            count: 22,
            price: 457
        },
        {
            id: 5,
            name: "Globe",
            count: 7,
            price: 789
        }
    ],
    [
        {
            id: 1,
            name: "Chair",
            count: 2,
            price: 54
        },
        {
            id: 2,
            name: "Eraser",
            count: 56,
            price: 2445
        },
        {
            id: 3,
            name: "Map",
            count: 11,
            price: 345
        },
        {
            id: 4,
            name: "Scissors",
            count: 24,
            price: 451
        },
        {
            id: 5,
            name: "Notebook",
            count: 32,
            price: 654
        }
    ]
];

function clearSortImage(exceptionTHId) {
    $('th:not(th:nth-child(' + +(exceptionTHId+1) + '))')
        .removeClass('asc')
        .removeClass('desc')
        .find('.indicator-image').hide();
}
function drawTabs() {
    for (var i = 0; i < orders.length; i++) {
        $('<div>', {
            text: 'Заказ ' + +(i+1),
            class: 'button order' + +(i+1),
            data: {
                id: i
            }
        }).appendTo($('header'));
    }
}
function drawTHs() {
    for (var i = 0; i < headers.length; i++) {
        var $thead = $('section #orderstable thead');
        var $th = $('<th>', {
            text: headers[i],
            data: {
                id: i
            }
        });

        var $indicatorImage = $('<img>', {
            alt: 'индикатор сортировки',
            class: 'indicator-image'
        });

        $th.prepend($indicatorImage);
        $thead.append($th);
    }
}
function sortTable(clickedHeader) {
    var $th = $('section #orderstable th');
    var headerIndex = $th.index($(clickedHeader));
    var fieldName = fieldsNames[headerIndex];
    var $divSelected = $('div.selected');
    var orderIdx = $divSelected.data('id');
    var order = orders[orderIdx];

    if($(clickedHeader).hasClass('asc')) {
        if (typeof order[0][fieldName] == "number") {
            order.sort(function (a, b) {
                return b[fieldName] - a[fieldName];
            });
        } else {
            order.sort(function (a, b) {
                if (a[fieldName] > b[fieldName]) {
                    return -1;
                }
                if (a[fieldName] < b[fieldName]) {
                    return 1;
                }
                return 0;
            });
        }
        $(clickedHeader).addClass('desc').removeClass('asc')
            .find('.indicator-image').attr('src', 'img/desc.png');
    }else{
        if(typeof order[0][fieldName] == "number"){
            order.sort(function(a, b) {
                return a[fieldName]-b[fieldName];
            });
        }else{
            order.sort(function(a, b) {
                if (a[fieldName] < b[fieldName]) {
                    return -1;
                }
                if (a[fieldName] > b[fieldName]) {
                    return 1;
                }
                return 0;
            });
        }
        $(clickedHeader).addClass('asc').removeClass('desc').find('.indicator-image').attr('src', 'img/asc.png');
    }
    $(clickedHeader).find('.indicator-image').show();

    $divSelected.click();
}

function drawTable(clickedButton) {
    var $tbody = $('#orderstable tbody')
    $tbody.empty();
    var orderIdx = $(clickedButton).data('id');
    var order = orders[orderIdx];
    for (var i = 0; i < order.length; i++) {
        var item = order[i];
        var $tr = $('<tr>');
        for (var column in item){
            var $td = $('<td>', {
                text: item[column]
            });
            $tr.append($td);
        }
        $tbody.append($tr);
    }
}

$(document).ready(function() {
    drawTabs();
    drawTHs();

    $('.button').on('click', function() {

        var $tbody = $('#orderstable tbody');
        if(!$(this).hasClass('selected')) {
            $('th').removeClass('asc')
                .removeClass('desc')
                .find('.indicator-image').hide();
        }

        $('.button').removeClass('selected');
        $(this).addClass('selected');

        drawTable(this);
    });

    $('th').on('click', function() {
        // var exceptionTHId = $(this).index();
        clearSortImage(/*exceptionTHId*/);
        sortTable(this);
    });

    $('section header .order2').click();
    $('#orderstable th.name').click();
});


Да мне просто ответ на вопрос нужен: как получить доступ к полю объекта? Вот, допустим, кликнул я по "Название". Как мне понять, что сортировать нужно по полю: name в объекте?
order.sort(function(a, b) {
                return a[fieldName]-b[fieldName];
            });

Вот этот кусок я написал, но как получить этот самый fieldName?
Вот во второй строке у меня то, чего быть не должно var fieldsNames = ['id', 'name', 'count', 'price']; Это костыль.

рони 18.07.2017 15:23

Цитата:

Сообщение от Neo54213
как получить этот самый fieldName?

function drawTHs() {
    var $thead = $("section #orderstable thead");
    headers.forEach(function(text, i) {
        var fieldsName = fieldsNames[i];
        var $th = $("<th>", {
            click: function() {
                superSort(fieldsName)
            },
            text: text,
            data: {
                id: i
            }
        });
        var $indicatorImage = $("<img>", {
            alt: "индикатор сортировки",
            "class": "indicator-image"
        });
        $th.prepend($indicatorImage);
        $thead.append($th)
    })
};

Neo54213 18.07.2017 15:28

А если без массива fieldsName? Ведь это дублирующиеся данные. Эти ключи у меня уже есть в объекте.

рони 18.07.2017 15:43

Neo54213,
:-? superSort(i)

Neo54213 18.07.2017 15:57

рони,
итак, i это индекс th(начиная с нуля, первый th - i=0). Дальше мне в функции superSort(вот она кстати ниже) нужно отсортировать массив по какому-либо столбцу. Этот столбец, допустим, третий. Как теперь по индексу получить доступ к полю? Ну т.е. что нам это дает, что мы знаем номер столбца? Как я с помощью цифры, например, 1, которую мы передали в функцию superSort() при клике на th с текстом "Название", получу доступ к полю name в объекте?
var $th = $('section #orderstable th');
    var fieldName = // что сюда записать? массив fieldsNames отсутствует
    var $divSelected = $('div.selected');
    var orderIdx = $divSelected.data('id');
    var order = orders[orderIdx];
if($(clickedHeader).hasClass('asc')) {
        if (typeof order[0][fieldName] == "number") {
            order.sort(function (a, b) {
                return b[fieldName] - a[fieldName];
            });
        } else {
            order.sort(function (a, b) {
                if (a[fieldName] > b[fieldName]) {
                    return -1;
                }
                if (a[fieldName] < b[fieldName]) {
                    return 1;
                }
                return 0;
            });
        }
        $(clickedHeader).addClass('desc').removeClass('asc')
            .find('.indicator-image').attr('src', 'img/desc.png');
    }else{
        if(typeof order[0][fieldName] == "number"){
            order.sort(function(a, b) {
                return a[fieldName]-b[fieldName];
            });
        }else{
            order.sort(function(a, b) {
                if (a[fieldName] < b[fieldName]) {
                    return -1;
                }
                if (a[fieldName] > b[fieldName]) {
                    return 1;
                }
                return 0;
            });
        }
        $(clickedHeader).addClass('asc').removeClass('desc').find('.indicator-image').attr('src', 'img/asc.png');
    }

рони 18.07.2017 16:09

Neo54213,
мне сложно понять ваш код, не могу ничего подсказать ... как хотя бы выглядит ваша таблица? (если несложно html таблицы напишите)

Neo54213 18.07.2017 16:46

рони,

Хорошо. Вопрос проще, без кода. Как, зная индекс ключа в объекте получить данные из этого поля? Допустим, объект var obj = {firstName: "Vasya", lastName: "Pupkin", age: 33} Я хочу обратиться ко второму полю(в нашем случае lastName). Но я знаю его порядковый индекс(который равен 1), а названия(собственно, lastName) я не знаю. Могу ли я как-то по индексу 1(т.к. это второй ключ в объекте) получить данные из этого поля? obj[1] не работает.

Manyasha 18.07.2017 16:59

Neo54213,
var obj = {firstName: "Vasya", lastName: "Pupkin", age: 33}
alert(Object.keys(obj)[1])

Neo54213 18.07.2017 17:12

Manyasha,
достаточно неочевидное решение. Спасибо!

рони 18.07.2017 17:17

Цитата:

Сообщение от Neo54213
индекс ключа в объекте

такого нет в js пока
можно конечно так, но это без гарантии, что key во всех тестах будет "lastName", а не что-нибудь ещё.

var obj = {firstName: "Vasya", lastName: "Pupkin", age: 33};
var k = 1;
var key = Object.keys(obj)[k];
alert(obj[key]);

рони 18.07.2017 17:27

Neo54213,
в-каком-порядке-перебираются-свойства

Manyasha 18.07.2017 18:26

может так?
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.9.0.min.js"></script>
<script>
var headers = ['Номер', 'Название', 'Количество', 'Цена'];
var fieldsNames = ['id', 'name', 'count', 'price'];
var orders = [
        {
            id: 1,
            name: "Book",
            count: 3,
            price: 157
        },
        {
            id: 2,
            name: "Pen",
            count: 4,
            price: 85
        },
        {
            id: 3,
            name: "Phone",
            count: 1,
            price: 464
        },
        {
            id: 4,
            name: "Pencil",
            count: 65,
            price: 314
        },
        {
            id: 5,
            name: "Sharpener",
            count: 6,
            price: 96
        }
];
</script>
</head>
<table>
    <tr>
        <th class='id'>Номер</th>
        <th class='name asc'>Название</th>
        <th class='count'>Количество</th>
        <th class='price'>Цена</th>
    </tr>
</table>
<script>
$('th').click(function(){
	var key = $(this).attr('class').replace(' asc', '').replace(' desc', '');
	orders.sort(function (a, b) {
		return b[key] - a[key];
	});
	//console.log(orders)
	console.log(JSON.stringify(orders))
})
</script>

рони 18.07.2017 23:00

создание и сортировка таблицы
 
Neo54213,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  .up span.indicator{
  display:   inline-block;
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-bottom: 16px solid red;

  }
  .dn span.indicator{
  display:  inline-block;
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 16px solid red;

  }
  span.indicator{
  display:  inline-block;
  width: 16px;
  height: 16px;
  }
  .act{
    background-color: #D3D3D3;
  }
  .button{
    display: inline-block;
     border: 1px #191970 solid;
     margin: 4px 2px;
     cursor:  pointer;
  }
  th{
    cursor:  pointer;
  }

  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

  <script>
$(function() {
var headers = ['Номер', 'Название', 'Количество', 'Цена'];
var fieldsNames = ['id', 'name', 'count', 'price'];
var orders = [
    [
        {
            id: 1,
            name: "Book",
            count: 3,
            price: 157
        },
        {
            id: 2,
            name: "Pen",
            count: 4,
            price: 85
        },
        {
            id: 3,
            name: "Phone",
            count: 1,
            price: 464
        },
        {
            id: 4,
            name: "Pencil",
            count: 65,
            price: 314
        },
        {
            id: 5,
            name: "Sharpener",
            count: 6,
            price: 96
        }
    ],
    [
        {
            id: 1,
            name: "Tape",
            count: 5,
            price: 543
        },
        {
            id: 2,
            name: "Textbook",
            count: 65,
            price: 314
        },
        {
            id: 3,
            name: "Pencil case",
            count: 35,
            price: 346
        },
        {
            id: 4,
            name: "Desk",
            count: 5,
            price: 4314
        },
        {
            id: 5,
            name: "Marker",
            count: 5,
            price: 145
        }
    ],
    [
        {
            id: 1,
            name: "Paper",
            count: 5,
            price: 87
        },
        {
            id: 2,
            name: "Chalk",
            count: 6,
            price: 435
        },
        {
            id: 3,
            name: "Clock",
            count: 8,
            price: 563
        },
        {
            id: 4,
            name: "Ruler",
            count: 22,
            price: 457
        },
        {
            id: 5,
            name: "Globe",
            count: 7,
            price: 789
        }
    ],
    [
        {
            id: 1,
            name: "Chair",
            count: 2,
            price: 54
        },
        {
            id: 2,
            name: "Eraser",
            count: 56,
            price: 2445
        },
        {
            id: 3,
            name: "Map",
            count: 11,
            price: 345
        },
        {
            id: 4,
            name: "Scissors",
            count: 24,
            price: 451
        },
        {
            id: 5,
            name: "Notebook",
            count: 32,
            price: 654
        }
    ]
];
var section = $("section");
var header = $("<header>").appendTo(section);
var table = $("<table>", {"id": "orderstable"}).appendTo(section);
var thead = $("<thead>").appendTo(table);
var tbody = $("<tbody>").appendTo(table);
var tbodyContent = orders.map(function(trs, i) {
    $("<div>", {
        text: "Заказ " + +(i + 1),
        "class": "button order" + +(i + 1),
        click: function() {
            tbody.html(tbodyContent[i]);
            $("th", thead).removeClass("up dn");
            $(".button", header).removeClass("act");
            $(this).addClass("act")
        }
    }).appendTo(header);
    return trs.map(function(tds) {
        var tr = $("<tr>");
        fieldsNames.forEach(function(key, i) {
            $("<td>", {
                text: tds[key]
            }).appendTo(tr)
        });
        return tr
    })
});

function fnSort(i) {
    return function(b, a) {
        a = $("td", a).eq(i).text();
        b = $("td", b).eq(i).text();
        b = +b || b;
        a = +a || a;
        return b > a ? 1 : b < a ? -1 : 0
    }
}
headers.forEach(function(text, i) {
    var fn = fnSort(i),
        k = 0;
    var th = $("<th>", {
        click: function() {
            k ^= 1;
            var tr = $("tr", tbody).get().sort(fn);
            k && (tr = tr.reverse());
            tbody.append(tr);
            $("th", thead).removeClass("up dn");
            th.addClass(k ? "up" : "dn")
        },
        text: text
    });
    var indicator = $("<span>", {
        "class": "indicator"
    });
    th.prepend(indicator);
    thead.append(th);
});
$(".button:first").click();
});
  </script>
</head>

<body>
<section></section>

</body>
</html>

Vlasenko Fedor 19.07.2017 14:34

моя реализация сортировки :haha:
<div id="search-menu">
  <p>Сортировать по :</p>
  <a class="btn" data-sort="user_name" href="#">Имя<span></span></a>
  <a class="btn" data-sort="user_age" href="#">Возраст</a>
</div>

<!-- result -->
<div id="search-results">

  <!-- user #1 -->
  <div class="user">
    <img src="photo_0.jpg" alt="#" class="user_photo">
    <div class="user_name">Peter</div>
    <div class="user_age">20 Age</div>
    <div class="user_about">Bla_bla_bla...description...</div>
  </div>

  <!-- user #2 -->
  <div class="user">
    <img src="photo_1.jpg" alt="#" class="user_photo">
    <div class="user_name">Alex</div>
    <div class="user_age">30 Age</div>
    <div class="user_about">Bla_bla_bla...description...</div>
  </div>

  <!-- user #3 -->
  <div class="user">
    <img src="photo_2.jpg" alt="#" class="user_photo">
    <div class="user_name">Max</div>
    <div class="user_age">27 Age</div>
    <div class="user_about">Bla_bla_bla...description...</div>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
(function($) {
  var $content = $("#search-results");
  var $users = $('.user', $content);
  $('#search-menu').on('click', 'a', function(e) {
    e.preventDefault();
    sortContent($(this));
  });

  function sortContent($el) {
    var type = '.' + $el.data('sort');
    var sort = $el.hasClass('sort-up') ? 1 : -1;
    $users.sort(function(a, b) {
      return sort * $(type, b).text().toLowerCase().localeCompare($(type, a).text().toLowerCase());
    }).appendTo($content);
    sort > 0 ? $el.removeClass('sort-up').addClass('sort-down') : $el.removeClass('sort-down').addClass('sort-up');
  }
}(jQuery));
</script>


Часовой пояс GMT +3, время: 15:05.