JMiur [E]

Las ventanas modales perfectas no existen, todas tienen algo que no pueden hacer o limitaciones de alguna clase y no hay manera de abarcar todas las posibilidades ya que son infinitas; es por eso que lo primero a definir luego de tanto código suelto y pedacitos de soluciones, es establecer para qué las necesitamos y cuál es la forma que nos resultará más cómoda de usarlas. El script y sus funciones son la forma de obtener eso y no lo inverso.

Así que vamos a poner orden y terminar este suplico con un modelo que muestre imágenes y una eventual variante que también pueda mostrar videos.

Primero que nada, necesitamos el HTML tal como se mostró en la primera parte con alguna variante para completarlo. Ponemos entonces esto al final de la página, justo antes de </body>:
<div id="MVM-overlay"></div>
<div id="MVM">
  <div id="MVM-inner">
    <div id="MVM-contenido"></div>
    <a id="MVM-cerrar" href="javascript:cerrarMIventanamodal()"></a>
  </div>
</div>
Y el CSS correspondiente antes de </head>. Esta es la parte personalizable al extremo así que acá esta el detalle del ejemplo pero puede ser cualquier otro:

<style type='text/css'>
  /* este es el DIV de fondo que oscurece toda la pantalla detrás de la ventana */
  #MVM-overlay {
    background:transparent url(http://img40.xooimage.com/files/7/0/3/black-70-141fd7a.png) repeat left top;
    height:0;
    left: 0;
    position: fixed;
    top: 0;
    visibility:hidden;
    width: 100%;
    z-index: 9999;
    /* algunas propiedades que no funcionarán en IE */
    opacity: 0;
    -moz-transition: all 1s;
    -webkit-transition: all 1s;
    -o-transition: all 1s;
  }
  /* el DIV que contiene la ventana modal en si misma */
  #MVM {
    left: 0;
    position: absolute;
    top: 0;
    visibility: hidden;
    z-index: 10000;
  }
  /* un DIV interior de esa misma ventana */
  #MVM-inner { position: relative; }
  /* el DIV donde se mostrarán las cosas */
  #MVM-contenido {
    background-image: -moz-linear-gradient(100% 100% 90deg, rgba(100,100,100,.5),rgba(100,100,100,.5));
    background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(100,100,100,.5)), to(rgba(100,100,100,.5)));
    filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#80646464', EndColorStr='#80646464');
    height: 100%;
    line-height: 0;
    padding: 20px;
    /* algunas propeidades que no funcionarán en versiones anteriores a IE9 */
    border-radius: 10px;
    box-shadow: 0 0 5px #FFF inset;
  }
  /* el botón para cerrar la ventana */
  #MVM-cerrar {
    background: transparent url(http://img73.xooimage.com/files/3/4/c/close-28e1d92.gif) no-repeat left top;
    height: 32px;
    opacity: 0.5;
    position: absolute;
    right: -15px;
    top: -15px;
    width: 32px;
  }
  #MVM-cerrar:hover { opacity:1; }
</style>

Tal como hasta se ha visto hasta ahora, vamos a llamar a la ventana haciendo click en una etiqueta span de una cierta clase; en este caso, la llamo mvm y posee tres atributos:

w contendrá el ancho de la imagen
h el alto de la imagen
url la dirección URL de la imagen

Cuando la quisiéramos usar, deberíamos escribir algo así:
<span class="mvm" url="URL_IMAGEN" w="un_valor" h="un_valor"> un texto o miniatura </span>
Obviamante, podemos agregar CSS para esa clase y que se muestre distinta a un enlace normal; eso queda a criterio de cada uno y no tiene efecto alguno en su funcionamiento.


ejemplo de ventana modal


Sólo nos falta el script que he colocado en este archivo de texto para que sea más sencillo de probar y que debemos colocar antes de </head>:

<script type='text/javascript'>
//<![CDATA[

// declaraciones generales
var MVM , MVMINNER, MVMCONTENIDO, MVMCERRAR;

// esto es l oque agrega un ID a las etiquetas cuando usamos IE
var IEelem={};
function IEaddID(fn,uniqueID) {
  return function(event) {return fn.call(IEelem[uniqueID],event);}
}

// la funcion que agregará el evento onclick a nuestras etiquetas
function creaMIventanamodal() {

  // guardamos los IDs de los distintos DIVs así luego podemos usarlos más fácilmente
  MVM = document.getElementById("MVM");
  MVMCONTENIDO = document.getElementById("MVM-contenido");
  MVMOVERLAY = document.getElementById("MVM-overlay");

  // buscamos todas las etiquetas SPAN cuya clase sea mvm y le agregamos el evento onclick
  var el = document.getElementsByTagName("span");
  for (var i=0; i<el.length; i++) {
    var c = el[i].className;
    if (c=="mvm") {
      if (el[i].addEventListener) {
        el[i].addEventListener("click", abrirMIventanamodal, false);
      } else if (el[i].attachEvent) {
        var uniqueID = el[i].uniqueID;IEelem[uniqueID] = el[i];
        el[i].attachEvent("onclick",IEaddID(abrirMIventanamodal,uniqueID));
      }
    }
  }
}

// esta es la funcion que se ejecutará cuando hagamos click en esas etiquetas
function abrirMIventanamodal() {

  // si la ventana ya está abierta no hacemos nada
  if(MVM.style.visibility == "visible") { return; }

  // leemos y guardamos los datos que contienen los atributos de la etiqueta
  var archivo, ancho, alto;
  archivo = this.getAttribute("url");
  ancho = this.getAttribute("w");
  alto = this.getAttribute("h");

  // este dato es una "corrección" para calcular el ancho de nuestro contenedor que, en este caso, posee un apdding
  var cLR = 20; // la suma de los paddings y borders left y right
  var cTB  = 20; // la suma de los paddings y borders top y bottom
  var calcancho = parseFloat(ancho) + cLR; // ancho de la ventana
  var calcalto = parseFloat(alto) + cTB; // alto de la ventana

  // calculamos el ancho del navegador y en que parte de la página estamos
  var sW = document.documentElement.clientWidth;
  var sH = document.documentElement.clientHeight;
  var posicion = getpagePosition();

  // con esos datos, establecemos la posición de la ventana modal
  var x, y;
  x = (sW - calcancho) / 2;
  y = posicion + (sH - calcalto) / 2;

  // se acabó la aritmética

  // dimensionamos la ventana según su contenido
  MVMCONTENIDO.style.width = ancho + "px";
  MVMCONTENIDO.style.height = alto + "px";
  // y ponemos una etiqueta IMG con el archivo a mostrar
  MVMCONTENIDO.innerHTML = "<img src='" + archivo + "' />";

  // posicionamos la ventana modal
  MVM.style.left = x + "px";
  MVM.style.top = y + "px";

  // dimensionamos el DIV oscuro de fondo y lo mostramos
  MVMOVERLAY.style.height = sH + "px";
  MVMOVERLAY.style.visibility="visible";
  MVMOVERLAY.style.opacity=1;

  // mostramos la ventana y su contenido
  MVM.style.visibility = "visible";
}

// esta es la función que cierra la ventana modal
function cerrarMIventanamodal() {
  MVM.style.visibility = "hidden"; // la ocultamos
  MVMCONTENIDO.innerHTML = ""; // eliminamos su contenido
  // ocultamos el fondo negro
  MVMOVERLAY.style.opacity=0; 
  MVMOVERLAY.style.visibility="hidden";
}

// esta finción nos devuelve la posición de la pa´gina donde nos encontramos
function getpagePosition() {
  if(typeof(window.pageYOffset) == 'number') {
    pp = window.pageYOffset;
  } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
    pp = document.body.scrollTop;
  } else if(document.documentElement) {
    pp = document.documentElement.scrollTop;
  }
  return pp;
}

// ¿qué pasa si redimensionamos la ventana del navegador? 
// lo simplificamos a lextremo, simpleemnte, cerramos la ventana modal
window.onresize = doResize;
function doResize() {
  if(document.getElementById("MVM").style.visibility=="visible") {
    cerrarMIventanamodal()
  }
}

// la función principal se ejecuta recién cuando se termina de cargar la página
window.onload = creaMIventanamodal;

//]]>
</script>

Y ahí se acabó todo.


IMG 300x188IMG 500x400IMG 800x600


Cualquier variante es posible si se entiende como funciona ya que sólo hay dos puntos a definir, cuales son los atributos donde agregaremos los datos a usar y cómo escribiremos la salida.

Por ejemplo, hacemos lo mismo pero con un video de YouTube. Defino porque se me ocurre, que el atributo a usar lo llamaré yt y contendrá el ID del video que son esos once caracteres que lo identifican.
<span class="mvm" yt="12345678901"> un texto o miniatura </span>
Como quiero usar la misma ventana modal para ambas cosas, modifico un poco la función, dividiéndola en dos:
function abrirMIventanamodal() {
  // si la ventana ya está abierta no hacemos nada
  if(MVM.style.visibility == "visible") { return; }

  // guardo el dato de la etiqueta donde se hizo click
  var obj=this;

  // verifico los atributos
  if(this.getAttribute("yt")) {
    // si tiene el atributo yt es un video y continua en otro lado
    abrirMIventanamodalVID(obj);
  } else {
    // si no lo tiene es una imagen y continua en otro lado
    abrirMIventanamodalIMG(obj);
  }
}
La función abrirMIventanamodalIMG() es igual a la primera excepto que la variable this ahora se llama obj.

La función abrirMIventanamodalVID() es muy similar ya que el cambio más importante sólo es la salida de los datos:

function abrirMIventanamodalVID(cual) {
  // el ID del video
  var idvideo = cual.getAttribute("yt");

  // el ancho y el alto son fijos así que no necesito enviárselos
  var ancho = 640;
  var alto = 385;

  ....... de aquí en adelante, todo es igual .......

  // y en lugar de una etiqueta IMG colocamos una etiqueta OBJECT

  var url ="http://www.youtube.com/v/" + idvideo + "&hl=es&fs=1&rel=0&autoplay=1&ap=%2526fmt%3D18&showsearch=0&showinfo=0";
  var salida= "<object width='" + ancho + "' height='" + alto + "' type='application/x-shockwave-flash' data='" + url + "'>";
  salida += "<param name='movie' value='" + url + "' />";
  salida += "<param name='wmode' value='transparent' />";
  salida += "<param name='allowfullscreen' value='true'/>";
  salida += "<param name='allowScriptAccess' value='always' />";
  salida += "</object>";
  MVMCONTENIDO.innerHTML = salida;

  ....... y terminamos igual, posicionando y mostrando la ventana .......
}


ejemplo con video de YOUTUBE


El código de esta última alternativa puede descargarse desde este archivo de texto.

38 comentarios:

Homo Inquietus  

Interesante, lo de crear una ventana modal, propia. He seguido las entradas y con esta última más o menos, lo tengo claro. Ahora solo queda probar y probar ..... bueno y tiempo para poner en práctica, todo lo expuesto en tus entradas. Pero sé con certeza que sí necesito ayuda, puedo recurrir a ti.

Responder
Beben Koben  

i think fixed on CSS more bautiful :D

Responder
JMiur  

Homo Inquietus:
Sólo es cuestión de probar y ver que sale :D

Beben Koben:
Beauty is not a technical matter. It is a subjective definition and can not be discussed.

Responder
Tapestryworkerman  

Hola JMiur.
Otra vez encandilado con el vídeo musical...
Ok my friend!! ;)
Un saludo.

Responder
deathdan93  

Es estupendo crearse una ventana modal propia, al fin y al cabo, a mi me basta con una simple para imágenes y vídeos de Youtube. Pero, ¿Cómo se podría hacer para que te siga hacia arriba y hacia abajo cuando está abierta como lightwindow? ¿Sería muy complicado?

Responder
JMiur  

Es un vicio, Tapestryworkerman :D

Responder
Ronymaru  

No entendí mucho, pero me divertí escudriñando las ventanas modales. Y me parece que mi problema se resolvió por si solo.

Responder
Beben Koben  

just share
http://simplemodal.plasm.it
hehehe ;)

Responder
JMiur  

Ronymaru:
Para eso debes usar position fixed en luagr de position absolute y calcular la altura de top en función de la altura de la ventana del navegador en lugar de calcularla en función de la altura de la página.

Beben Koben:
It's a plugin for MooTools.

Responder
FG  

hola...no estoy entendiendo....puse todo como corresponde y me sale algo asi
No se ha podido analizar su plantilla, porque no está bien formada. Asegúrese de que todos los elementos XML se han cerrado correctamente.
Mensaje de error de XML: Element type "el.length" must be followed by either attribute specifications, ">" or "/>".
Error 500

Responder
JMiur  

SI la etiqueta SCRIPT incluye CDATA tal como muetra el post, no debe haber ningún mensaje de error de ese tipo.

Responder
astro2k  

Y porque el puñetero IE8 me saca típica la barrita amarilla diciendome que se intenta ejecutar un script y que si estoy de acuerdo y demás chorradas.

Cuando pincho en esta web en cualquier ejemplo, me sale sin problema, pero cuando ejecuto la que yo he "hecho" en mi ordenador me sale la advertencia de los coj...

¿No hay manera de evitarlo?

Responder
JMiur  

Depende de como lo hayas configurado; revisa las restricciones que tienes agregadas.

Responder
mamadealess  

Hola !!!!...debo confesar que esto me requete supera!!...
estoy queriendo agregar las definiciones a algunas palabras dentro de un texto y se me ocurrio que esto de las ventanas modales podria servir...pero el problema es que no entiendo mucho de esto !!..Alguna sugerencia???...
Será muy bienvenida!!!

Responder
JMiur  

Tendrías que usar alguna ventana modal ya prediseñada.

Responder
mamadealess  

Gracias !!!!.Estuve viendo aqui mismo el ibox..pero se me ocurre que con el tiempo algunos artilugios no se pueden usar (el post es del 2008) por lo que no quise usarlo...Ese estaria bien?...o hay otra manera de poner esa definicion con otra cosa que no sea una ventana modal?

Mil gracias!!!!

Responder
JMiur  

Cualquiera funcionará. La ventana modal de ibox es de las más sencillas.

Responder
mamadealess  

Mil Gracias!!!!!

Responder
mamadealess  

FUNCIONÓ!!..Gracias!!!!....
No sé si hice bien en guardar todo en la misma plantilla....quise alojarlos en google sites pero es inentendible para mí (la ayuda no es tan eficiente que digamos)..salvo que me haya equivocado y google sites no es para eso...
La cuestion es que quedó de rechupete!!!..le voy a poner un borde punteado y listo!!!
Mil gracias!!!!

Responder
JMiur  

No hay ningún problema en guardarlo en la plantilla. A mi juicio, en el caso de Blogger es mejor.

Responder
mamadealess  

Uf..Menos mal!!!!...Muy agradecida!!!

Responder
Ros  

Como puedo lograr que el contenido sea un texto dinamico o no, que vaya ubicado en div id="MVM-contenido">texto</div

JMiur  

¿Y cuál seria ese contenido? ¿de donde sale?

Ros  

El texto lo pondria yo o lo tomaria desde otro lugar mediante php.. pregunto esto porque al querer poner un texto dentro del div contenido me di cuenta que el script solo tomaba imagenes.

JMiur  

Poner sólo un texto sería distinto, debería cambiarse (simplificar) el script.

Ros  

como podria hacerla dado que intente meter getelementbyid pero obviamente no me funciono dado que soy un newbie en esto del js

JMiur  

Como no sé que es lo que estás haciendo, no puedo decirte mucho más. Debería ver tu ejemplo para entender de qué se trata.

Responder
Angel Rosales  

Hola amigo muy bueno tu aport.

Me gustaria saber como le hago para que en vez de la imagen que tu le cargaas o el string de la imagen que le envias, incluya un archivo.php

JMiur  

¿Un archivo PHP que haga qué cosa?

Responder
Alex Moñino  

Buenas,

Haces un trabajo espectacular felicidades!!!
Puede ser que en Chrome no me funcione adecuadamente?
Lo digo porque he realizado todo de pe a pa y en ie y firefox funciona, pero en chrome no.
Alguna idea??

JMiur  

Imposible responderte porque no sé cuál es tu ejemplo y el que se muestra en esta entrada, funciona perfectament en Chrome

Responder
Alex Moñino  

Perfecto ja funciona en chrome, era un tema del charset

Responder
Alex Moñino  

Una pregunta, seria posible en lugar de enseñar una imagen , redirigir a una pantalla de registro o similar?

Muchas gracias!!!

JMiur  

Sí, claro. el contenido puede ser cualquier cosa que agregues; basta crear el código respectivo.

Responder
Unknown  

como seria el codigo para q habra una pagina ya sea html o php, por que intente con varias cuestiones pero no logro conseguir

con window.open me traer el resultado deseado pero no dentro de la ventan modal

JMiur  

Una página externa se debe abrir utilizando una etqueta IFRAME.

Responder
JH MAGNO  

En dónde se pone esa etiqueta IFRAME? Ayuda pliz

JMiur  

Donde quieras que se muestre ese contenido.

Responder

¿Quiere dejar un comentario?

recuerde que los comentarios están siendo moderados y serán publicados a la brevedad ...

Todos los archivos y demos alojados en Fileden han sido redireccionados y deberían estar funcionando correctamente.
De todos modos, también puede accederse a ellos a través de SkyDrive

Nota: sólo los miembros de este blog pueden publicar comentarios.

Si le gusta ir a lo seguro utilice este botón para abrir los comentarios en una ventana modal en esta misma pagina.

Si añora tiempos idos, use este enlace para agregar un comentario al viejo estilo ...

 
CERRAR