событие завершения отрисовки таблицы
Есть таблица, в которую динамически добавляются строки, соответственно может меняться ширина колонок.
Есть вторая таблица, которая представляет собой полную копию заголовка первой. (в т.ч. размеры) Как отследить изменение ширины колонок первой для применения размеров во второй. Интересует само событие, все остальное реализовано. Если запускать функцию выравнивания размеров в функции обновления первой таблицы (добавление/изменение/удаление строк) то она отрабатывает по старым размерам. |
alexsum,
вот что димнамически строки добавляет в первую то пусть и вторую таблицу корректирует. |
рони,
так и есть, но, похоже, пока таблица не выведется (отрисуется), ширина столбцов не меняется. При "вот что димнамически строки добавляет в первую то пусть и вторую таблицу корректирует" размеры берутся еще старые |
Цитата:
|
alexsum,
function addData() { //здесь изменили 1 таблицу window.setTimeout(function () { //здесь получили размер первой и изменили вторую },0) } |
рони,
с таймером не получится потому как может быть и 1000 записей и медленное железо, т.е. записи обработались, сработал выравниватель, а уже потом пошел вывод и реальное изменение ширины |
alexsum,
вам виднее |
laimas,
то-же, что и с таймаутом |
Цитата:
|
// 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(); } где-то так. так и не работает |
Наблюдатель да еще плюс таймер (в помощь что-ли?), это круто.
Трудно сказать что там за таблица, но к примеру, первая ее строка задает размеры, значит достаточно следить за ячейками этой строки - вставка в них данных. Может не это, а по описанным в ссылке примерам сначала, что-от простое, а затем...? |
Цитата:
по первой строке следить не получится - не обязательно в первой будет изменение, хотя такое тоже возможно. строки могут добавляться и при этом меняться ширина столбцов. как вы заметили, после полного обновления таблицы запускается соответствующая функция, которая изменяет "обновлялкин" див, за которым собственно и наблюдает наблюдатель. и все равно не работает |
Не нужно наблюдателю никакого таймера - ему поставлена задача отследить вставку/изменения/итд... отследил, сообщил.
А если изменения всех ячеек таблицы, то может быть и не нужно ничего, а задать размеры столбцам, к примеру в процентах, в зависимости от содержимого. Ведь очень сложно сосредоточится на содержимом если оно "скачет", не так ли? |
да таймер уже как крайний костыль из серии "мало-ли", просто не убрал
задумка такая: создалась таблица - запустил setHeader. обновилась - запустил resetHeader. resetHeader создает div за которым и следит наблюдатель + какая конкретно таблица обновилась. Наблюдатель заметил - обновил ширину заголовков. |
<!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> |
laimas,
У меня все так и работает (не работает). Единственно есть подозрение, что $("#resetfixsedtablediv").append("<div refresh='"+name+"'></div>"); после обработки таблицы (скриптом но до загрузки на экран- построения полной модели) отрабатывает раньше, чем собственно таблица дообработается |
// 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(); } Вот так под ФФ работает, под Хромом - нет |
Зачем вы скрещиваете наблюдателя с таймером?
|
Цитата:
|
Цитата:
А это для чего observ.push(composeObserver);? |
1. - если объект с именем "name" еще не загрузился (были прецеденты, оставил на "мало-ли"), хотя можно наверно удалить.
2. так массив наблюдателей-же. Если создаешь второй без массива - первый работать перестает, проверено Тут как-бы предусмотрено, что может быть несколько таблиц на одну страницу |
1 - что значит не загрузился?
2 - надо полагать, что вы следите не затем, чем следовало бы. |
с 1 согласен
со 2 - а за чем-же? |
Изначально условием было "Есть таблица, в которую динамически добавляются строки, соответственно может меняться ширина колонок. Есть вторая таблица, которая представляет собой полную копию заголовка первой.". Следовательно, наблюдая за изменением DOM первой таблицы решаем задачу.
Если же множество таблиц, то какой объект должен быть наблюдаемым? Конечно же тот, который является родителем этих таблиц. Вы же вместо наблюдения за ним пытаетесь решать задачу множеством наблюдателей героически борясь с проблемами порождаемыми этим решением. Отложите пока в строну свои таблицы. На простом примере с одной таблицей модифицируйте ее ячейки, циклом, а в наблюдателе выводите в консоль его записи MutationRecord. Это будет массив таких записей, количество которых будет равно количеству модифицируемых ячеек таблицы. При этом каждая запись MutationRecord, это объект несущий информацию способный ответить на все ваши вопросы. Разве этого недостаточно? |
Имеется ввиду несколько таблиц со своими заголовками и соответственно своими дополнительными таблицами
|
Да на здоровье, определитесь с тем во что добавляется, а значит и зачем следить, вот и все.
|
Часовой пояс GMT +3, время: 21:10. |