Barra de menús desplegables (II): Soporte W3C-DOM

Actualización del código de las barras de menús desplegables para poder funcionar en navegadores que soporten el W3C DOM (Netscape 6 y Explorer 5). Modificado para albergar los cambios en el Netscape 6.

¿Qué es el W3C DOM?

Vistas las numerosas incompatibilidades surgidas entre las visiones del HTML dinámico de Netscape y Explorer, el consorcio W3 decidió crear un modelo de objetos del documento (DOM) que permitiera que el DHTML fuera compatible entre todos los navegadores.

Parece que dicho objetivo esta en vías de verse cumplido. Con la reciente aparición de la primera versión preliminar del Netscape 6 se ve confirmado que los dos navegadores mayoritarios van a soportar DOM. Netscape, incluso, ha eliminado el soporte de su antiguo modelo de HTML dinámico, por lo que podemos estar seguros que la mayoría de las páginas DHTML se actualizarán a DOM a lo largo de este año. Así pues, ¿por qué no hacer nosotros lo mismo?

Prestos a modificar nuestros menús

Si disponéis de Explorer 5 o Netscape 6, podéis ver como nuestro ejemplo funciona en dichos navegadores. Si miráis el código puede que os sorprenda los cortito que es. Vamos a estudiar a partir de ahora qué modificaciones han sido necesarias para adaptarlo. Para seguir este artículo es más que recomendable que hayáis leído y entendido la entrega anterior de nuestra saga de menús desplegables.

Como usuarios la única novedad es que deberemos indicar la anchura de los menús al inicializarlos. Será el cuarto parámetro del constructor:

function inicializar() {
  ...
  menu[0] = new Menu("menu0", 20, 5, 100);
  menu[1] = new Menu("menu1", 20, 93, 120);
  menu[2] = new Menu("menu2", 20, 250, 310);
}

Sin embargo, esta necesidad se debe principalmente a un bug del Netscape 6 PR1, que no parece soportar la anchura automática. Debido a ello es posible que eliminemos esta restricción en el futuro.

Cómo funcionan los menús en DOM

Lo primero que debemos hacer es adaptar nuestro detector de navegadores para que soporte los nuevos navegadores:

Objeto DetectorNavegador
function DetectorNavegador() {
  this.NS4 = document.layers;
  this.IE4 = document.all;
  this.DOM = document.getElementById;
  this.DHTML = this.NS4 || this.IE4 || this.DOM;
}

var soporta = new DetectorNavegador();

La única novedad es la inclusión de la propiedad this.DOM, que indica si el navegador soporta este estándar. Lo averiguamos preguntando por la existencia del método document.getElementsById, propia del DOM.

El grueso de nuestras modificaciones estarán, por tanto, en el objeto Menu. Comenzaremos viendo el nuevo constructor:

function Menu(capaID, top, left) {
  this.activar = activarMenu;
  this.mostrar = mostrarMenu;
  this.ocultar = ocultarMenu;
  this.cambiarPosicion = cambiarPosicionMenu;
  if (soporta.DOM) {
    this.domRef = document.getElementById(capaID);
    this.domRef.style.width = width;
    this.domRef.style.display = "none";
    this.cambiarPosicion(top, left);
  }
}

La primera novedad es que la obtención de una referencia, que llamamos domRef, al nodo correspondiente a nuestro menú. DOM modeliza toda nuestra página HTML como un gigantesco árbol, siendo cada etiqueta un nodo del mismo. Por medio del método document.getElementsById obtenemos el nodo cuyo atributo id sea idéntico al dado como parámetro.

Una vez obtenida la referencia al nodo correspondiente a la etiqueta DIV que contiene al menú, modificamos su anchura por medio de la línea this.domRef.style.width = width;. ¡Y funciona en ambos navegadores! Siglos hacía que una cosa así se podía hacer igual tanto en Explorer como en Netscape. Dejad que disfrute del momento y ahora continúo... Ya.

Hay que indicar que por medio del atributo style se pueden modificar todas las propiedades de las que dispone una etiqueta por medio de las hojas de estilo. En la siguiente línea modificamos las propiedad display, que es nueva y fue definida en el estándar CSS2. Debemos indicar que no queremos que el elemento se visualice de ninguna manera. Si no lo hacemos así seguiríamos sin ver el menú, puesto que dijimos en la hoja de estilos que estuviera oculto (visibility: hidden), pero podríamos pulsar sobre los enlaces, aún cuando éstos no se vieran.

Finalmente llamamos al método que cambia de posición el menú y que ahora tiene este aspecto:

function cambiarPosicionMenu(top, left) {
  this.domRef.style.top = top;
  this.domRef.style.left = left;
}

Como véis, el sistema es muy parecido a lo realizado anteriormente. Los métodos para mostrar y ocultar un menú son, a su vez, muy similares:

function mostrarMenu() {
  this.domRef.style.visibility = "visible";
  this.domRef.style.display = "block";
}

function ocultarMenu() {
  this.domRef.style.visibility = "hidden";
}

La mayor diferencia con respecto a la anterior versión es que tendremos que modificar tanto visibility como display. En Netscape 6, sin embargo, al poner la visibilidad como oculta, se produce el mismo efecto que poner display a none en versiones preliminares del mismo. Y si añadimos esa línea, los enlaces dejarán de funcionar, por lo que no la ponemos.

Compatibilidad hacia atrás

Por supuesto, dado que podemos hacer menús tanto para DOM como para los navegadores de versión 4, es posible realizar una versión que funcione en todos ellos. No vamos a entrar en cómo realizarla, ya que principalmente no es más que un montón de if comprobando el navegador por todos lados, pero os dejo un nuevo ejemplo de cómo se hace.

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
SIGUIENTE ARTÍCULO

HAY 29 COMENTARIOS
  • Orestes Gonzalez dijo:

    las opciones del menu no van a ningun lugar en el Nescape 6 y Internet Explore 5 si porque?

  • José Martínez dijo:

    Las opciones de la barra de menú principal son imágenes con enlace. ¿Como se podría poner que las opciones fueran texto, pero que al situar el cursor del ratón el puntero tuviese forma de flecha?

  • Daniel Rodríguez dijo:

    Que yo sepa, no se puede cambiar el puntero del ratón bajo ningún concepto. Lo de ponerlo como imágenes es porque en el Netscape 4 no se puede detectar que un ratón esté por encima de un texto sin hacer cosas realmente extrañas. En cuanto a lo del Netscape 6, lo sé, sé el problema que hay, debe ser causado por algún bug raro porque en versiones preliminares funcionaba perfectamente. Cuando tenga tiempo y me entere lo corregiré.

  • weichafe dijo:

    bajo CSS2 se puede cambiar el puntero del raton, no se bien como se utiliza, pero lo intentare averiguar y les cuento.

  • Daniel rodríguez dijo:

    Efectivamente, tienes razón (prego). Se puede. Mirad http://www.vespito.com/css2

  • Gornak dijo:

    Se pueden poner punteros diastintos, tambien se pueden cambiar los colores de las tablas, lo e visto y estoy cachando como, y lo mejor que cache hoy, es que se puede cambiar el color de el Scrolling, ese lo tengo si lo quieren, avisenme. Quizas estoy atrasado y esto lo saben, pero igual. Eso si si saben hacer lo de las tablas me lo enseñan, a todo esto NETSCAPE no pesca Archivos de estilo, pero si saben ASP lo hacen desde el servidor en ASP y lo cacha cualquiera.

  • ruicapmi dijo:

    En navegadores 4.* de NS y IE la propiedad x,y que indica la posición absoluta de un ancla en la pantalla era un atributo público. En NS6 no he encontrado la forma de acceder a esas propiedades y en cambio IE5.* continúa conservándolas. Alguien sabe como acceder a ellas? Alguien puede sugerirme alternativas? Gracias

  • Andrés García Alcántara dijo:

    Solo debes usar bordercolor en las tablas Ejemplo: y en el cursor con html dinámico Ejemplo: El tipo de cursores son auto crosshair default hand move e-resize ne-resize nw-resize n-resize se-resize sw-resize s-resize w-resize text wait help

  • Andrés García Alcántara dijo:

    Solo debes usar bordercolor en las tablas Ejemplo: <table bordercolor="..."... y en el cursor con html dinámico Ejemplo: <style type="text/css" <!-- A:link{   font-face:arial;   color:blue;   text-decoration:none;  } A:hover{   font-face:arial;   color:#AA0000;   text-decoration:underline overline;   cursor:help;   }  -- </style El tipo de cursores son: auto crosshair default hand move e-resize ne-resize nw-resize n-resize se-resize sw-resize s-resize w-resize text wait help

  • CARLOS MORENO dijo:

    ¿Como puedo desplegar un menú que solape marcos de pantalla? Tengo una pantalla con un marco de encabezado estrecho, y en este quiero poner una barra de menús desplegable, pero cuando de despliegua el menú las opciones quedan ocultas por el marco principal.

  • Pedro F. Marta dijo:

    Apreciados todos, He metido los menus desplegables en las paginas web de mi institucion, pero los usuarios de MSIE 5 y superiores no lo ven como quiero, solo ven la lista arriba y me descoloca todo. Ademas los menus toman el tamaño de la columna desde donde se cargan. Como puedo solucionarlo http://antropologia.urv.es

  • Mª Eugenia dijo:

    Hola! He estado probando el ejemplo, pero tengo el problema de que cuando las capas se despliegan encima de controles de formulario modificables (input text, select, etc), si estos son mas "largos" que la capa, la capa no tapa estos controles, sino que se queda entrecortada por los mismos...Alguna sugerencia? Gracias. Aprovecho para felicitar al autor del articulo, es muy bueno

  • Andres dijo:

    muy buena..!! pero necesitaria saber como hago para que los menues desaparezcan una vez que el mouse no esta sobre ellos. gracias.

  • Cesar Ivan Lopez Herrera dijo:

    Saludos: Cuando intento combinar marcos con capas, estas últimas se solapan bajo las primeras, no respondiendo de ninguna manera a las variable 'z-index'. Lo mismo sucede con los menus desplegables. La solución que he encontrado es convertir, la capa que contiene el menu, en un marco y de este modo si responde correctamente, pero pierde la agilidad y dinamismo del menu desplegable. Solicito me envien alguna solución, o alguna propuesta. GRACIAS Por favor si es posible envien dicha solucion o propuesta a mi e-mail [email protected] y yo personalmente me encargaré de publicarla en este mismo foro.

  • Cesar Pelegrin dijo:

    Hola, tengo un menu desplegable dentro de un frame, y cuando se despliega, me aparece por debajo de la otra division del frame.¿Alguna idea? Gracias.

  • Miguel Angel dijo:

    Bueno, copie el menu desplegable de prueba de su pagina y la puse a una que estoy haciendo, hay un problema, es que cuando cambio la pantalla a 1024x768 se refleja en otro lado del link y cuando esta en 800x600 esta normal. Mi pregunta es ¿¿¿A que se debe eso???

  • Vicente Garrido dijo:

    He cogido vuestro menu y lo he metido en la página que estoy elaborando, ya que el menu desplegable que tenía no aparecía en Netscape, y funciona tanto en MSIE como en NS. Me gustaría saber cómo se puede ocultar el desplegable sin hacer click, que se retire al salir el puntero del raton de la celda. Muchas gracias y felicidades por vuestra labor.

  • Monica dijo:

    Esta muy buena esta sección. Les quería pedir un favor, tengo un menu desplegable, que desde las opciones del menu hasta los submenus de estos, son textos editables; lo que quiero hacer es que al pasar por alguna de las opciones del menu este se quede prendido es decir este en bold pero tambien se quede asi hasta que estoy en el submenu del escogfido, cosa que no me sucede, una vez que escojo una opcion del submenu se apaga la opcion del menu principal, podrían ayudarme?

  • daniel dijo:

    Hola he visto vuestro menu me gusta bastante, ademas compatible con NS6. Pero tengo un problema que he encontrado en todos los menus que he visto. los malditos combo (o select) siempre se quedan por encima del menu. Alguien tiene alguna idea (que no sea quitar los combo) de que hacer para que estes se queden por debajo. gracias

  • Martín dijo:

    Estoy muy contento con el código, me va de maravilla en IE y en NS6, pero no en NS4, alguien sabe lo que puede pasar. Gracias

  • Diego dijo:

    He buscado un menu como este para mi pagina en todos los lados, y por fin lo encuentro. Muchas gracias x todo. Muy pronto lo vereis en http://www.madriles.net

  • felix dijo:

    No he conseguido que el ejemplo me funcione en esta versión, alguien saber porque GRACIAS

  • MrSpock57 dijo:

    Apreciaré que alguien me indique si es posible utilizar estos menúes pero alineados verticalmente Gracias.

  • santos dijo:

    Como puedo crear un menu

  • joseluis dijo:

    Tengo un menú con esta forma de actuar una de las pantallas en las que lo uso resulta ser muy grande, con la versio ie 5 y 5.5 no había ningún problema pero a partir de ie 6 he notado que consume muchísimos más recursos de la máquina (menoria y cpu) por consiguiente tarda en desplegar cada rama varios segudos. ¿Alguien puede darme una solución? o por lo menos una explicación de por que pasa? Gracias

  • Usuario dijo:

    No os comais la cabeza con tanto codigo este programa te lo hace solo: AllWebMenus PRO 3.1

  • Metal dijo:

    Existe algún manual para este programa? Es que el Ingles como que se me resiste. O si ni ¿Sabeis de algún programa para los menus que sea en Español.

  • huevos dijo:

    chingen su madre putos

  • informático empedernido dijo:

    function DetectorNavegador() { this.NS4 = document.layers; this.IE4 = document.all; this.DHTML = this.NS4 || this.IE4; } var soporta = new DetectorNavegador(); var menu = new Array(); var menuActivo = null; function activarMenu() { if (soporta.DHTML && (menuActivo != this)) { if (menuActivo) menuActivo.ocultar(); menuActivo = this; this.mostrar(); } } function mostrarMenu() { eval(this.capaRefStr + this.estiloRefStr + .visibility = "visible"); } function ocultarMenu() { eval(this.capaRefStr + this.estiloRefStr + .visibility = "hidden"); } function cambiarPosicionMenu(top, left) { if (soporta.DHTML) { eval(this.capaRefStr + this.estiloRefStr + this.topRefStr + = top); eval(this.capaRefStr + this.estiloRefStr + this.leftRefStr + = left); } } function ocultarMenuActivo(e) { if (menuActivo) { menuActivo.ocultar(); menuActivo = null; } } function Menu(capaID, top, left) { this.activar = activarMenu; this.mostrar = mostrarMenu; this.ocultar = ocultarMenu; this.cambiarPosicion = cambiarPosicionMenu; this.capaRefStr = (soporta.NS4) ? document["+capaID+"] : document.all["+capaID+"]; this.estiloRefStr = (soporta.NS4) ? : .style; this.topRefStr = (soporta.NS4) ? .top : .pixelTop; this.leftRefStr = (soporta.NS4) ? .left : .pixelLeft; this.cambiarPosicion(top, left); } function inicializar() { if (soporta.DHTML) { if (soporta.NS4) document.captureEvents(Event.MOUSEUP); document.onmouseup = ocultarMenuActivo; } menu[0] = new Menu("menu0", 20, 5); menu[1] = new Menu("menu1", 20, 93); menu[2] = new Menu("menu2", 20, 250); } window.onload = inicializar; ... Imágenes ...

Conéctate o Regístrate para dejar tu comentario.