Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   событие завершения отрисовки таблицы (https://javascript.ru/forum/events/68131-sobytie-zaversheniya-otrisovki-tablicy.html)

alexsum 28.03.2017 11:39

событие завершения отрисовки таблицы
 
Есть таблица, в которую динамически добавляются строки, соответственно может меняться ширина колонок.
Есть вторая таблица, которая представляет собой полную копию заголовка первой. (в т.ч. размеры)
Как отследить изменение ширины колонок первой для применения размеров во второй.
Интересует само событие, все остальное реализовано.
Если запускать функцию выравнивания размеров в функции обновления первой таблицы (добавление/изменение/удаление строк) то она отрабатывает по старым размерам.

рони 28.03.2017 12:19

alexsum,
вот что димнамически строки добавляет в первую то пусть и вторую таблицу корректирует.

alexsum 28.03.2017 12:42

рони,
так и есть, но, похоже, пока таблица не выведется (отрисуется), ширина столбцов не меняется. При "вот что димнамически строки добавляет в первую то пусть и вторую таблицу корректирует" размеры берутся еще старые

laimas 28.03.2017 12:57

Цитата:

Сообщение от alexsum
Интересует само событие

http://frontender.info/mutation-observers-tutorial/

рони 28.03.2017 13:09

alexsum,
function addData() {
   //здесь изменили 1 таблицу
  window.setTimeout(function () {
   //здесь получили размер первой и изменили вторую
},0)

}

alexsum 28.03.2017 20:36

рони,
с таймером не получится потому как может быть и 1000 записей и медленное железо, т.е. записи обработались, сработал выравниватель, а уже потом пошел вывод и реальное изменение ширины

рони 28.03.2017 20:44

alexsum,
вам виднее

alexsum 29.03.2017 09:05

laimas,
то-же, что и с таймаутом

laimas 29.03.2017 12:06

Цитата:

Сообщение от alexsum
то-же, что и с таймаутом

Значит не смогли применить должным образом.

alexsum 03.04.2017 09:33

// setFixedTableHeader(name) создает клон заголовка таблицы
// resetFixedTableHeader(name) обновляет клон заголовка после обновления основной таблицы
// clearFixedTableHeader(name) удаляет клон заголовка таблицы

function setFixedTableHeader(name){
	var newthead="";
	if(! $("#"+name+"_topdiv").length){
		$("#"+name).wrap("<div style=\"overflow: auto; height:100%; width:100%;\" id=\""+name+"_topdiv\" ></div>");
	}
	if($("#"+name+"_thd").length){
		$("#"+name+"_thd").remove();
	}
	var zindex=$("#"+name).css("z-index");
	if(isNaN(zindex)){
		zindex=1;
	}else{
		zindex++;
	}
	$("#"+name).before("<table style=\"background-color:white;z-index:"+zindex+";position:fixed;width:"+$("#"+name).width()+"px\" id='"+name+"_thd'><thead></thead></table>");
	if(! $("#"+name+"_topdiv1").length){
		$("#"+name).wrap("<div style=\"overflow: auto; height:100%; width:100%;overflow-y: scroll;\" id=\""+name+"_topdiv1\" ></div>");
	}
	$('#'+name+' thead th').each(function(){
		var stlh=$(this).attr("style");
		if(typeof stlh !== "undefined"){
			stlo=' stlh="'+stlh+'" ';
		}else{
			stlo="";
			stlh="";
		}
		var cls=$(this).attr("class");
		if(typeof cls === "undefined"){
			cls="";
		}
		var ids=$(this).attr("id");
		if(typeof ids !== "undefined"){
			ids=' id="'+ids+'" ';
		}else{ids="";}
		var names=$(this).attr("name");
		if(typeof names !== "undefined"){
			names=' name="'+names+'" ';
		}else{names="";}
		
		newthead=$("<th "+ids+names+" style=\"/*border:1px solid white;*/"+stlh+";width:"+ $(this).width()+"px;height:"+$(this).height()+"px;\" "+stlo+">"+$(this).text()+"</th>");
		newthead=$("<th "+ids+names+" style=\"/*border:1px solid grey;*/"+stlh+";width:"+ $(this).width()+"px;/*height:"+$(this).height()+"px;*/\" "+stlo+">"+$(this).text()+"</th>");
		$('#'+name+'_thd thead').append(newthead);
		if(cls.length>0){
			newthead.addClass(cls);
		}
	});
	$("#"+name+"_thd").css("top",$("#"+name).css("top"));
	$("#"+name).css({
		position: "relative"
	});

	var $viewport = $(window); 

	$viewport.scroll(function(){
		FTHsetOffset(name);
	});	
	
	$( window ).resize(function() {
		clearTimeout(FTHdoit);
		FTHdoit=setTimeout(resetFixedTableHeader(name),150);
	});	

	FTHsetOffset(name);		
	
	if(!$("#resetfixsedtablediv").length){
		$("body").prepend("<div style='display:none' id='resetfixsedtablediv'></div>");
		addObserverIfDesiredNodeAvailable();
	}
}

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;


var composeObserver = new MutationObserver(function(mutations) { 
	mutations.forEach(function(mutation) {	
	});
	refreshTimer();
});
		
function refreshTimer(){
	$("#resetfixsedtablediv div").each(function(){
		resetFTH($(this).attr('refresh'));
		console.log('rfth '+$(this).attr('refresh'));
		$(this).remove();
	});			
}
		
function addObserverIfDesiredNodeAvailable() {
	var composeBox = document.querySelector('#resetfixsedtablediv');
	if(!composeBox) {
		window.setTimeout(addObserverIfDesiredNodeAvailable,500);
		return;
	}
	var config = {
			attributes: false, 
			childList: true, 
			characterData: false 
		};
	composeObserver.observe(composeBox,config);
}		


var FTHdoit;

function FTHsetOffset(name){
	if($("#"+name+"_thd").length){
		var left=$("#"+name+"_thd").parent().offset().left;
		var top=$("#"+name+"_thd").parent().offset().top;//+ $("#"+name).position().top - $("#"+name+"_thd").height();;
		var st=$('html,body').scrollTop();
		if(st==0){
			st=$('body').scrollTop();
		}
		var ctop=-st + top;
		ctop=$("#"+name+"_topdiv").offset().top-st;
		if(ctop<0){ctop=0;}
		if(top + $("#"+name+"_thd").parent().height()-$("#"+name+"_thd").height()<(st)){ctop=-top;}

		$("#"+name+"_thd").css({
			left: -$(this).scrollLeft() + left,
			top: ctop
		});
	}
}
function clearFixedTableHeader(name){
	$("#"+name+"_thd thead th").each(function(index,value){
		$("#"+name+" thead th:eq("+index+")").text($(value).text());
	});
	$("#"+name+"_thd").remove();
}


function resetFixedTableHeader(name){
	var doit=true;
	$("#resetfixsedtablediv div").each(function(){
		if($(this).attr('refresh')==name) doid=false;
	});	
	if(doit)
		$("#resetfixsedtablediv").append("<div refresh='"+name+"'></div>");
}


function resetFTH(name){
	$("#"+name+"_thd").hide();
	$("#"+name+"_thd").width($("#"+name).width());
	$("#"+name+" thead th").each(function(index,value){
		$("#"+name+"_thd thead th:eq("+index+")").html($(value).html());
		$("#"+name+"_thd thead th:eq("+index+")").width($(value).width());
		$("#"+name+"_thd thead th:eq("+index+")").height($(value).height());
	});			
	FTHsetOffset(name);	
	$("#"+name+"_thd").show();
}

где-то так. так и не работает

laimas 03.04.2017 12:14

Наблюдатель да еще плюс таймер (в помощь что-ли?), это круто.

Трудно сказать что там за таблица, но к примеру, первая ее строка задает размеры, значит достаточно следить за ячейками этой строки - вставка в них данных. Может не это, а по описанным в ссылке примерам сначала, что-от простое, а затем...?

alexsum 04.04.2017 09:42

Цитата:

Сообщение от laimas (Сообщение 449104)
Наблюдатель да еще плюс таймер (в помощь что-ли?), это круто.

все равно не работает. пробовал уже все варианты до которых...
по первой строке следить не получится - не обязательно в первой будет изменение, хотя такое тоже возможно. строки могут добавляться и при этом меняться ширина столбцов.
как вы заметили, после полного обновления таблицы запускается соответствующая функция, которая изменяет "обновлялкин" див, за которым собственно и наблюдает наблюдатель. и все равно не работает

laimas 04.04.2017 09:58

Не нужно наблюдателю никакого таймера - ему поставлена задача отследить вставку/изменения/итд... отследил, сообщил.

А если изменения всех ячеек таблицы, то может быть и не нужно ничего, а задать размеры столбцам, к примеру в процентах, в зависимости от содержимого. Ведь очень сложно сосредоточится на содержимом если оно "скачет", не так ли?

alexsum 06.04.2017 09:59

да таймер уже как крайний костыль из серии "мало-ли", просто не убрал

задумка такая: создалась таблица - запустил setHeader.
обновилась - запустил resetHeader.
resetHeader создает div за которым и следит наблюдатель + какая конкретно таблица обновилась. Наблюдатель заметил - обновил ширину заголовков.

laimas 06.04.2017 18:04

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<style>
table {
    border-collapse: separate;
}
td {
    border: 1px solid #666;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
    var callback = function(){
        alert(tbl.rows[0].cells[0].offsetWidth+'/'+tbl.rows[0].cells[1].offsetWidth);
    },
    options = {
        'childList': true,
        'subtree': true
    },
    observer = new MutationObserver(callback),
    tbl = document.querySelector('table');
    
    observer.observe(tbl, options);
    
    document.querySelector('button').onclick = function() {
        tbl.rows[0].cells[0].innerHTML = 'aaaaaaaaaaa';
        tbl.rows[0].cells[1].innerHTML = 'bbbbbbbbbbbbbbbbbbbb';
    }    
});
</script> 
</head>
<body>
<table><tr><td></td><td></td></tr></table>
<button>Insert</button>
</body>
</html>

alexsum 12.04.2017 11:14

laimas,
У меня все так и работает (не работает). Единственно есть подозрение, что $("#resetfixsedtablediv").append("<div refresh='"+name+"'></div>"); после обработки таблицы (скриптом но до загрузки на экран- построения полной модели) отрабатывает раньше, чем собственно таблица дообработается

alexsum 13.04.2017 12:53

// setFixedTableHeader(name) создает клон заголовка таблицы
// resetFixedTableHeader(name) обновляет клон заголовка после обновления основной таблицы // заглушка для совместимости
// clearFixedTableHeader(name) удаляет клон заголовка таблицы

function setFixedTableHeader(name){
	var newthead="";
	if(! $("#"+name+"_topdiv").length){
		$("#"+name).wrap("<div style=\"overflow: auto; height:100%; width:100%;\" id=\""+name+"_topdiv\" ></div>");
	}
	if($("#"+name+"_thd").length){
		$("#"+name+"_thd").remove();
	}
	var zindex=$("#"+name).css("z-index");
	if(isNaN(zindex)){
		zindex=1;
	}else{
		zindex++;
	}
	$("#"+name).before("<table style=\"background-color:white;z-index:"+zindex+";position:fixed;width:"+$("#"+name).width()+"px\" id='"+name+"_thd'><thead></thead></table>");
	if(! $("#"+name+"_topdiv1").length){
		$("#"+name).wrap("<div style=\"overflow: auto; height:100%; width:100%;overflow-y: scroll;\" id=\""+name+"_topdiv1\" ></div>");
	}
	$('#'+name+' thead th').each(function(){
		var stlh=$(this).attr("style");
		if(typeof stlh !== "undefined"){
			stlo=' stlh="'+stlh+'" ';
		}else{
			stlo="";
			stlh="";
		}
		var cls=$(this).attr("class");
		if(typeof cls === "undefined"){
			cls="";
		}
		var ids=$(this).attr("id");
		if(typeof ids !== "undefined"){
			ids=' id="'+ids+'" ';
		}else{ids="";}
		var names=$(this).attr("name");
		if(typeof names !== "undefined"){
			names=' name="'+names+'" ';
		}else{names="";}
		
		newthead=$("<th "+ids+names+" style=\"/*border:1px solid white;*/"+stlh+";width:"+ $(this).width()+"px;height:"+$(this).height()+"px;\" "+stlo+">"+$(this).text()+"</th>");
		newthead=$("<th "+ids+names+" style=\"/*border:1px solid grey;*/"+stlh+";width:"+ $(this).width()+"px;/*height:"+$(this).height()+"px;*/\" "+stlo+">"+$(this).text()+"</th>");
		$('#'+name+'_thd thead').append(newthead);
		if(cls.length>0){
			newthead.addClass(cls);
		}
	});
	$("#"+name+"_thd").css("top",$("#"+name).css("top"));
	$("#"+name).css({
		position: "relative"
	});

	var $viewport = $(window); 

	$viewport.scroll(function(){
		FTHsetOffset(name);
	});	
	
	$( window ).resize(function() {
		clearTimeout(FTHdoit);
		FTHdoit=setTimeout(resetFixedTableHeader(name),150);
	});	

	FTHsetOffset(name);		
	
	if(!$("#resetfixsedtablediv").length){
		$("body").prepend("<div style='display:none' id='resetfixsedtablediv'></div>");
		
	}
	
	var doit=true;
	$("#resetfixsedtablediv div").each(function(){
		if($(this).attr('refresh')==name){ 
			doit=false;
		}
	});	
	if(doit){
//		alert(name);
		$("#resetfixsedtablediv").append("<div refresh='"+name+"'></div>");	
		addObserverIfDesiredNodeAvailable(name);
	}else{
		for (var i = 0; i < observ.length; i++) {
			observ[i].disconnect();;
		}
		observ=[];
		$("#resetfixsedtablediv div").each(function(){
			if(document.getElementById($(this).attr('refresh'))){
				addObserverIfDesiredNodeAvailable($(this).attr('refresh'));
			}else{
				$(this).remove();
			}
		});		
	}
	
}

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

var observ = [];

		
function refreshTimer(){
	$("#resetfixsedtablediv div").each(function(){
		resetFTH($(this).attr('refresh'));
		console.log('rfth '+$(this).attr('refresh'));
//		$(this).remove();
	});			
}
		
function addObserverIfDesiredNodeAvailable(name) {
	var composeBox = document.querySelector('#'+name);
	if(!composeBox) {
		window.setTimeout(addObserverIfDesiredNodeAvailable(name),500);
		return;
	}
	var config = {
			'attributes': false, 
			'childList': true, 
			'characterData': false,
			'subtree': true
		};
	var composeObserver = new MutationObserver(function() { 
		refreshTimer();
	});		
	composeObserver.observe(composeBox,config);
	observ.push(composeObserver);
}	


var FTHdoit;

function FTHsetOffset(name){
	if($("#"+name+"_thd").length){
		var left=$("#"+name+"_thd").parent().offset().left;
		var top=$("#"+name+"_thd").parent().offset().top;//+ $("#"+name).position().top - $("#"+name+"_thd").height();;
		var st=$('html,body').scrollTop();
		if(st==0){
			st=$('body').scrollTop();
		}
		var ctop=-st + top;
		ctop=$("#"+name+"_topdiv").offset().top-st;
		if(ctop<0){ctop=0;}
		if(top + $("#"+name+"_thd").parent().height()-$("#"+name+"_thd").height()<(st)){ctop=-top;}

		$("#"+name+"_thd").css({
			left: -$(this).scrollLeft() + left,
			top: ctop
		});
	}
}
function clearFixedTableHeader(name){
	$("#"+name+"_thd thead th").each(function(index,value){
		$("#"+name+" thead th:eq("+index+")").text($(value).text());
	});
	$("#"+name+"_thd").remove();
}


function resetFixedTableHeader(name){
/*	заглушка*/
}


function resetFTH(name){
	$("#"+name+"_thd").hide();
	$("#"+name+"_thd").width($("#"+name).width());
	$("#"+name+" thead th").each(function(index,value){
		$("#"+name+"_thd thead th:eq("+index+")").html($(value).html());
		$("#"+name+"_thd thead th:eq("+index+")").width($(value).width());
		$("#"+name+"_thd thead th:eq("+index+")").height($(value).height());
	});			
	FTHsetOffset(name);	
	$("#"+name+"_thd").show();
}


Вот так под ФФ работает, под Хромом - нет

laimas 13.04.2017 13:10

Зачем вы скрещиваете наблюдателя с таймером?

alexsum 18.04.2017 09:30

Цитата:

Сообщение от laimas (Сообщение 449923)
Зачем вы скрещиваете наблюдателя с таймером?

не наблюдаю такого.

laimas 18.04.2017 09:39

Цитата:

Сообщение от alexsum
не наблюдаю такого.

А это зачем window.setTimeout(addObserverIfDesiredNodeAvailabl e(name),500);?

А это для чего observ.push(composeObserver);?

alexsum 18.04.2017 15:57

1. - если объект с именем "name" еще не загрузился (были прецеденты, оставил на "мало-ли"), хотя можно наверно удалить.
2. так массив наблюдателей-же. Если создаешь второй без массива - первый работать перестает, проверено


Тут как-бы предусмотрено, что может быть несколько таблиц на одну страницу

laimas 18.04.2017 18:29

1 - что значит не загрузился?
2 - надо полагать, что вы следите не затем, чем следовало бы.

alexsum 19.04.2017 10:34

с 1 согласен
со 2 - а за чем-же?

laimas 19.04.2017 18:18

Изначально условием было "Есть таблица, в которую динамически добавляются строки, соответственно может меняться ширина колонок. Есть вторая таблица, которая представляет собой полную копию заголовка первой.". Следовательно, наблюдая за изменением DOM первой таблицы решаем задачу.

Если же множество таблиц, то какой объект должен быть наблюдаемым? Конечно же тот, который является родителем этих таблиц. Вы же вместо наблюдения за ним пытаетесь решать задачу множеством наблюдателей героически борясь с проблемами порождаемыми этим решением.

Отложите пока в строну свои таблицы. На простом примере с одной таблицей модифицируйте ее ячейки, циклом, а в наблюдателе выводите в консоль его записи MutationRecord. Это будет массив таких записей, количество которых будет равно количеству модифицируемых ячеек таблицы. При этом каждая запись MutationRecord, это объект несущий информацию способный ответить на все ваши вопросы.

Разве этого недостаточно?

alexsum 24.04.2017 09:16

Имеется ввиду несколько таблиц со своими заголовками и соответственно своими дополнительными таблицами

laimas 24.04.2017 10:02

Да на здоровье, определитесь с тем во что добавляется, а значит и зачем следить, вот и все.


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