Св-ва top и left

 
0
 
JavaScript
ava
kaa | 09.08.2007, 13:55
Возникла некоторая проблема... Для определения абсолютной позиции элемента накропал следующую функцию:


function CoordinateAbs(element, top, left)
{
top += element.style.top;
top += element.style.marginTop;
left += element.style.left;
left += element.style.marginTop;
if(element.parentNode&&(element.parentNode.nodeName!='BODY'))
{
CoordinateAbs(element.parentNode, top, left);
return;
}
else
{
return new Array(top, left);
}
}


Но ничего не получается.
Выражение element.style.top - вообще ничего не возвращает.
Выражение window.getComputedStyle(element,"").top возвращает значение auto.

Никто не подскажет как извернуться? И почему неработает element.style.top?


Comments (11)
ava
Astraller | 09.08.2007, 13:24 #

element.offsetTop

smile
ava
dXdYdZ | 09.08.2007, 13:29 #
Лучше вот так (Из моей библиотеки):

getLeft=function(node)
{
if(node==document.body) return 0;
if(!node.offsetParent) return node.offsetLeft;
return node.offsetLeft+JSON.getLeft(node.offsetParent);
}

getTop=function(node)
{
var result=0;
if(node==document.body) return 0;
if(!node.offsetParent) return node.offsetTop;
return node.offsetTop+JSON.getTop(node.offsetParent);
}

Просто offsetLeft и offsetTop не всегда дают правильный результат, так как это не абсолютные координаты, а координаты относительно offsetParent.
ava
kaa | 09.08.2007, 14:14 #
dXdYdZ,

А что такое JSON?
и еще: на offsetXXX народ жалуется что иногда опускает целые блоки при проходе по дереву.
ava
dXdYdZ | 10.08.2007, 00:34 #
JSON-это я так назвал свою библиотеку. Но оказалось, что такая уже есть. Поэтому название буду менять. Взял коды со своей библиотеки, а привязку к ней забыл убрать. Правильно будет так:

getLeft=function(node)
{
if(node==document.body) return 0;
if(!node.offsetParent) return node.offsetLeft;
return node.offsetLeft+getLeft(node.offsetParent);
}
getTop=function(node)
{
var result=0;
if(node==document.body) return 0;
if(!node.offsetParent) return node.offsetTop;
return node.offsetTop+getTop(node.offsetParent);
}

Если не нравится offsetLeft и offsetTop, то можно вот так:

getScrollPosition=function() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return {"top":scrOfY, "left":scrOfX};
}

abs=function(node)
{
if(node.getBoundingClientRect)
with(node.getBoundingClientRect()){
return {x: left-2+getScrollPosition().left, y: top-2+getScrollPosition().top};
}
if(document['getBoxObjectFor'])
return document.getBoxObjectFor(node);

return {x: getLeft(node), y: getTop(node)}; //Если не получилось иначе
}
ava
kaa | 10.08.2007, 23:05 #
dXdYdZ,
Спасибо, разобрался!


Всем спасибо за ответы smile
ava
kaa | 29.08.2007, 12:31 #
Рано закрыл вопрос...
dXdYdZ, пользуюсь той функцией что вы привели.

В общем проблема такая: идёт ошибка у св-ва top на 130 пикселей приблизительно в плюс.
Притом в зависимости от верстки:
тоесть если выдаю для горизонтальной области - то всё нормально,



<table class="my_drop_menu_container">
<tbody>
<tr>
<td class="my_drop_menu_column_container"><div class="my_drop_menu_root_item" foo="my-drop-menu-item" foo-id="54" foo-parent-id="53" foo-parent="1" foo-level="0"><a href="/drupal/?q=node/2" title="Item menu">Item menu</a></div>
</td>
<td class="my_drop_menu_column_container"><div class="my_drop_menu_root_item" foo="my-drop-menu-item" foo-id="59" foo-parent-id="53" foo-parent="1" foo-level="0"><a href="/drupal/?q=node/12" title="my menu item 2">Item2</a></div>
</td>
</tr>
</tbody>
</table>



если для вертикальной - идет ошибка


<div foo="my-drop-menu" class="my_drop_menu">
<table class="my_drop_menu_container">
<tbody>
<tr>
<td class="my_drop_menu_column_container">
<div foo-level="0" foo-parent="1" foo-parent-id="53" foo-id="54" foo="my-drop-menu-item" class="my_drop_menu_root_item"><a title="Item menu" href="/drupal/?q=node/2">Item menu</a></div>
</td>
</tr>
<tr>
<td class="my_drop_menu_column_container">
<div foo-level="0" foo-parent="1" foo-parent-id="53" foo-id="59" foo="my-drop-menu-item" class="my_drop_menu_root_item"><a title="my menu item 2" href="/drupal/?q=node/12">Item2</a></div>
</td>
</tr>
</tbody>
</table>
</div>



Соответсвенно и контент вставляется в разные места страницы. Первый - в верхнюю строку(шапку), а второй в левый столбец.
Притом ошибка +130 появляется только когда вставляю в левую или правую колонку страницы, но отсутствует если в шапку или в "подвал".

ЗЫ: если кому-то о чем-то скажет - пишу модуль для движка DRUPAL. В движки постить не стал ибо, как считаю, проблема всёравно сводится к скрипту.
ava
kaa | 29.08.2007, 14:40 #
Да, забыл код определяющий координаты


function CoordinateAbs(element, TopLeftArr)
{
TopLeftArr[0] = TopLeftArr[0] + Number(element.offsetTop) + Number(element.style.marginTop);
TopLeftArr[1] = TopLeftArr[1] + Number(element.offsetLeft) + Number(element.style.marginLeft);
if(element.offsetParent.nodeName!='BODY')
{
CoordinateAbs(element.offsetParent, TopLeftArr);
}
else
{
return;
}
}
ava
kaa | 29.08.2007, 16:24 #
Как обнаружилось, правильность определения пути прохода по родителям зависит от св-ва стиля position и стилей родительских блоков.

Было:

.my_drop_menu_root_item{position:relative; cursor:pointer;}


Стало


.my_drop_menu_root_item{cursor:pointer;}


В итоге ошибка уменьшилась на 33px :(

Прилагаю все стили:

*.my_drop_menu {width:30%; text-align: center; vertical-align: middle; margin:auto; z-index:1;} /**/
*.my_drop_menu_container{width:100%; text-align: center; vertical-align:middle; margin:auto;}
*.my_drop_menu_items_div{z-index:1; cursor:pointer; display:none; position:absolute; text-align:center; background-color: #ff0000; }
*.my_drop_menu_column_container{ padding-left:5%; padding-right:5%; padding-top:0; padding-bottom:0; }
.my_drop_menu_root_item{cursor:pointer;}
.my_drop_menu_item{position:relative; background-color:#00ff00; cursor:pointer;}


Кто нить знает по каким правилам, тоесть как от стилей зависет, способ определения offsetTop и offsetLeft?

added later:
В общем если у всех родителей св-во position равно static то величина top определяется прально.
Если хотябы у одного есть relative то св-во top идёт на +.

Никто не знает как обойти это ограничение?
ava
kaa | 29.08.2007, 17:19 #
В общем родил.


function CoordinateAbs(element, TopLeftArr)
{
var styleChildNode = document.defaultView.getComputedStyle(element, null);
if(styleChildNode.getPropertyValue("position")!="relative")
{
alert(element.offsetTop+" "+element.offsetLeft+" "+styleChildNode.getPropertyValue("position"));
TopLeftArr[0] = TopLeftArr[0] + Number(element.offsetTop) + Number(element.style.marginTop);
TopLeftArr[1] = TopLeftArr[1] + Number(element.offsetLeft) + Number(element.style.marginLeft);
}

if(element.offsetParent.nodeName!='BODY')
{
//alert("top:"+element.style.height+"; left:"+element.style.width+"; ElementName="+element.parentNode.nodeName);
CoordinateAbs(element.offsetParent, TopLeftArr);
}
else
{
alert(TopLeftArr[0]+" "+TopLeftArr[1]);
return;
}
}


Надо пропускать родителей со св-вом position:relative, тогда всё прально вычисляется.

Скажу больше спасибо тому человеку который мне ответит на вопрос почиму рэлативные блоки всё так поганят.
ava
Ghirik | 29.08.2007, 23:00 #
Наверное это нельзя считать косяком функции. Вы сами должны учитывать "эффекты" от применения стилей.
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  Burrr   kaa   Ghirik   dXdYdZ   Astraller
advanced
Submit