2015-02-03 2 views
0

Я пытаюсь отобразить узел рядом с другим (поверх содержимого) с помощью Javascript. Я не могу изменить структуру документа для этого узла, и мне нужно вставить новый узел под одним и тем же родителем. Я хотел бы использовать позицию: абсолютная позиционировать новый узел, но мне кажется, трудно найти позицию опорного узла. Использование getBoundingClientRect() на ссылочном узле не работает, потому что узел может находиться внутри предка с позицией: relative или position: absolute, а getBoundingClientRect() возвращает позицию относительно документа, которая не может использоваться в качестве координат с позицией CSS : абсолютный.Получить абсолютное положение узла CSS в Javascript

Нужно ли мне прокручивать предков, чтобы найти первую позицию: абсолютную или позицию: относительную, чтобы найти абсолютную позицию CSS, или есть более простой способ получить эту информацию?

Примечание: Я ищу ответ в чистом Javascript.

Обновление: Другими словами, я ищу позицию верхнего/левого пикселя, элемент должен отображаться в том же месте, когда его положение CSS изменяется на «абсолютное». offsetTop/offsetLeft не является ответом, потому что элемент может находиться внутри таблицы, и в этом случае offsetParent является ячейкой таблицы.

+0

Возможный дубликат [Javascript: получить позицию/смещение элемента относительно родительского контейнера?] (Http://stackoverflow.com/questions/11634770/javascript-get-position-offset-of-element-relative-to -a-parent-container) - принятые ответы детали чистых свойств javascript для этого –

+0

Я не вижу, как связаны эти вопросы: я не ищу позицию относительно родителя. – Damien

+0

Я добавил пример, чтобы продемонстрировать, как использовать 'offsetLeft' и' offsetTop'.Возможно, название этого вопроса вводит в заблуждение, но решение одинаков - вам нужна позиция относительно «offsetParent», которая на самом деле не может быть прямым родителем - она ​​относится к ближайшему предку с абсолютным или относительным позиционированием. –

ответ

1

Вот рекурсивное решение:

function getCSSAbsolutePosition(el) { 
    var pos= ('absolute relative').indexOf(getComputedStyle(el).position) == -1, 
     rect1= {top: el.offsetTop * pos, left: el.offsetLeft * pos}, 
     rect2= el.offsetParent ? getCSSAbsolutePosition(el.offsetParent) : {top:0,left:0}; 

    return {top: rect1.top + rect2.top, 
      left: rect1.left + rect2.left, 
      width: el.offsetWidth, 
      height: el.offsetHeight 
     }; 
} 

В this Fiddle, красный приговор должен быть выделен. Нажмите кнопку, и будет вызываться getCSSAbsolutePosition, чтобы получить его координаты, ширину и высоту. Под ним находится новый div (с отрицательным z-Index), который имеет фон и границу.

Обратите внимание, что «цель» div находится в таблице с абсолютным расположением в относительном позиционированном div с различными дополнениями и полями.

+0

В вашей скрипке вы добавляете новый элемент в document.body. Одно из моих требований состоит в том, что новый элемент добавляется внутри родительского объекта цели («Мне нужно вставить новый узел под одним и тем же родителем», в вашей скрипке это будет td). – Damien

+0

Думаю, я понимаю. См. Http://jsfiddle.net/mqb9ua12/ Это то, что вы ищете? Если это так, я обновлю свой ответ. –

+0

Это больше похоже на то, но ваша новая скрипка не работает, если у вас есть div между td и target: http://jsfiddle.net/0ohj6muy/ – Damien

0

Это мое текущее решение. Он работает, но я все еще ищу более простой.

var getCSSAbsolutePosition = function getCSSAbsolutePosition(el) { 
    var x = 0; 
    var y = 0; 
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) { 
     x += el.offsetLeft - el.scrollLeft; 
     y += el.offsetTop - el.scrollTop; 
     el = el.offsetParent; 
     if (el) { 
      var style = window.getComputedStyle(el); 
      if (style.position == 'absolute' || style.position == 'relative') 
       break; 
     } 
    } 
    return {top: y, left: x}; 
} 
0

Вы можете использовать offsetLeft и offsetTop свойства, чтобы получить позицию элемента относительно его offsetParent.

Вот краткий пример, принимая во внимание тот факт, что элемента offsetParent может быть ячейка таблицы без позиционирования как вы так справедливо указывают:

function positionOver(targetNode) { 
    var el = document.createElement("div"), 
     left = targetNode.offsetLeft, 
     top = targetNode.offsetTop, 
     testParent = targetNode.offsetParent; 

    while (testParent) { 
     if (
      testParent.tagName === "TD" || 
      testParent.tagName === "TH" || 
      testParent.tagName === "TABLE" 
     ) { 
      left += testParent.offsetLeft; 
      top += testParent.offsetTop; 
     } 
     testParent = testParent.offsetParent; 
    } 
    el.style.left = left + "px"; 
    el.style.top = top + "px"; 
    el.classList.add("created"); 
    targetNode.parentNode.appendChild(el); 
} 

// Create and position a new element over #target 
positionOver(document.querySelector("#target")); 

CSS

.created { 
    position: absolute; 
    background: red; 
    z-index: 10; 
    width: 10px; 
    height: 10px; 
} 

Fiddle here ,

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

+0

offsetLeft и offsetTop не являются ответом, потому что родитель может не быть абсолютно позиционированным. Другой предк может быть (или нет: я не предполагаю ничего о предках). Кроме того, целевой узел может быть не совсем позиционирован. – Damien

+0

Вы имеете в виду вот это? http://jsfiddle.net/ju3uyva3/3/ - использует ту же самую технику, без какого-либо позиционирования на целевом или родительском узлах. –

+0

... и [это] (http://jsfiddle.net/ju3uyva3/4/) с предком, у которого есть некоторое позиционирование. –

Смежные вопросы