Jak zamrozić pierwszą i ostatnią kolumnę tabeli html w przewijalnym div?

Mam tabelę, która ma wiersz nagłówka, ale także kolumnę nagłówka i kolumnę całkowitą z kilkoma kolumnami pomiędzy.

Coś takiego:

Name    Score 1    Score 2  ...  Total
--------------------------------------
John       5          6            86
Will       3          7            82
Nick       7          1            74

Cała tabela jest zdefiniowana wewnątrz przewijalnego div o stałej szerokości, ponieważ prawdopodobnie istnieje duża liczba wierszy "Score" i mam układ strony o stałej szerokości.

<div id="tableWrapper" style="overflow-x: auto; width: 500px;">
    <table id="scoreTable">
        ...
    </table>
</div>

Chciałbym, aby pierwsze (Name) i Ostatnie (Total) kolumny pozostały widoczne podczas przewijania wewnętrznych kolumn.

Czy ktoś może pomożesz mi z tym?

Edit: chodzi mi tylko o przewijanie poziome-zmieniłem aby to określić.


Update: sam rozwiązałem ten problem i zamieściłem odpowiedź poniżej. Daj znać, jeśli potrzebujesz więcej informacji - to było trochę trudne do zrobienia i nie chciałbym, aby ktoś inny musiał wszystko przepisać.

Author: Christopher Rapcewicz, 2009-04-13

7 answers

Czy mogę zaproponować nieco niekonwencjonalne rozwiązanie?

Co sądzisz o umieszczeniu kolumny 'total' po kolumnie' name', a nie na samym końcu? Czy nie uniknie to wymogu przewijania tylko części tabeli?

To nie jest dokładnie to, o co prosisz, ale być może jest to wystarczające rozwiązanie, biorąc pod uwagę, że alternatywa byłaby dość niechlujna. (Np. umieszczenie kolumn "total" I "name" poza tabelą spowoduje wyrównanie problemy, gdy nie wszystkie rzędy są jednakowej wysokości. Możesz to poprawić za pomocą javascript, ale wtedy wkraczasz w zupełnie nowy świat bólu).

Również z punktu widzenia interfejsu użytkownika, może być tak, że "nazwa" i "suma" są najważniejszymi danymi, w którym to przypadku sensowne byłoby złożenie ich razem, a następnie rodzaj "podziału" sumy. Oczywiście, wydaje się, że mamy intuicję, że "suma" powinna pochodzić po jego częściach składowych, ale nie sądzę, że spowodowałoby to zbyt wiele zamieszania dla użytkownik, jeśli zamówienie zostało odwrócone w ten sposób (choć jest to pytanie dla Ciebie, na podstawie produktu i użytkowników).

W każdym razie, coś do rozważenia.

EDIT:

Oto kilka bardziej niekonwencjonalnych rozwiązań, teraz, gdy myślę, że rozumiem twoje intencje nieco lepiej:

  1. pogrupuj wyniki. Podaj ostatnie dziesięć, powiedzmy, i całość, i link do starszych punktów, które są przyznawane po 10 na raz
  2. podaj tylko nazwy, sumy i inne znaczące środki takich jak średnia i sd, a następnie zapewnić link do każdej nazwy, która pokazuje wszystkie wyniki odpowiadające temu nazwisko. Możesz wtedy również zapewnić link pokazujący wszystkie wyniki dla a biorąc pod uwagę zestaw punktów, tak aby porównania między różnymi użytkownikami można zrobić. Chodzi o to, że wystarczy podać 1 wymiar danych dla każdego widoku, a nie posiadanie nieporęcznego zestawu danych 2D
  3. aby wiersze sortowalne (łatwe z jQuery UI) tak, że jeśli chcę porównaj Mary z Jane, mogę ciągnąć i umieść jeden po drugim, więc nie będę trzeba przewijać w lewo i prawo do sprawdzenia, które wyniki odpowiadają do których nazw
  4. Podświetl wiersz po kliknięciu, zmieniając tło kolor lub podobne, ponownie, więc nie muszę przewijać w lewo iw prawo.

W każdym razie masz pomysł. Być może lepiej jest szukać rozwiązania interfejsu użytkownika niż wypaczonego rozwiązania znaczników. Ostatecznie zastanawiałbym się, jak ważne jest, aby przedstawić tak wiele danych do użytkownik od razu, że jego część musi przewijać w określony sposób, aby dane były czytelne. Być może budujesz aplikację arkusza kalkulacyjnego i naprawdę musisz wyświetlić matrycę 100x100 w jednym widoku. Jeśli nie, z pewnością możesz wymyślić bardziej kreatywne sposoby, niż muszę podzielić wyniki.

 5
Author: ozan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-13 13:54:27

Spójrz na ten plugin jQuery:

Http://fixedheadertable.com/

 3
Author: Markos Fragkakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-04 15:42:39

Nie jest teraz kompletny (tylko wyśmiałem go bardzo szybko), ale oto sposób na zrobienie tego za pomocą prostego HTML. Chcesz trzy stoliki ... dwa Na Zewnątrz

I jeden wewnątrz
. Wszystkie trzy są unoszone w lewo, więc wszystkie są na tej samej linii.

Test Tabeli

I sam kod:

  <table style="float: left;">
     <tr>
        <td>Name</td>
     </tr>
     <tr>
        <td>John</td>
     </tr>
     <tr>
        <td>Will</td>
     </tr>
  </table>
  <div id="tableWrapper" style="overflow-x: auto; width: 500px;float:left;padding-bottom: 10px;">
      <table>
        <tr>
           <td>Score1</td>
           <td>Score2</td>
           ...
        </tr>
        <tr>
           <td>5</td>
           <td>6</td>
           ...
        </tr>
        <tr>
           <td>3</td>
           <td>7</td>
           ...
        </tr>
        <tr>
           <td>7</td>
           <td>1</td>
           ...
        </tr>
      </table>
  </div>
  <table style="float: left;">
     <tr>
        <td>Total</td>
     </tr>
     <tr>
        <td>86</td>
     </tr>
     <tr>
        <td>82</td>
     </tr>
  </table>

Uwaga: padding-bottom na div jest tak, że pasek przewijania nie zasłania tabeli w IE. Ponadto, błąd, który muszę wypracować, to jak określić szerokość elementów nagłówka wewnątrz Środkowej tabeli. Z jakiegoś powodu określenie atrybutu width=" " nie działa. Tak więc, jeśli tekst elementu nagłówka jest zbyt szeroki (i łamie się na inną linię), to układ jest łamany (wyłączony o jeden wiersz)

 2
Author: cmptrgeekken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-13 13:21:24

Zakładam, że chcesz przewijać tylko w poziomie. W przeciwnym razie mogłoby to być mylące z kolumnami statycznymi.

Można umieścić overflow: auto na elemencie zawierającym tylko wewnętrzne komórki tabeli... Nie jestem pewien, jak przeglądarki poradziłyby sobie z tym, ale być może będziesz w stanie umieścić elementy, które chcesz naprawić wewnątrz elementów thead i tfoot, i umieścić część przewijania wewnątrz elementu tbody i ustawić jego przepełnienie na auto.

W przeciwnym razie może być konieczne porzucenie semantyki i kodu lewa kolumna i prawa kolumna poza tabelą.

Osobiście spróbowałbym zakodować go tak semantycznie, jak to możliwe, a następnie użyć JavaScript, aby ustawić lewą i prawą kolumnę. Bez JavaScript, powinieneś sprawić, że nie uda się to tylko szerokiej tabeli (Nie wiem, jak trudne byłoby to, jak mówisz, że masz stałą szerokość)

Możesz spróbować tego (przybliżonego) przykładu jQuery, aby umieścić wartości pierwszej kolumny na zewnątrz.

var nameTable = '<table id="outside-name-col">
                  <thead>
                   <tr>
                    <th>Name</th>
                   </tr>
                  </thead>
                 <tbody>'; // start making a table for name column only

$('#scoreTable tbody tr').each(function() { // iterate through existing table

   var nameCol = $(this).find(':first'); // get column of index 0, i.e. first

   var cellHeight = nameCol.height(); // get the height of this cell

   $(this).find('td').height(cellHeight); // equalise the height across the row so removing this element will not collapse the height if it is taller than the scores and total       

   nameTable += '<tr><td style="height: ' + cellHeight + 'px">' + nameCol.html() + '</td></tr>'; // append the next row with new height and data

   nameCol.remove(); // remove this cell from the table now it's been placed outside

});

nameTable += '</tbody></table>'; // finish table string


$('#scoreTable').before(nameTable); // insert just before the score table

Użyj CSS, aby ustawić je poprawnie. To jest nieprzetestowane, ale powinno dać ci jakiś pomysł.

 2
Author: alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-14 13:12:46

Eksperymentowałem z kilkoma metodami (dzięki wszystkim, którzy pomogli) i oto co wymyśliłem używając jQuery. Wydaje się, że działa dobrze we wszystkich przeglądarkach, które testowałem. Możesz go wziąć i używać, jak chcesz. Następnym krokiem będzie dla mnie przekształcenie go w wtyczkę jQuery wielokrotnego użytku.

Podsumowanie:

Zacząłem od normalnej tabeli ze wszystkim w niej ( Id="ladderTable"), i napisałem trzy metody - jedna do rozebrania pierwszej kolumny, druga do rozebrania ostatniej kolumny, a jeden do ustalenia wysokości wiersza.

Metoda stripFirstColumn tworzy nową tabelę ( Id="nameTable"), przemieszcza oryginalną tabelę i usuwa pierwszą kolumnę i dodaje te komórki do nameTable.

Metoda stripLastColumn robi zasadniczo to samo, z wyjątkiem tego, że usuwa ostatnią kolumnę i Dodaje komórki do nowej tabeli o nazwie totalTable .

Metoda fixHeights patrzy na każdy wiersz w każdej tabeli, oblicza maksymalną wysokość i stosuje ją do powiązanych tabel.

W zdarzeniu document ready wywołałem wszystkie trzy metody w kolejności. Zauważ, że wszystkie trzy tabele unoszą się w lewo, więc będą układać się poziomo.

Struktura HTML:

<h1>Current Ladder</h1> 
<div id="nameTableSpan" style="float:left;width:100px;border-right:2px solid gray;"></div> 
<div id="ladderDiv" style="float:left;width:423px;overflow:auto;border:1px solid gray;margin-top:-1px;"> 
    <table id="ladderTable" class="ladderTable">
        <thead> 
            <tr><td>Name</td><td>Round 1</td> ... <td>Round 50</td><td class="scoreTotal">Total</td></tr>
        </thead>
        <tr><td>Bob</td><td>11</td> ... <td>75</td><td>421</td></tr>
           ... (more scores)
    </table>
</div>
<div id="totalTableSpan" style="float:left;width:70px;border-left:2px solid gray;"></div> 

JQuery:

function stripFirstColumn() {                
    // pull out first column:
    var nt = $('<table id="nameTable" cellpadding="3" cellspacing="0" style="width:100px;"></table>');
    $('#ladderTable tr').each(function(i)
    {
        nt.append('<tr><td style="color:'+$(this).children('td:first').css('color')+'">'+$(this).children('td:first').html()+'</td></tr>');
    });
    nt.appendTo('#nameTableSpan');
    // remove original first column
    $('#ladderTable tr').each(function(i)
    {
        $(this).children('td:first').remove();
    });
    $('#nameTable td:first').css('background-color','#8DB4B7');
}

function stripLastColumn() {                
    // pull out last column:
    var nt = $('<table id="totalTable" cellpadding="3" cellspacing="0" style="width:70px;"></table>');
    $('#ladderTable tr').each(function(i)
    {
        nt.append('<tr><td style="color:'+$(this).children('td:last').css('color')+'">'+$(this).children('td:last').html()+'</td></tr>');
    });
    nt.appendTo('#totalTableSpan');
    // remove original last column
    $('#ladderTable tr').each(function(i)
    {
        $(this).children('td:last').remove();
    });
    $('#totalTable td:first').css('background-color','#8DB4B7');
}

function fixHeights() {
    // change heights:
    var curRow = 1;
    $('#ladderTable tr').each(function(i){
        // get heights
        var c1 = $('#nameTable tr:nth-child('+curRow+')').height();    // column 1
        var c2 = $(this).height();    // column 2
        var c3 = $('#totalTable tr:nth-child('+curRow+')').height();    // column 3
        var maxHeight = Math.max(c1, Math.max(c2, c3));

        //$('#log').append('Row '+curRow+' c1=' + c1 +' c2=' + c2 +' c3=' + c3 +'  max height = '+maxHeight+'<br/>');

        // set heights
        //$('#nameTable tr:nth-child('+curRow+')').height(maxHeight);
        $('#nameTable tr:nth-child('+curRow+') td:first').height(maxHeight);
        //$('#log').append('NameTable: '+$('#nameTable tr:nth-child('+curRow+')').height()+'<br/>');
        //$(this).height(maxHeight);
        $(this).children('td:first').height(maxHeight);
        //$('#log').append('MainTable: '+$(this).height()+'<br/>');
        //$('#totalTable tr:nth-child('+curRow+')').height(maxHeight);
        $('#totalTable tr:nth-child('+curRow+') td:first').height(maxHeight);
        //$('#log').append('TotalTable: '+$('#totalTable tr:nth-child('+curRow+')').height()+'<br/>');

        curRow++;
    });

    if ($.browser.msie)
        $('#ladderDiv').height($('#ladderDiv').height()+18);
}

$(document).ready(function() {
    stripFirstColumn();
    stripLastColumn();
    fixHeights();
    $("#ladderDiv").attr('scrollLeft', $("#ladderDiv").attr('scrollWidth'));    // scroll to the last round
});

Jeśli masz jakieś pytania lub jest coś, co nie było jasne, jestem bardziej niż szczęśliwy, aby pomóc.

Zajęło mi to trochę czasu, zanim zorientowałem się, że nie ma nic, co mógłbym ponownie wykorzystać i napisanie tego zajęło trochę więcej czasu. Nie chciałbym, żeby ktoś zadał sobie tyle samo trudu.
 2
Author: Damovisa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-22 07:21:26

Czy chodziło Ci o przewijanie poziome??

Jeśli chcesz osiągnąć poziome przewijanie, możesz użyć 3 kontenerów.

  1. dla pierwszej kolumny (Nazwa)
  2. dla kolumn, które chcesz przewijać. Ustawia styl overflow-x tego kontenera na auto
  3. dla ostatniej kolumny (razem)
 1
Author: rahul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-13 11:58:50

Przewijanie zawartości tabel jest problematycznym problemem, ponieważ nie ma prostego i bezpiecznego dla przeglądarki rozwiązania, aby to osiągnąć.

Najlepszy i najbezpieczniejszy sposób to zrobić wymaga JavaScript. Można osiągnąć nawet poziome przewijanie łatwo (jest dołączony za darmo) z tej techniki użyłem. Możesz łatwo przekształcić to w swój problem:

1) zrobiłem 3 tabele

2) umieszczono środkową tabelę, która przechowuje dane w kontenerze DIV

3) Ustaw styl DIV na overflow: auto

4) dał nagłówek i stopkę tabeli i div każdy Szerokość 100%

5) otoczony wszystko przez inny div do kontroli ogólnej szerokości tabeli

6) upewnił się, że ilość kolumn jest zgodna we wszystkich trzech tabelach i że wszystkie trzy mają te same style dotyczące paddingów, marginesów i obramowań

Teraz ciekawa część:

6) poniżej ostatniego elementu konstrukcji tabeli, napisz blok javascript (lub dołącz go z plik)

7) napisz funkcję, która kolejno patrzy na każdą kolumnę (użyj pętli for), zaczynając od pierwszej. Przy każdej iteracji tej pętli sprawdź komórkę td z dwóch pierwszych tabel w bieżącej kolumnie. Sprawdź, które z jest większe i przypisz to do stylu mniejszej komórki td. Możesz również zastosować tę wartość do tabeli stopki.

8) wywołaj tę funkcję. Możesz to zrobić w interwale lub gdy wystąpią specjalne zdarzenia, takie jak nowe dane w komórki (jeśli używa się na przykład ajax).

Uwaga: Jeśli przewijasz poziomo, rozmiary kolumn są zsynchronizowane. Ale będziesz musiał zsynchronizować pozycję przewijania tabeli nagłówka i stopki z tabelą treści. Alternatywnie po prostu pozwól ogólnemu div przewijać całość w poziomie, ale nie w pionie. To byłoby zadanie DIV, który zawiera tabelę danych.

Ta technika działała bardzo dobrze we wszystkich głównych przeglądarkach na bardzo coplex diagramie Gantta projekt.

Uwaga: możesz łatwo myśleć o tej koncepcji w sposób obracany o 90 stopni, dzięki czemu naprawisz pierwszą i ostatnią kolumnę nagłówka podczas przewijania.

Edit: oto kolejny przykład z mojej bazy kodu, który może pomóc Ci znaleźć rozwiązanie:

var left_td = document.getElementById("left_td");
var right_td = document.getElementById("right_td");
var contentDiv = document.getElementById("contentDiv");
window.setInterval(function(){
    var left_td_width = Math.round((parseInt(contentDIV.offsetWidth) - 120) / 2);
    var right_td_width = (parseInt(contentDIV.offsetWidth) - left_td_width - 120;

    left_td.style.width = left_td_width + "px";
    right_td.style.width = right_td_width + "px";
}, 25);

Ten kod wykonuje następujące czynności: upewnia się, że Tabela z 3 kolumnami zawsze wygląda tak: pierwsza i ostatnia kolumna mają ten sam rozmiar, a środkowa kolumna ma szerokość 120 pikseli. Oczywiście, że nie ma zastosowania bezpośrednio do twojego specjalnego problemu, ale może to dać ci punkt wyjścia w dynamicznej manipulacji tabelą za pomocą JavaScript.

 0
Author: Thanks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-13 13:16:12