Newsgroup: it.comp.lang.javascript
Titolo: coordinate top e left rispetto alla root

ciao a tutti,
qualcuno conosce un modo assoluto per conoscere le coordinate top e left di
un qualsiasi elemeto della pagina relativamente a document.body ?
 var el=document.getElementById('myel');
 var abstop=CalcolaTop(el);       // # di pixel rispetto a
document.documentElement.style.top
 var abselft=CalcolaLeft(el);       // # di pixel rispetto a
document.documentElement.style.left
finora ho sempre risolto problemi simili sommando le coordinate di elementi
nestati, ricorrendo alle proprieta' top e left di ogni elemento, ed
eventualmente a offsetTop e offesetLeft o getComputedValue()
il problema e' che dell'elemento di cui desidero calcolare le due proprieta'
stavolta non conosco a priori la posizione all'interno del Dom della pagina,
ne' le proprieta' CSS position di eventuali elementi che lo contengano.
qualcuno hai mai affrontato il problema?
al momento mi accontento anche di una soluzione per il solo IE5.5
--
    Federico Sasso &8v>
 
http://www.crt.unige.it/jsSQL
    The jsSQL Project - JavaScript Database and SQL Engine

 document.documentElement.style.left
scusate, volevo dire "# di pixel rispetto a document.body.style.top" e  "#
di pixel rispetto a document.body.style.left"


 un qualsiasi elemeto della pagina relativamente a document.body ?
alla fine l'ho fatto e non era difficile.
se pero' c'e' un modo piu' rapido ditemelo ;-)
function ComputeTop(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  res+=el.offsetTop;
  el=el.parentElement;
 }
 return res;
}
ciao


qualcuno su comp.lang.javascript mi ha criticato per avere scritto codice
troppo "MS oriented". :-(
chiedo venia, e' vero, ma scrivere un componente .htc la portabilita' non
era richiesta e in effetti mi sono fatto prendere la mano approffittandone
per usare proprieta' non standard (es. parentElement, ma giuro, non lo
faccio mai, volevo solo provarle! :-)
cmq, per gli amanti del X, ecco una versione piu' portabile:
function ComputeTop_X(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  res+=parseInt(el.offsetTop);
  el=el.parentNode;
 }
 return res;
}
che funziona con IE5+, NS6+, Moz/Gecko, ma usa offsetTop che non e' un
attributo standard
Per la gioia dei puristi, segue una verione standard W3C:
function ComputeTop_W3C(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  res+=parseInt(document.defaultView.getComputedStyle(el,
null).getPropertyValue("top"));
  el=el.parentNode;
 }
 return res;
}
che fa uso del metodo standard DOM2 getComputedStyle() che, a quanto ne so,
al momento e' supportato solo da NS6+/Moz/Gecko
naturalmente aggiungendo un po' di client sniffing si puo' facilmente
rendere il codice compatibile anche con IE4.x e NS4.x, ma lascio questa
gioia ad altri (capito Riccardo? :-)
...ognuno ha le proprie idiosincrasie!


ciao a tutti, eccomi di nuovo nei guai!
pensavo di avere risolto, ma purtroppo ho visto che la funzione con copre
tutti i casi :-((((
se commento la definizione CSS per #nesting, #nested viene correttamente
posizionato alla coordinato top:10px ma la funzione non ne tiene conto e
retituisce 110px
non riesco a discriminare i due casi, avete qualche idea?
vi saro' eternamente grato per ogni aiuto ;-)
   Federico Sasso
<html>
<head>
<title>Nested Divs</title>
<style type="text/css">
#nesting
{
 position:absolute; top:100px; left:200px;
 width:200px; height:200px;
 border:0px; padding:0px;
 background-color:red;
}
#nested
{
 position:absolute; top:10px; left:10px;
 width:100px; height:100px;
 border:0px; padding:0px;
 background-color:blue;
}
/* serve solo per confrontare a video con il risultato */
#fixediv
{
 position:absolute; top:119px; left:10px;
 width:10px; height:100px;
 border:0px; padding:0px;
 background-color:green;
}
</style>
<script type="text/javascript">
/*
questo codice computa la coordinata y in modo assoluto (relativa a
document.body)
facendola relativa a document.contentElement (il nodo corrispondente al tag
<HTML>) dovrebbe tagliare anche border e margin del body
*/
// IE5+/NS6+/Moz/Gecko (usa l'attributo non standard offsetTop)
function ComputeTop_X(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  alert('top: ' + el.top + '\r\noffsetTop: ' + el.offsetTop + '\r\npos: ' +
el.style.position + '\r\nid: ' + 
el.id
);
  res+=parseInt(el.offsetTop);
  el=el.parentNode;
 }
 return res;
}
</script>
</head>
<body id="mybody">
<h2>Nested Divs</h2>
<a href="javascript: alert('ComputeTop (X): ' +
ComputeTop_X('nested'));">Compute Top (X)</a><br />
<div id="nesting">
  aaa<br>
  <div id="nested">nested content</div>
</div>
<div id="fixediv"></div>
</body>
</html>

 (coordinate relative a document.body)
ho trovato una soluzione, che purtroppo funzione solo per IE
// solo IE4+ (usa l'attributo non standard offsetParent)
function ComputeTop_IE(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  res+=parseInt(el.offsetTop);
  el=el.offsetParent; //sostituisce parentNode
 }
 return res;
}
il suggerimento di usare l'attributo offsetParent (manco sapevo esistesse)
mi e' stato dato da Michael Wender su
microsoft.public.windows.inetexplorer.ie55.programming.dhtml.scripting
la proprieta' offsetParent e' il puntatore all'elemento che determina gli
offsets per l'elemento che la possiede.
per uletriori informazioni vedere:
http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/offsetp
arent.asp
purtroppo non ho trovato un modo standard DOM2 per ottenere lo stesso
risultato
[
per es. el.offsetTop si puo' ricavare con
document.defaultView.getComputedStyle(el,null).getPropertyValue("top")
]
qualora dovessi riuscirci mi premuro' di informare il NG (sperando che
interessi, e sempre che qualcuno legga questo thread ;-)



offsetParent esiste anche in NS6 solo che si comporta in modo bizzarro:
restituisce null se l'elemento e' assoluto o se uno dei genitori è
assoluto altrimenti restituisce l'oggetto body; non riesco a capire come
sia possibile utilizzarlo.
Comunque, mi sembra che offsetTop, con NS6, restituisca sempre la
distanza dal bordo,non la distanza dall'elemento genitore, qualsiasi sia
la profondita' dell'elemento.
Con IE si puo' anche utilizzare currentStyle che riporta tutti gli
attributi di stile in qualsiasi modo siano stati valorizzati e quindi
discriminare tra un elemento posizionato e non.
 if (el.currentStyle.position!='static') res+=parseInt(el.offsetTop);
Saluti, Paolo

mi sono accorto che la soluzione proposta non era ancora ottimale, perche'
sbagliava di un paio di pixel, che erano la dimensione del bordo del body;
me ne sono accorto comparando il valore ottenuto dalla coordinata riportata
da event.clientY.
La cosa strana e' che ad impostare un qualunque valore a tale bordo,
l'effetto risultante e' metterlo a zero (????).
Leggerne borderSize non e' possibile, a meno che questo non sia stato
impostato con uno stile in linea o via script; cio' e' corretto perche'
allineato con la specifica CSS; la soluzione e' leggere la dimensione del
bordo usando l'attributo (proprietario) clientTop :
// solo IE4+ (usa l'attributo non standard offsetParent)
function ComputeTop_IE(elname)
{
 var myel=document.getElementById(elname);
 var root=document.body;
 var res=0;
 var el=myel;
 while (el!=root)
 {
  res+=parseInt(el.offsetTop);
  el=el.offsetParent; //sostituisce parentNode
 }
 return res + root.clientTop;
}
ciao a tutti


  if (el.currentStyle.position!='static') res+=parseInt(el.offsetTop);
non lo conoscevo. grazie, me lo guardero' un po'.
Federico



[]
Si puo' leggere con  body.currentStyle.borderTopWidth ma,
sfortunatamente, il risultato e' *medium* valore di default.
L'unica soluzione mi sembra quella che hai suggerito per allineare i
valori top dell'elemento con i valori di event.y.
Saluti, Paolo

 non ho capito bene cio' che intendi
Il "bordo" e' certamente poco chiaro :-(
Io ho installato NS6.1
Mozilla/5.0 (Windows; U; Win98; en-US; m18) Gecko/20010131
Netscape6/6.01
e i risultati con il tuo codice sono:
1° alert    IE 10px     NS6    110px
2° alert    IE 100px   NS6    100px
3° alert    IE 110px   NS6    210px
poiche' il risultato atteso e' 110px deduco che offsetTop, con NS6.1,
restituisca la distanza dal body non, come dovrebbe, dall'elemento
contenitore.
Stesso risultato anche con ulteriori innesti.
Sappimi dire se hai risultati diversi e con che versione di NS6.
Saluti, Paolo

 > Leggerne borderSize
errata corrige, volevo dire "borderWidth"
ciao.
Federico

 contenitore.
evidentemente nel chiamare la funzione *_X sono stato un po' frettoloso!
confermo i tuoi risultati con NS6.01
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; m18) Gecko/20010131
Netscape6/6.01
cosi' come con Mozilla  0.8
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; 0.8) Gecko/20010221
e con Mozilla 0.9
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:0.9) Gecko/20010505
ciao. Federico