..."Ahora entiendo lo que querés hacer. :) Es medio complicadito!"...
Lo que me sorprende es que no debería serlo. Me resisto a creer que entre todas
las APIs no exista algo que me permita obtener las coordenadas del area cliente
de un elemento.
Lo de clientLeft y clientTop fue lo primero que intenté, y muy rápidamente me
desilusioné cuando descubrí que no fueron implementadas en Firefox, aún cuando
este si implementa clientWidth y clientHeight. De hecho, buceando un poco en el
site de Mozilla, me cruzé con comentarios de que 'habría' intenciones de
implementarlas.
Con respecto a getComputedStyle(), esto es lo que estoy usando para copiar el
estilo del elemento destino. Pero tu sugerencia me sirvió porque cuando me
encontraba redactando una respuesta explicando que el problema de
getComputedStyle() se presentaba en el caso de que el borde haya sido definido
en una unidad diferente a pixels, por ejemplo como 'thick', quize confirmar
esto en el ejemplo, y me sorprendí cuando getComputedStyle() me devolvió el
ancho del borde correctamente convertido a pixels. Estaba convencido de que
siempre devolvía el valor en las unidades en las que fue especificado, ya que
en algún momento de las doce millones de pruebas que hice estaba seguro de
haber visto esto. Pero ahora creo que me debo de haber confundido con
currentStyle, que es el método equivalente en IE, y que si devuelve valores
expresados en las unidades originales. Creo que esto fue lo que me llevó a
descartar la opción de obtener las coordenadas a partir del border externo y
sumando el ancho del borde en pixels. Pero en apariencia una combinación de
clientLeft / clientTop para IE, y getComputedStyle() para Firefox podría
funcionar. Parece que tenía todas las piezas del rompecabezas, pero no supe
armarlo. Gracias Luis.
Claro que todavía no probé nada en Opera y Safari... Además, cuanto más me me
meto en el tema, más complicado se vuelve. En las pruebas triviales todo
funciona de maravillas. Pero el mismo código en páginas complejas, donde hay
una variedad de estilos, elementos anidados, con posiciones absolutas y
relativas, las cosas no son tan simples. En fin...
Me quedé un poco intrigado por la siguiente frase ..."También elaborándolo un
poco más, podrías usar getComputedStyle en todos los casos (incluído IE)."...
Te importaría explayarte un poco más con respecto a este punto. IE6 no soporta
getComputedStyle, no estoy seguro sobre IE7 pero una prueba rápida parece
sugerir que tampoco.
A propósito, tenés idea si existe alguna forma de obtener el estilo de un
pseudo-elemento, por ejemplo 'first-letter', en el caso de IE. El problema se
presenta cuando intento copiar el estilo del elemento destino cuando este
contiene pseudo-elementos. En el caso de getComputedStyle('elemento',
'pseudo-elemento'), el segundo parámetro permite acceder a ellos, pero en el
caso de IE no parece existir forma de hacer referencia a estos a través de
currentStyle.
Muchas gracias nuevamente.
Saludos,
Fernando Tubio
----- Original Message -----
From: Luis Farzati
To: [email protected]
Sent: Saturday, December 16, 2006 10:25 AM
Subject: [puntonet] OFF-TOPIC - Recuperar la posicion de un elemento HTML
Hola Fernando,
Ahora entiendo lo que querés hacer. :) Es medio complicadito!
En IE tenés la propiedad clientLeft y clientTop, que te devuelve precisamente
el ancho del borde izquierdo y superior respectivamente, aunque esto no es W3C
compliant y en otros browsers como el Firefox no está disponible.
Ahora, intrigado me puse a investigar alguna solución y encontré una opción
que habría que ver si te sirve:
Podrías recuperar el ancho del borde de otra forma que es utilizando el
método DOM getComputedStyle. Esto, como el nombre lo dice, te devuelve los
valores computados del estilo de un elemento (en vez de traerte los valores
literales que obtenés con la propiedad style).
Con lo cual podrías ir por la primer opción, si evaluás que el browser tiene
el soporte ala IE, y en caso contrario utilizar getComputedStyle.
Un ejemplo rápido:
if(dst.currentStyle && dst.currentStyle.hasLayout ) {
src.style.top = dst.offsetTop + dst.offsetParent.offsetTop +
dst.clientTop + 'px';
src.style.left = dst.offsetLeft + dst.offsetParent.offsetLeft +
dst.clientLeft + 'px';
}
else {
var realTop = parseInt( document.defaultView.getComputedStyle(dst,
"").getPropertyValue('border-top-width').replace('px', ''));
var realLeft = parseInt(document.defaultView.getComputedStyle(dst,
"").getPropertyValue('border-left-width').replace('px', ''));
src.style.top = dst.offsetTop+dst.offsetParent.offsetTop+realTop +
'px';
src.style.left = dst.offsetLeft+dst.offsetParent.offsetLeft+realLeft
+ 'px';
}
También elaborándolo un poco más, podrías usar getComputedStyle en todos los
casos (incluído IE).
Más info en:
http://www.w3.org/2003/01/dom2-javadoc/org/w3c/dom/css/ViewCSS.html
http://www.faqts.com/knowledge_base/view.phtml/aid/7157
http://annevankesteren.nl/2006/05/offset#comment-5377
http://www.setmajer.com/demo/find_position_test/js/main.js
De todas formas, por lo que veo querés hacer algo bien genérico, no? Si el
div que se posiciona encima tiene que adaptarse al tamaño y demás estilos
visuales (como ser el borde) del elemento a pisar, no es mala idea lo que estás
haciendo de 'camuflarlo' con el estilo destino.
Saludos,
Luis
On 12/15/06, Fernando Tubio <[EMAIL PROTECTED]> wrote:
(Primero disculpas al resto de la lista porque cuando envié el mensaje
originalmente omití indicar que se trataba de un off-topic. )
Hola Luis,
Gracias por contestar. Ya lo creo que es todo un tema, particularmente
cuando se trata de hacer algo que funcione de igual forma en los browser más
populares. En este caso especificar un float no me permitiría superponer un
objeto sobre otro, y z-index me ayudaría solo en el caso de que los elementos
ya se encuentren correctamente posicionados y superpuestos.
Intentaré dar un ejemplo simplificado de lo que intento lograr.
<html>
<head>
<style>
#src {
background-color:yellow;
}
#elt1 {
background-color:#ffeeff;
padding:40px;
}
#elt2 {
border:solid 30px;
padding:40px;
}
</style>
<script>
function moverAqui(dst) {
var src = document.getElementById('src');
// parche para IE para forzar hasLayout
dst.style.zoom = '1';
// esto es simplificado, ya que si el elemento se encontrara
anidado dentro de
// otros elementos posicionados habría que recorrer la
jerarquia sumando los offsets
src.style.position = 'absolute';
src.style.top = dst.offsetTop + dst.offsetParent.offsetTop +
'px';
src.style.left = dst.offsetLeft + dst.offsetParent.offsetLeft +
'px';
src.style.height = dst.clientHeight + 'px';
src.style.width = dst.clientWidth + 'px';
}
</script>
</head>
<body>
<h1 id="elt1" onclick="moverAqui(this);">Esto es un elemento
cualquiera. Haga clic aqui!</h1>
<h1 id="elt2" onclick="moverAqui(this);">Esto es otro elemento
cualquiera. Haga clic aqui!</h1>
<div id="src">ESTE ES EL ELEMENTO A POSICIONAR</div>
</body>
</html>
Haciendo clic en cualquiera de los dos elementos, 'elt1' y 'elt2',
posiciona el <div> sobre el elemento en cuestión. Como el elemento 'elt1'
carece de borde, el div cubre el area de contenido correctamente. Sin embargo,
el estilo del elemento 'elt2' indica un borde, y el div aparece en la posición
incorrecta. Mi problema es encontrar la forma de encontrar las coordenadas del
'area interior' del elemento, por adentro del borde. No encuentro un mecanismo
que me devuelva el ancho del borde en pixels y que funcione en forma
'cross-browser'.
Por ahora encontré una alternativa que es copiar el estilo del elemento
sobre el cual se va a posicionar, de tal forma que el div tenga el mismo borde.
De esta forma el efecto visual es correcto. Pero estoy teniendo otros problemas
con esta solución así que todavía no estoy seguro si es viable.
Saludos,
Fernando Tubio
----- Original Message -----
From: Luis Farzati
To: [email protected]
Sent: Friday, December 15, 2006 6:46 PM
Subject: [puntonet] Recuperar la posicion de un elemento HTML
Hola Fernando,
La obtención de las posiciones es todo un tema, tienen ciertas reglas que
tienen que ver con la forma de renderear el elemento que tiene el browser.
Si te posteás un pequeño ejemplo del problema concreto, como para que sea
más visible, vemos cómo lo podemos encarar. Pero mi sugerencia es que, si lo
que querés es superponer un objeto, pruebes combinando el float y z-index (o
z-order?) del CSS. En mi experiencia siempre es conveniente esquivar
posicionado absoluto, en lo posible.
Saludos,
Luis
On 12/12/06, Fernando Tubio <[EMAIL PROTECTED]> wrote:
Necesito posicionar un <div> en forma absoluta de tal forma que se
superponga al area de contenido de un elemento en una página HTML, pero
estoy encontrando dificultades en hallar un mecanismo que me devuelva
las
dimensiones necesarias. Puedo calcular las coordenadas del ángulo
superior
izquierdo del elemento sumando los valores de offsetLeft y offsetTop de
la
jerarquía de elementos contenedores, pero el resultado corresponde a
las
coordenadas del borde externo del elemento. Necesito las coordenadas del
área de contenido, excluyendo bordes y padding.
Internet Explorer posee las propiedades clientLeft y clientTop que
podrían
ser útiles, pero por desgracia no son estándar y no han sido
implementadas
en Mozilla por ejemplo, a pesar de que este último si dispone de
clientWidth
y clientHeight. Para determinar las dimensiones del borde + padding
supongo
que podría usar algo similar a (offsetWidth - clientWidth) / 2, pero
esto
asume que el borde y el padding son iguales en cada lado del elemento, y
esto no siempre es el caso. Los valores disponibles a partir de la
propiedad
style no pueden ser usados para realizar el cálculo ya que sus unidades
no
son siempre uniformes. Se podría tener por ejemplo un valor para el
ancho
del borde expresado como 'thick' o '1em'. Necesito un valor expresado en
pixels.
¿Alguna sugerencia?
Saludos,
Fernando Tubio