2010-10-17 19 views
9

estoy tratando de poner en práctica un simple efecto de pliegue/unforld para divs elásticas, es decir, cuando las dimensiones reales de un elemento que no se establecen a través de CSS y por lo tanto no son trivialmente determinable. Por lo tanto, necesito equivalentes de ancho() y alto() de jQuery para elementos arbitrarios; los métodos deben devolver algo que sea asignable a * .style.width/height para lograr el efecto de plegado/desplegado. Los métodos también pueden ser setters, aunque no necesariamente ya que es trivial de todos modos (¿o no?)anchura() y la altura() para navegadores modernos sin jQuery

Compatibilidad: IE8 + y la pandilla adecuada de 3: Firefox, Chrome, Safari. ASI QUE. no tiene una respuesta para esto que no sea "use jQuery" que no quiero hacer en este momento. La cuestión es que no necesito soportar navegadores tan arcaicos como IE6/7 y Netscape. Quiero que mi código sea solo simple, primer JavaScript para navegadores modernos. Dejar caer IE8 para IE9 también es una opción.

Creo que la respuesta puede ser útil para muchos desarrolladores web. ¡Gracias!

Editar: Entiendo, por supuesto, analizar jQuery (y eliminar caprichos arcaicos) es una buena opción, pero creo que alguien ya lo ha hecho y podría compartir con nosotros.

+0

Siempre se puede mirar la fuente de jQuery (u otro kit de herramientas/biblioteca de su elección) para determinar el enfoque, y luego descartar (o reglamentar) las diferentes peculiaridades necesarias en diferentes entornos. –

+0

pst, eso siempre es una opción, por supuesto, pero pensé que alguien con un conocimiento razonable de estos 4 navegadores, o alguien que ya lo haya hecho antes, le daría una respuesta de inmediato. Y comprender jQuery puede o no ser tan fácil. – mojuba

+0

Creo que resolver el problema hight()/width() no va a llevar tanto tiempo como hacer que la animación se vea bien, lo que jquery hace por usted. – tster

Respuesta

5

Aquí es una respuesta a mi propia pregunta que se me ocurrió hoy después de jugar con IE8, FF, Chrome y Safari.

Digamos que queremos plegar y desplegar un elemento div verticalmente (por lo que vamos a estar hablando sólo de la altura para simplificar) con un mínimo posible de JavaScript y jQuery no. Podría ser un cuadro de mensaje de error en línea que desea mostrar y ocultar muy bien en la página. El cuadro de mensaje en sí es elástico y no conoce sus dimensiones reales. Hay dos problemas generales que deben resolverse aquí:

Problema n. ° 1: las propiedades offsetHeight, clientHeight y scrollHeight son notoriamente inconsistentes en todos los navegadores. No puede confiar en ellos especialmente cuando margin/padding/border están configurados en algo distinto de 0 y cuando la altura de CSS es distinta a la predeterminada (es decir, cuando se dobla o se despliega realmente el elemento). Hay getComputedStyle(), pero está disponible solo en navegadores sanos y no en IE. OTOH, la propiedad Style actual de IE no devuelve los valores calculados como cabría esperar (por ejemplo, puede ver "auto" como valor de altura). Resulta que, sin margen/relleno/borde compensado, la altura es confiable y compatible en todos los navegadores modernos.

Problema # 2: la única manera (que yo sepa) para animar el elemento div es cambiar el estilo.altura, que, sin embargo, no incluye relleno y borde, y por lo tanto no puede animar la caja a 0 o comenzar su animación desde 0 para elementos con relleno y borde distintos de cero. (Además de eso, IE no acepta 0px como style.height, por lo que el tamaño mínimo sería 1px de todos modos).

La solución a ambos problemas es envolver su caja con otro div con estilo predeterminado, es decir, relleno/margen/borde todo configurado en 0, que es el estilo predeterminado para un nuevo div. La caja que desea doblar y desplegar debe estar dentro y no debe tener una configuración de margen, solo relleno y borde si lo desea. De esta forma, podrá (1) determinar de manera confiable la altura de su caja interna elástica a través de offsetHeight, y (2) animar la altura de la caja externa hacia y desde 1 píxel.

Por lo tanto, digamos que queremos animar esta:

<div id="errmsg" style="display:none"> 
    <div class="errmsg"> 
     <div class="window-close" onClick="javascript:showErrMsg('', this.parentNode.parentNode)"></div> 
     <div id="errmsg.text"></div> 
    </div> 
</div> 

El cuadro es invisible al principio. La clase "ventana cerrada" es una pequeña caja a la derecha con una cruz que se usa para ocultar el cuadro cuando se hace clic. Llamar a showErrMsg() con una cadena vacía dobla el cuadro de mensaje (ver a continuación).

código

Mi JavaScript para animar este cuadro de mensaje de error es como sigue (También estoy animando la opacidad que se omite aquí por simplicidad):

var ANIMATE_STEPS = 10; 
var ANIMATE_DELAY = 20; 


function _obj(obj, parent) 
{ 
    if (typeof obj == 'string') 
     obj = (parent ? parent : document).getElementById(obj); 
    return obj; 
} 

function _setStyleHeight(obj, h) 
{ 
    _obj(obj).style.height = Math.round(h) + 'px'; 
} 

function _animateVertFold(obj, cur, by, lim) 
{ 
    obj = _obj(obj); 
    cur += by; 
    if (by < 0 && cur <= 1) 
    { 
     obj.style.display = 'none'; 
     _setStyleHeight(obj, 1); // IE doesn't accept 0 
    } 
    else if (by > 0 && cur >= lim) 
    { 
     _setStyleHeight(obj, lim); 
    } 
    else 
    { 
     _setStyleHeight(obj, cur); 
     setTimeout('_animateVertFold(\'' + obj.id + '\', ' + 
      cur + ', ' + by + ', ' + lim + ')', ANIMATE_DELAY); 
    } 
} 

function _expandElem(obj) 
{ 
    obj = _obj(obj); 
    if (obj.style.display == 'none') 
    { 
     obj.style.overflow = 'hidden'; 
     _setStyleHeight(obj, 1); 
     obj.style.display = 'block'; 
     var innerDiv = obj.getElementsByTagName('div')[0]; // better way? 
     var h = innerDiv.offsetHeight; 
     if (h > 0) 
      _animateVertFold(obj, obj.offsetHeight, h/ANIMATE_STEPS, h); 
    } 
} 

function _shrinkElem(obj) 
{ 
    obj = _obj(obj); 
    if (!obj.style.display || obj.style.display != 'none') 
    { 
     obj.style.display = 'block'; 
     obj.style.overflow = 'hidden'; 
     var h = obj.offsetHeight; 
     _animateVertFold(obj, h, - h/ANIMATE_STEPS, h); 
    } 
} 


function showErrMsg(msg, id) 
{ 
    id || (id = '_errmsg'); 
    obj = _obj(id); 
    if (msg != '') 
    { 
     _obj(id + '.text').innerHTML = msg; 
     _expandElem(obj); 
    } 
    else 
     _shrinkElem(obj); 
} 

Puede llamar showErrMsg() y el código se encargará del resto. Deberá definir la clase de cierre de ventana como algo que imita un botón de ventana de la GUI. Y, por supuesto, la clase "errmsg" como una caja con distinto color de fondo, borde y posiblemente cara de fuente también.

4

creo que el enfoque más práctico en este caso sería analizar la fuente de jQuery y construir sus funciones a partir de ahí.

3

Puede utilizar window.getComputedStyle disponible en los navegadores modernos que admita.
Devuelve una colección de todas las propiedades de estilo real aplicadas a un elemento.

Aquí es una descripción: https://developer.mozilla.org/en/DOM:window.getComputedStyle

+0

Suena interesante, aunque no está disponible en IE8, solo viene en IE9 (según mi Google). Todavía hay algo que probar, gracias. – mojuba

4

element.offsetHeight, element.offsetWidth de trabajo más o menos las mismas a través de los navegadores, enteros

element.clientWidth, element.clientHeight enteros volver volver, pero tienen algún Diferencias del navegador X (relleno, ancho del borde)

Los navegadores currentStyle o las cadenas de retorno de estilo calculado, y pueden estar en píxeles, ems, porcentajes, difíciles de manipular en el navegador X.

+0

Según la especificación, al menos getComputedStyle() siempre devuelve todo en píxeles, aunque sí, en cadenas. – mojuba

Cuestiones relacionadas