Общий предок
Как получить общего предка двух элементов (в DOM'е)? Есть простые способы, или нужно самому писать?
|
нужно самому писать
|
Если по классу как-то так наверное, набросок:
function parent(class1,class2){ var e=document.getElementsByClassName(class1)[0]; while((e=e.parentNode)&&!e.getElementsByClassName(class2)[0]); return e } |
Не удивлён, однако...
|
Нет классов. Два абсолютно любых элемента. С какой стороны лучше подступиться?
|
Я думаю, общий смысл должен быть таким:
function mutualParent(elem1, elem2){ var test; while(elem1 !== document.body){ elem1 = elem1.parentNode; test = elem2; while(test !== document.body){ test = test.parentNode; if(test === elem1) return test; }; }; return null; }; |
от, только толсто, много циклов, но работает
<body> <div> <div id="multi-parent"> <div> <div id="firstChild"></div> </div> <div> <div> <div id="secondChild"></div> </div> </div> </div> </div> <script type="text/javascript"> var $ = function(n){return document.getElementById(n);} var getPerent = function(fe,se){ var body = document.getElementsByTagName("body")[0]; var parentF = fe.parentNode; var parentS = se.parentNode; var arrayParantsF = []; var arrayParantsS = []; while(true){ if(parentF!=body){ arrayParantsF[arrayParantsF.length]=parentF; parentF = parentF.parentNode; }else{ break; } } while(true){ if(parentS!=body){ arrayParantsS[arrayParantsS.length]=parentS; parentS = parentS.parentNode; }else{ break; } } for(i=0;i<arrayParantsF.length;i++){ for(j=0;j<arrayParantsS.length;j++){ if(arrayParantsF[i]==arrayParantsS[j]) return arrayParantsS[j]; } } return body; } alert(getPerent($("firstChild"),$("secondChild")).id); </script> </body> |
Это я написал)) Я просто надеялся... А вдруг! Как-то проше... Но нет. Жестокая реальность показала смехотворную необоснованность моих надежд.
|
Slawaq, о боже, что это??
|
Всё можно оптимизировать, потом покажу как.)
|
Цитата:
|
вообще-то от что получилось :)
<body> <div> <div id="multi-parent"> <div> <div id="firstChild"></div> </div> <div> <div> <div id="secondChild"></div> </div> </div> </div> </div> <script type="text/javascript"> var $ = function(n){return document.getElementById(n);} var getParent = function(fe,se){ var parentF = fe.parentNode; while(true) if(parentTest(se,parentF)) return parentF; else parentF=parentF.parentNode; return document.body; } function parentTest(child,parent){ while(true){ if(child.parentNode==parent) return true; else if(child.parentNode!=document.body) child=child.parentNode; else break; } return false; } alert(getParent($("firstChild"),$("secondChild")).id); </script> </body> |
function getParent ( firstElem, secondElem ) { var parent; while ( parent != document.body ) { parent = firstElem.parentNode, child = parent.firstChild; while ( child ) { if ( child == secondElem ) { return parent; } child = child.nextSibling; } parent = parent.parentNode; } return parent; } Агоритм не рабочий |
Slawaq, зачем каждый раз body получать через getElementsByTagName?
nikita.mmf, не думаю, что через .nextSibling будет эффективно. Скорее наоборот. |
Sweet, сложно сказать, это все зависит структуры, мне так кажется, это как бы поиск в глубину и поиск в ширину. Навскидку трудоемкость вашего алгоритма О(n^2), а у моего O(n*m), где n - число родителей до body, а m - макимальное число детей у одного родителя.
|
nikita.mmf, у меня ваш скрипт не работает, только всё лагать начинает...
|
Народ, вы чего. У нас же тут не математические вычисления с длинными числами. Средняя вложенность элемента на странице - 15-20 родителей. Соответственно, не более 400 операций сравнения при худшем раскладе. С таким даже алгоритм Slawaq'а быстро справится.
UPD: мне даже кажется, что про 15-20 - я загнул. |
function unitedParent(first,second){ var parents=function(e){var a=[];while(e=e.parentNode)a.push(e);return a} var f=parents(first), s=parents(second), fl=f.length, sl=s.length; while(f[--fl]&&f[fl]===s[--sl]); return f[fl+1]||null } |
Aetae, у вас ошибка. Грубо говоря, если обзывать предков числами, то при сравнении элемента с таким массивом предков: [0, 1, 2] и элемента с вот таким: [1, 2, 3] - ф-ция вернёт null.
Но идея с набиванием предков в массив - отличная. Благодарю. |
Пример пжалста, ибо не могу представить такой ситуации. У всех в DOM'е один главный предок.)
Пример:
<html> <body> <style>div{padding:5px;margin:5px;border:2px dotted #000} #first{border-color:#f00} #second{border-color:#0f0} #parent{border-color:#00f} </style> <div> <div> <div></div> <div id="second"></div> </div> <div id="first"></div> </div> <script> function unitedParent(first,second){ var parents=function(e){var a=[];while(e=e.parentNode)a.push(e);return a}; var f=parents(first), s=parents(second), fl=f.length, sl=s.length; while(f[--fl]&&f[fl]===s[--sl]); return f[fl+1]||null } unitedParent(document.getElementById('first'),document.getElementById('second')).id="parent"; </script> </body> </html> |
Да, я ступил. Mea Culpa) Всё, прекрасно) Спасибо))
|
тут не надо никаких циклов. достаточно навести текстовый диапазон началом на один элемент, концом на другой, а потом попросить у него родительский контейнер.
|
гуглить по TextRange commonAncestorContainer
|
*бьется головой о стену*
|
*приклеил к стене подушечку*
|
tenshi, хоть это и некропост будет, но всё же... Range-объектов в ie нет (причём версии до восьмой, что ли). А я немного гоняюсь за кроссбраузерностью.
|
|
Range по стандарту w3c и по "стандарту" microsoft - немного разные вещи. Почитайте.
Да простой пример, собственно: alert(document.createRange); У меня восьмой осёл, и выдаёт undefined. |
тебе шашечки или ехать?
|
Ну, и плюс к тому же, Range.commonAncestorContainer - это не совсем общий родитель. Пример:
<div id="div">text</div> <script> div= document.getElementById('div'); rng= document.createRange(); // not ie rng.setStart(div, 0); rng.setEnd(div, 1); alert(rng.commonAncestorContainer.id); // "div" </script> В данном случае, он равен элементу, в котором начинается и заканчивается Range-объект. А общим родителем этих двух элементов в данном случае будет body. |
Извините) Любимая тема, понесло))
|
на элементы надо наводиться снаружи, а не внутри и всё будет хорошо
|
Часовой пояс GMT +3, время: 07:23. |