• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Tabellen Kopfzeile stehen lassen beim scrollen

Ich hab' mich mal auch ein bisschen hingesetzt - da machen die Browser echt manchmal seltsame Dinge, aber so könnte man damit arbeiten... ist zwar noch nicht perfekt, aber was soll's: Table with scrolling thead
Das ist effektmäßig schon ziemlich geil! Seltsamerweise ist das Scrollen mittels Bewegung des Scrollbalkens mit der Maus bei mir auf einem schwachbrüstigen Laptop mit IE9 etwas hakelig, wenn der Browser im Vollbild läuft. Reduziere ich den Browser nur geringfügig läuft es flüssig. Obwohl die CPU laut Taskmanager nicht wesentlich in die Höhe geht.
Kann man das noch optimieren?

Und noch eine Anmerkung: In dem Beispiel sind alle Spalten bereits auf Maximum Breite. Meine Tabellen stehen immer auf 100 % Breite und die Spalten sind häufig nicht auf Maximum, wenn die Anzeigebreite größer ist.
 
Und noch eine Anmerkung: In dem Beispiel sind alle Spalten bereits auf Maximum Breite. Meine Tabellen stehen immer auf 100 % Breite und die Spalten sind häufig nicht auf Maximum, wenn die Anzeigebreite größer ist.
Die Anmerkung verstehe ich jetzt nicht so ganz. Was meinst du mit maximum Breite?
 
Die Anmerkung verstehe ich jetzt nicht so ganz. Was meinst du mit maximum Breite?
Dito.

Dass das Ganze im IE etwas ruckelt (auch bei meine Laptop, der eigentlich nicht "schwach auf der Brust" ist) ist mir auch schon aufgefallen - den Grund hab' ich noch nicht so wirklich rausfinden können.

PS: im Safari und Chrome hat das Ganze einen ganz komischen Nebeneffekt, dass plötzlich zwischen thead und tbody ein Zwischenraum entsteht... k.A. warum.
 
Die Anmerkung verstehe ich jetzt nicht so ganz. Was meinst du mit maximum Breite?
In Korbinian's Beispiel hat die Tabelle nicht die Breite 100%, es sind rechts und links Ränder. Dadurch werden alle Spalten zusammen gedrückt.
Bei mir ist das meistens anders herum. Die Spalte aller Breiten sind weniger als 100 % der Anzeigebreite, sodass der Browser den restlichen Platz auf die Spalten verteilt.
Es wäre interessant, das Beispiel in diesem Fall einmal zu sehen. Insbesondere wie der Browser mit der Kopfzeile umgeht, wenn er die fixiert.
 
Die Spalte aller Breiten sind weniger als 100 % der Anzeigebreite, sodass der Browser den restlichen Platz auf die Spalten verteilt.
Welcher Breiten ???

Egal... Habe mal etwas die Browser analysiert, was die denn so treiben, wenn man thead und tbody voneinander trennt, sei es durch verschieben in eine andere Tabelle oder durch Herauslösen mittels position (absolute, relative oder fixed). Das Ergebnis ist einfach nur sch..... ehm schrott!!! Das Hauptproblem ist das bündige Abschließen der Zellen des Kopfbereichs mit den Zellen des Bodybereichs.

Habe mir auch mal kkapsners Beispiel angeschaut. Auch hier die selben Probleme: Kein bündiges Abschließen. Auch kommt das Script mit breiten Tabellenrahmen (20px oder so) ins schleudern. Eine relativ oder absolut positionierte Tabelle habe ich damit jedoch nicht getestet.

Habe es jetzt mal mit einem dritten Ansatz probiert und bin mit dem Ergebnis soweit am ehesten zufrieden.
Es werden unterschiedliche Rahmenbreiten unterstützt. Auch thin, middle und thick!
Es werden padding und margin unterstützt.
Es werden unterschiedliche Positionierungen unterstützt: absolute, relative, fixed und static
Entsprechend auch die Angaben für left und/oder top.

Damit die Kopfzeile beim Scrollen nicht zu sehr ruckelt, wird diese nachgezogen, heist sie folgt etwas verzögert der Scrollrichtung bis vor die letzte Zeile als Endpunkt bzw. bis zum Kopfbereich als Startpunkt.

Funktioniert soweit ich testen konnte in FF3.6+, Chrome, Opera, Maxthon und IE6/7/8.
Safari dürfte wie bei Maxthon funktionieren.
IE9/10 habe ich nicht zum Testen.
Das ganze kann man hier testen
 
Nicht schlecht - hatte auch schon mit dem Gedanken gespielt einfach die komplette Tabelle zu kopieren - aber das war mit nicht dynamisch genug. Wenn sich am Inhalt der Tabelle irgendwas dynamisch ändert läuft das ins Leere.

PS: Wenn der Seiten Aufbau sich vor der Tabelle ändert (z.B. ein <div> ein- oder ausgeblendet wird) stimmt die Scrollmarkierung nicht mehr.
PPS: Soll der tHead nicht bis ganz zum Ende der tBodies gehen?
 
Nicht schlecht - hatte auch schon mit dem Gedanken gespielt einfach die komplette Tabelle zu kopieren - aber das war mit nicht dynamisch genug. Wenn sich am Inhalt der Tabelle irgendwas dynamisch ändert läuft das ins Leere.
Ich nutze in Tabellen regelmäßig JS, um per Klick aus einem Anzeigefeld ein Eingabefeld zu machen, sende dann die Daten per Ajax zum Server und aktualisiere danach das Feld wieder zum Anzeigefeld. Fällst das auch darunter?
 
Hier nochmal kurz die Frage an miniA4kuser und Korbinian: Soll ich das mit der dynamischen Zelleninhaltsänderung per Ajax testen oder wißt ihr auch ohne Tests ob das funktioniert?
Es gibt noch eine Kleinigkeit: Ich brauche zwingend die Möglichkeit, bei einem Bildaufbau mittels window.scrollTo() zu einer Scrollposition zu springen. Das sollte die Tabelle natürlich auch sinnvoll verarbeitet bekommen. An dem scrollTo hänge ich nicht, wenn es andere Möglichkeiten gibt kann ich das ändern.
Wie gesagt: Es brauchen KEINE alten Browser unterstütz werden, das ist eine geschlossene Benutzergruppe!
 
Oh... hatte nur den ersten Post gesehen - mal wieder nicht aktualisiert.

Also wenn die dynamischen Änderungen die Spaltenbreiten/-höhen verändern fällt das darunter.

Das window.scrollTo() sollte eigentlich kein Problem darstellen, da das auch das onscroll-Event feuert.
 
Also wenn die dynamischen Änderungen die Spaltenbreiten/-höhen verändern fällt das darunter.
Ausschließen kann ich das nicht.
Aber ich sag es mal so, es kann dann entweder Text sein, der bei nicht ausreichender Spaltenbreite umgebrochen werden kann. Oder es sind Eingabefelder wie type=text oder <select>. Bei type=text arbeite ich mit 100 % width, wird also maximal so breit wie die Spalte. Und bei <select> weiß ich immer vorher, wie breit das maximal werden könnte. Das heißt, man könnte das vorher in einem unsichtbaren div erzeugen, Breite auslesen und die Spalte von vorn herein so breit setzen.

@miniA4kuser: Wie ist denn der Entwicklungsstand? Lohnt es sich für mich schon, es zu implementieren und zu testen? Oder kommen noch Änderungen, die schon absehbar sind, weil dir noch was aufgefallen ist? Bitte entschuldige die nervige Fragerei aber das ist keine Undankbarkeit sondern einfach meine Zeitnot :)
 
OK, hab es mal implementiert und mit Tests begonnen. Folgende Fragen habe ich:

1. Brauche ich zwingend das <caption> Tag? Welchen Zweck erfüllt es? Ich sehe im Code, dass dessen captionHeight ermittelt wird und später ganz häufig benötigt wird.

2. Der Code ermittelt in meiner Tabelle die Höhe der Kopfzeile nicht korrekt. Es wird nur ein ganz schmaler Streifen verwendet. Ich muss dazu sagen, dass ich die gelieferten CSS Definitionen nicht verwende, weil die nicht passen. Meine Frage nun, was ist ausschlaggebend für die korrekte Erkennung der Kopfzeile? <thead> und </thead> habe ich drin. Meine Kopfzeile besteht derzeit aus 8 Spalten und in jeder Zelle befindet sich eine zweizeilige <table> mit den Steuerelementen für die Sortierung. Worauf muss ich achten, dass die Kopfzeile richtig gegriffen werden kann?

Ansonsten sieht das schon ziemlich bombig aus. Hab auch schon am Code gefummelt, damit die ID flexibel ist:
HTML:
function fixedTableHeader(tID) {
	var patch = (new Date()).getTime(),
		fixedHeader = false,
		scrollTimeout = false,
		// Get the original table and sections
		jqTable = jQuery('#'+tID),
		jqCaption = jqTable.find('caption'),
		jqHead = jqTable.find('thead'),
		// Placeholders
		jqTableClone,
		jqHeadClone,
		jqTableWrapper,
		jqTableCloneWrapper,
		// Calculations
		startPosLeft,
		startPosTop,
		endPosTop,
		jqTableCloneWrapperHeight,
		jqTableCloneScrollEndHeight,
		jqTableWrapperCSS = {},
		jqTableCloneWrapperCSS = {},
		captionHeight = jqCaption.length > 0 ? jqCaption.outerHeight() : 0;

	// Wrap the original table
	jqTable.wrap('<div id="jqTableWrapper' + patch + '" />');
	jqTableWrapper = jQuery('#jqTableWrapper' + patch);

	// Validate css properties of jqTableWrapper
	jqTableWrapperCSS.width = jqTable.outerWidth();
	jqTableWrapperCSS.height = jqTable.outerHeight();
	jqTableWrapperCSS.marginTop = jqTable.css('marginTop');
	jqTableWrapperCSS.marginRight = jqTable.css('marginRight');
	jqTableWrapperCSS.marginBottom = jqTable.css('marginBottom');
	jqTableWrapperCSS.marginLeft = jqTable.css('marginLeft');
	jqTable.css('margin', 0);
	jqTableWrapperCSS.overflow = 'hidden';
	switch (jqTable.css('position')) {
	case 'fixed':
		return;
	case 'static':
		jqTableWrapperCSS.position = 'relative';
		break;
	case 'relative':
		jqTableWrapperCSS.position = 'relative';
		jqTableWrapperCSS.left = jqTable.css('left');
		jqTableWrapperCSS.top = jqTable.css('top');
		jqTable.css('left', 0);
		jqTable.css('top', 0);
		break;
	case 'absolute':
		jqTableWrapperCSS.position = 'absolute';
		jqTableWrapperCSS.left = jqTable.css('left');
		jqTableWrapperCSS.top = jqTable.css('top');
		jqTable.css('left', 0);
		jqTable.css('top', 0);
		break;
	}
	jqTableWrapper.css(jqTableWrapperCSS);

	// Clone original table and original thead
	jqTableClone = jqTable.clone();
	jqHeadClone = jqHead.clone();

	// Prevent double id and remove caption if one exists
	jqTableClone[0].id = 'jqTableClone' + patch;
	jqTableClone.find('caption').remove();

	// Get needed height to show only until thead bottom
	jqTableCloneWrapper = jqTableClone.clone();
	jqTableCloneWrapper.find('tbody').find('tr:not(:last)').remove();
	jqTableWrapper.after(jqTableCloneWrapper);
	jqTableCloneScrollEndHeight = jqTableCloneWrapper.outerHeight();
	jqTableCloneWrapper.find('caption').remove();
	jqTableCloneWrapper.find('tfoot').remove();
	jqTableCloneWrapper.find('tbody').remove();
	jqTableCloneWrapper.css('borderBottom', 0);
	jqTableCloneWrapperHeight = jqTableCloneWrapper.outerHeight();
	jqTableCloneScrollEndHeight += captionHeight;
	jqTableCloneWrapper.remove();

	// Append jqTableCloneWrapper after original table
	jqTable.after('<div id="jqTableCloneWrapper' + patch + '" />'
		);
	jqTableCloneWrapper = jQuery('#jqTableCloneWrapper' + patch);

	// Validate css properties of jqTableCloneWrapper
	jqTableCloneWrapperCSS.width = '100%';
	jqTableCloneWrapperCSS.overflow = 'hidden';
	jqTableCloneWrapperCSS.position = jqTableWrapperCSS.position === 'relative' ? 'absolute' : 'relative';
	jqTableCloneWrapperCSS.left = 0;
	jqTableCloneWrapperCSS.top = 0;
	jqTableCloneWrapper.css(jqTableCloneWrapperCSS);

	// Set jqTableCloneWrapper css properties and insert jqTableClone
	jqTableCloneWrapper.css({
		height: jqTableCloneWrapperHeight,
		top: captionHeight
	}).append(jqTableClone);

	// Exchange the headers for event handling
	jqTableClone.find('thead').remove();
	jqTableClone.prepend(jqHead);
	jqTable.prepend(jqHeadClone);

	// Set values for scrolling
	startPosLeft = jqTableWrapper.offset().left || jqTableWrapperCSS.left;
	startPosTop = jqTableWrapper.offset().top + captionHeight || jqTableWrapperCSS.top + captionHeight;
	endPosTop = startPosTop + jqTableWrapper.height() - jqTableCloneScrollEndHeight;

	// Let it scroll...
	jQuery(window).scroll(function () {
		var animatePosition,
			moveTop,
			scrollPosTop = jQuery(window).scrollTop();

		if (scrollTimeout) {
			clearTimeout(scrollTimeout);
			scrollTimeout = false;
		}

		animatePosition = function () {
			scrollTimeout = false;
			jqTableCloneWrapper.stop().animate({top: moveTop}, 400);
		};

		if (scrollPosTop > startPosTop) {
			if (!fixedHeader) {
				fixedHeader = true;
			}
			if (scrollPosTop < endPosTop) {
				moveTop = scrollPosTop + captionHeight - startPosTop;
				scrollTimeout = setTimeout(animatePosition, 50);
			} else {
				jqTableCloneWrapper.stop().css('top', endPosTop + captionHeight - startPosTop);
			}
		} else {
			scrollTimeout = false;
			jqTableCloneWrapper.stop().css('top', captionHeight);
			fixedHeader = false;
		}
	});
}
Danke euch
 
Zuletzt bearbeitet:
2. Der Code ermittelt in meiner Tabelle die Höhe der Kopfzeile nicht korrekt.
Hab mal versucht über ein Debugging der Variable jqHead dahinter zu steigen. Aber das ist ein mehrfach verschachteltes Objekt, soviel JS hab ich nicht drauf.
Bitte helft mir. Wie kann ich feststellen, warum das Script bei meiner Tabelle die Kopfzeile nicht vollständig nimmt sondern nur einen ganz schmalen Streifen davon?
 
1. Brauche ich zwingend das <caption> Tag? Welchen Zweck erfüllt es? Ich sehe im Code, dass dessen captionHeight ermittelt wird und später ganz häufig benötigt wird.
Nein das ist es nicht. Habe es nur zum Testen drinnen gehabt. Das Script berücksichtigt, ob ein <caption>-Tag vorhanden ist oder nicht.
 
2. Der Code ermittelt in meiner Tabelle die Höhe der Kopfzeile nicht korrekt. Es wird nur ein ganz schmaler Streifen verwendet. Ich muss dazu sagen, dass ich die gelieferten CSS Definitionen nicht verwende, weil die nicht passen. Meine Frage nun, was ist ausschlaggebend für die korrekte Erkennung der Kopfzeile? <thead> und </thead> habe ich drin. Meine Kopfzeile besteht derzeit aus 8 Spalten und in jeder Zelle befindet sich eine zweizeilige <table> mit den Steuerelementen für die Sortierung. Worauf muss ich achten, dass die Kopfzeile richtig gegriffen werden kann?
Sollte eigentlich passen. Hast du mal ein Screenshot davon? Kannst du die Struktur der Tabelle posten? Welche Art Sortierung verwendest du (welches Script etc.)? Werden nur Zeilen im <tbody> hinzugefügt? Oder werden auch Spalten hinzugefügt?

Bin grade am porbieren, werde evtl. später meine Testseite aktualisieren...
 
Sollte eigentlich passen. Hast du mal ein Screenshot davon?
Ja, siehe hier. Oben die Original Kopfzeile (Texte habe ich übermalt) und darunter sieht man den schmalen Streifen der beim Scrollen übrig ist :)
fixedtab_original.jpg
fixedtab_abbild.jpg

Kannst du die Struktur der Tabelle posten?
Ja, ist wie folgt (ich stelle hier im thead und tbody je nur eine Spalte dar, es sind natürlich mehr)
HTML:
<table>
	<thead>
		<tr>
			<td>
				<table>
					<tr>
						<td>
							<table>
								<tr>
									<td></td>
									<td></td>
									<td></td>
								</tr>
							</table>
						</td>
					</tr>
					<tr>
						<td></td>
					</tr>
				</table>
			</td>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td></td>
		</tr>
	</tbody>
</table>

Welche Art Sortierung verwendest du (welches Script etc.)?
Serverseitig. Habe Buttons in der Kopfzeile die ein <form> mit den nötigen Parametern absenden. Serverscript gibt das HTML mit sortierter Tabelle komplett fertig aus.

Werden nur Zeilen im <tbody> hinzugefügt? Oder werden auch Spalten hinzugefügt?
Du meinst dynamisch? Keins von beidem Wenn überhaupt ändere ich nur Zelleninhalte. Zeilen oder Spalten werden nicht geändert.
 
Zuletzt bearbeitet:
Zurück
Oben