Ejemplos de aplicación de la clase formEmerge

Exponemos aquí algunos ejemplos de aplicación de la clase formEmerge para crear formularios emergentes. Usaremos todos los recursos vistos: objeto repuesta, eventos del formulario y pestañas. Todo el código JavaScript para crear los objetos así como el estilo CSS aplicado puede verlo en los elementos <script> y <style> en la cabecera de esta página, por lo que puede también consultarlo con el menú del navegador o bien en esta copia que hemos hecho del código de estos ejemplos.

Usando un emergente para un calendario

En primer lugar incorporamos un calendario dentro de un formulario emergente con la clase calendar. La información sobre este clase está en el calendario con objetos de JavaScript.

Disponemos de un cuadro de texto donde el usuario puede introducir una fecha, o bien usar el botón para seleccionarla desde el calendario:

Ejemplo:

El código de este cuadro y botón es el siguiente:

<label>Introduzca fecha con el botón:
   <input type="text" value=" " id="cuadro-fecha" />
</label>
<input type="button" value="..."
onclick="emergeCalendario.abrir('', '', this.offsetLeft,
this.offsetTop+this.offsetHeight)" /> 

Creamos un formulario emergente para contener nuestro objeto calendario. Los dos objetos los construimos en el window.onload de esta página, donde también puede ver el estilo aplicado al calendario así como el siguiente script:

//Una instancia de un calendario para usar en el ejemplo
var miCalendario = null;
//Una instancia de un emergente para el ejemplo
var emergeCalendario = null;
...
//Carga de la página, donde creamos formularios emergentes
window.onload = function() {
    // EJEMPLO DEL CALENDARIO ------------------------
    //Creamos el primer emergente para el calendario
    emergeCalendario = new formEmerge("emergeCalendario", "Calendario",
            true, 2, "marco");
    //Componemos un interior para ubicar el calendario
    var html = "<div class='previo-cal'>" +
    "<input type='button' value='<' " +
    "onclick = 'miCalendario.mueveCalendar(-1)' />" +
    "<input type='text' id='ubica-titulo' value='' size='8' " +
    "onfocus = 'miCalendario.entraFecha(this)' " +
    "onblur = 'miCalendario.mueveMesAnyo(this)' />" +
    "<input type='button' value='>' " +
    "onclick = 'miCalendario.mueveCalendar(1)' />" +
    "</div>" +
    "<div id='ubica-calendario'></div>";
    //Ponemos esa composición en el interior del emergente
    emergeCalendario.nuevoInterior(html);
    //Establecemos el cuadro de fecha como objeto respuesta.
    emergeCalendario.idObjetoRespuesta = "cuadro-fecha";
    //Cuando se abra el calendario, situamos la fecha del cuadro
    emergeCalendario.eventoAbrir = true;
    emergeCalendario.ejecutaEventoAbrir = function (){
        miCalendario.situaFecha(emergeCalendario.respuesta);
    }
    //Cuando pulsemos aceptar extraemos la fecha del calendario
    emergeCalendario.eventoAceptar = true;
    emergeCalendario.ejecutaEventoAceptar = function(){
         emergeCalendario.respuesta = miCalendario.devuelveFecha("fecha-larga");
    }
    //Creamos un objeto calendario
    miCalendario = new calendar("miCalendario", "ubica-calendario",
            "ubica-titulo", "", true);
    if (miCalendario.creado) miCalendario.construyeCalendario();
    ...
}

En resumen se trata de hacer lo siguiente:

  1. Creamos el nuevo objeto emergeCalendario = new formEmerge() para contener el calendario.
  2. Componemos una cadena literal HTML para el interior de ese emergente y luego la añadimos con emergeCalendario.nuevoInterior(). Esta construcción podrá entenderla mejor si analiza lo explicado en los ejemplos del calendario con objetos de JavaScript. En resumen se trata de dotar de unos elementos de control del formulario: botones para avanzar y retroceder un mes y un cuadro de texto para poner el mes-año.
  3. Establecemos el objeto respuesta del formulario apuntando al cuadro de texto que está por fuera, pasando el id a la propiedad idObjetoRespuesta.
  4. Activamos el evento al abrir el formulario para que cargue la fecha de ese cuadro en el objeto calendario mediante su método miCalendario.situaFecha()
  5. Activamos el evento aceptar del emergente para hacer lo contrario, poner la fecha seleccionada del calendario en el emergente en el cuadro de texto externo (por medio de la propiedad respuesta del emergente). Se usa el método miCalendario.devuelveFecha() para obtener la fecha seleccionada.
  6. Creamos el objeto calendario con miCalendario = new calendar() y lo construimos con miCalendario.construyeCalendario().

Esta aplicación funciona bien en Internet Explorer 8, Firefox 3.6, Opera 10.6 y Safari 4.0.

Un formulario emergente para enviar datos al servidor

El formulario no deja de ser un elemento <form> por lo que podría servir para enviar datos al servidor.

Ejemplo:

Abre un formulario para envío de datos al servidor

Al crear el emergente usamos los dos últimos argumentos para indicar el PHP que se ejecutará en el atributo action y el método post para el atributo method del formulario:

...
//Una instancia para el formulario de envío de datos
var miForm = null;
...
//Carga de la página, donde creamos formularios emergentes
window.onload = function() {
    ...
    // EJEMPLO DEL FORMULARIO PARA ENVIO DE DATOS -----
    //Creamos otro emergente para envío de datos
    miForm = new formEmerge("miForm", "Enviar datos",
            true, 3, "marco", "miform.php", "post");
    //Componemos un literal HTML para la primera pestaña
    var html1 = "<label>Nombre:<input type='text' name='nombre' value='' " +
    "size='35' class='fuente-mi-form' />" +
    "</label><br />" +
    "<label>Dirección:<input type='text' name='direccion' value='' " +
    "size='35' class='fuente-mi-form' />" +
    "</label><br />" +
    "<label>E-mail:<input type='text' name='email' value='' " +
    "size='35' class='fuente-mi-form' />" +
    "</label><br />" +
    "<label>Cuestión:<br /><textarea name='cuestion' rows='7' cols='40' "+
    "class='fuente-mi-form'></textarea>" +
    "</label>";
    //Componemos otro literal para la segunda pestaña
    var html2 = "<label>Edad:<input type='text' name='edad' value='' " +
    "size='10' class='fuente-mi-form' />" +
    "</label><br />" +
    "<label>Profesión:<input type='text' name='profesion' value='' " +
    "size='35' class='fuente-mi-form' />" +
    "</label><br />" +
    "<label>Aficiones:<input type='text' name='aficiones' value='' " +
    "size='35' class='fuente-mi-form' />" +
    "</label><br />";
    //Llenamos un array con los nombres de las pestañas
    var arrayPestanyas = new Array("Personales", "Otros datos");
    // Llenamos una array con los contenidos
    var arrayHtmls = new Array(html1, html2);
    // Creamos las pestañas con esos dos array y les damos
    //ancho, alto y "auto" para la propiedad overflow
    miForm.creaTabs(arrayPestanyas, arrayHtmls, "23em", "14em", "auto");
    ...
}

En este caso podemos usar pestañas si son muchos los campos a enviar y no queremos que ocupe mucho espacio en pantalla, al tiempo que nos permite agruparlos de alguna forma.

Para el recibido de datos en el servidor hemos usado un ejemplo expuesto en nuestro glosario XHTML+CSS: enviando formulario al servidor con PHP, donde también exponemos el código del php. Hemos copiado ese archivo script.php en la ruta de este documento renombrándolo como miform.php y le hemos incorporado algunos campos más: edad, profesión y aficiones.

Un formulario emergente para una calculadora

Una de las primeras aplicaciones que hice al aprender JavaScript fue esta calculadora, donde puede ver más detalles en mi glosario, en el tema sobre el uso del evento onload para hacer una aplicación de JavaScript: la calculadora. En este año he estado aprendiendo sobre los objetos de JavaScript y he reconvertido la calculadora anterior, que actuaba con funciones, en un objeto de JavaScript. Esto nos permite abrir varias calculadoras independientes en el mismo documento. Se estructura con archivos externos calculadora-objeto.js para el script y calculadora-objeto.css para el estilo. Puede ver el codigo del objeto con más comentarios.

En primer lugar insertamos en el siguiente <div id="div-una-calculadora"> con borde verde un objeto calculadora mediante el código que está en el window.onload de esta página, declarándolo en la variable unaCalculadora y creándolo en primer lugar.

...
//Instancias para el ejemplo de la calculadora
var unaCalculadora = null;
var emergeCalculadora = null;
var miCalc = null;
...
//Carga de la página, donde creamos formularios emergentes
window.onload = function() {
    ...
    //EJEMPLO DEL FORMULARIO EMERGENTE CON CALCULADORA -------
    //Creamos un objeto calculadora en un div del documento
    unaCalculadora = new calculadora("unaCalculadora",
        "div-una-calculadora");
    //Creamos un emergente para OTRO objeto calculadora
    emergeCalculadora = new formEmerge("emergeCalculadora",
        "Calculadora", false, 0, "marco");
    //Otro objeto calculadora para el emergente anterior, 
    //poniéndolo en su interior.
    miCalc = new calculadora("miCalc", "IDPRE" + "emergeCalculadoraInterior");
    ...
}
    
Este es un objeto calculadora insertado en el <div id="div-una-calculadora">:

Ejemplo:

Luego declaramos otra variable emergeCalculadora para crear un formulario emergente. Otro nuevo objeto calculadora miCalc se crea y se inserta en el interior de ese emergente. El cuerpo interior de un emergente es un elemento <div> que se identifica con "IDPRE" + nombre_del_emergente + "Interior", donde nombre_del_emergente es igual que el nombre de la variable con la que se instanció el objeto. Así para el emergeCalculadora su interior se identifica con "IDPRE" + "emergeCalculadoraInterior". Recuerde que "IDPRE" es el prefijo que se antepone a todos los identificadores creados dinámicamente en un formulario emergente. Este prefijo se declara como una constante global en el archivo form-emerge.js donde esta la clase emergeForm.

Con el siguiente botón puede abrirse este emergente con calculadora:

Ejemplo:

Abre una calculadora emergente.

Como en otros ejemplos, este botón contiene el método abrir del emergente:

Abre una calculadora emergente.
<input type="button" value="..."
onclick="emergeCalculadora.abrir('', '', this.offsetLeft,
this.offsetTop+this.offsetHeight)" />
    

Como objetos que son, ambas calculadoras son independientes de tal forma que podemos instanciar cuantas queramos y con sus propios cálculos. El estilo de la calculadora está en el archivo calculadora-objeto.css que define un borde y color de fondo. Para adecuarlo a nuestro emergente volvemos a a sobreescribir estas propiedades. El código CSS siguiente está en el elemento <style> de este documento:

div.PRECALCcalculadora {
    border: gray solid 1px;
    background-color: rgb(230,230,205);
    }

Un formulario emergente para Notas

Ahora ponemos un elemento HTML <textarea> dentro de otro formulario emergente que construimos como emergeNotas, con la finalidad de que sirva para anotaciones del usuario. También ponemos un botón que llama a otro emergente emergeOpciones para cambiar opciones de la fuente del <textarea>:

Ejemplo:

Abre notas

Activamos los eventos al abrir el formulario y al aceptarlo o aplicarlo:

...
//Una instancia para un bloc de notas y otro para opciones
var emergeNotas = null;
var emergeOpciones = null;
...
//Carga de la página, donde creamos formularios emergentes
window.onload = function() {
    ...
    //EJEMPLO DEL FORMULARIO EMERGENTE BLOC NOTAS ----------
    //Creamos un emergente para contener el textarea de notas
    emergeNotas = new formEmerge("emergeNotas", "Notas", false, 0);
    //Componemos un literal HTML para el interior 
    var interiorNotas = "<textarea rows='10' cols='30' id='textarea-notas' " +
    "style='font-size: 16px; font-family: Courier New; font-style: normal; " +
    "font-weight: normal;'></textarea><br />" +
    "<input type='button' value='opciones' " +
    "onclick = \"emergeOpciones.abrir('', '', " +
    "emergeNotas.form().offsetLeft+emergeNotas.form().offsetWidth, " +
    "emergeNotas.form().offsetTop)\" />";
    //Ponemos ese literal en el interior
    emergeNotas.nuevoInterior(interiorNotas);

    //Creamos otro emergente con opciones para cambiar el
    //estilo de la fuente en el textarea de emergeNotas
    emergeOpciones = new formEmerge("emergeOpciones", "Opciones", false, 3);
    //Componemos el literal HTML para el interior
    var contenidoOpciones = "<label>Tamaño fuente: " +
    "<input type='text' id='tamanyo-fuente-notas' value='' " +
    "size='2' maxlength='2' "+
    "onblur = \"limitaValor(this, 'entero', 6, 48)\" />" +
    "<label><br />" +
    "<label>Fuente: " +
    "<select id='fuente-notas'>" +
    "<option value='Courier New'>Courier New</option>" +
    "<option value='Times New Roman'>Times New Roman</option>" +
    "<option value='Palatino Linotype'>Palatino</option>" +
    "<option value='Arial'>Arial</option>" +
    "<option value='Arial Narrow'>Arial Narrow</option>" +
    "</select>" +
    "<label><br />" +
    "<label>Itálica: " +
    "<input type='checkbox' id='italica-notas' />" +
    "<label><br />" +
    "<label>Negrita: " +
    "<input type='checkbox' id='negrita-notas' />" +
    "<label>";
    //Ponemos ese literal en el interior
    emergeOpciones.nuevoInterior(contenidoOpciones);
    //Activamos el evento al abrir el formulario para que llame a una
    //función auxiliar opcionesNotas(salida) que está en este script pero
    //fuera de este window.onload. Con salida=false toma el estilo de la
    //fuente (tamaño, familia, itálica, negrita) y los pone en los
    //cuadros de emergeOpciones
    emergeOpciones.eventoAbrir = true;
    emergeOpciones.ejecutaEventoAbrir = function(){
        opcionesNotas(false);
    }
    //Activamos los eventos aceptar y aplicar, ambos con la misma
    //función opcionesNotas(salida) pero con salida = true para hacer
    //el proceso contrario: poner las opciones de emergeOpciones en
    //emergeNotas
    emergeOpciones.eventoAceptar = true;
    emergeOpciones.ejecutaEventoAceptar = function(){
        opcionesNotas(true);
    }
    emergeOpciones.eventoAplicar = true;
    emergeOpciones.ejecutaEventoAplicar = function(){
        opcionesNotas(true);
    }

}

Mediante una función auxiliar opcionesNotas(salida) que puede ver en el script de este documento, podemos cambiar esas opciones. Con el argumento salida igual a false recogemos el estilo de la fuente del <textarea> (tamaño, familia, itálica y negrita) y rellenamos el cuadro de opciones al abrir el formulario. Con salida igual a true hacemos la operación inversa cuando pulsamos aceptar o aplicar: ponemos los valores del cuadro de opciones en el estilo de la fuente del <textarea>. En principio no merece extenderse más en esto, pues lo que se pretende es mostrar un ejemplo de uso de los emergentes, más que de las ejecuciones que puedan realizar en una aplicación de uso concreta.

Al componer el literal HTML para el botón interior del emergente notas que llama al método abrir() del emergente opciones, se observa que obtenemos las posiciones offset de esta forma:

"onclick = \"emergeOpciones.abrir('', '', " +
"emergeNotas.form().offsetLeft+emergeNotas.form().offsetWidth, " +
"emergeNotas.form().offsetTop)\" />";    
    

El propósito es abrir las opciones al lado de las notas. Para ello necesitamos los offset o posiciones y medidas actuales o computadas del elemento <form> que supone el emergente de notas. Y es que todo el contenido de un formulario emergente se construye dentro de un <form>. La clase formEmerge dispone del método this.form() que nos devuelve una referencia al elemento <form> sin necesidad de tener que conocer el id para hacer un document.getElementById() por ejemplo. Puede ver más sobre el acceso a los controles del formulario.

Usando un emergente como menú contextual

El menú contextual, en inglés context menu y también llamado contextual, shortcut o pop-up menu, es un menú de acciones que se presenta al usuario según el contexto, normalmente mediante el uso del botón derecho del ratón. Nuestro emergente puede también prestarse a este cometido. Aunque con ciertas limitaciones en cuanto al uso del botón derecho del ratón, pues interacciona con el del navegador cuando presenta su menú contextual. En este ejemplo usaremos el botón izquierdo, es decir, el que se usa para el click. Si se conoce la posibilidad de desactivar la acción del navegador sobre el botón derecho se podría aplicar para conseguir un resultado óptimo (Ver notas siguientes).

En Marzo 2013 he preparado el script menu-context.js para implementar menús contextuales en una página. Aunque no lo incorporo en este ejemplo puede ver cómo usarlo en el tema cómo se hace un menú contextual. Ahí no uso el formulario emergente pues es "demasiado código" para esa tarea. Además puede abrirse usando el botón derecho del ratón.
En Septiembre 2013 he estado actualizando todos los JavaScript para que gestionen también eventos de toque (touch events) y poder ejecutarlos en los móviles. He actualizado este ejemplo modificando la función abreContextual(). Ahora usamos el evento contextmenu lo que nos permite usar el botón derecho del ratón, bloqueando el menú contextual que por defecto sale en el navegador. Aparecerán más abajo códigos tachados que han sido eliminados. Los que tienen fondo azul claro son las nuevas incorporaciones. En el texto las referencias al evento click se deben entender ahora a contextmenu.

En este ejemplo insertamos a continuación un elemento <p class="contextual"> y un <ul class="contextual"> con dos entradas de lista <li>, además de otros elementos HTML en sus interiores (todo encerrado en un DIV con id="contenedor-contextual"). Les hemos puesto bordes a algunos con objeto de probar nuestro menú contextual sobre esos elementos y saber su superficie para hacerle click:

Ejemplo:

Esto es un párrafo P con un elemento SPAN en su interior. Además tenemos este input type="text" y también este input type="button" .

  • Primer LI con un elemento I en su interior.
  • Segundo LI con un elemento EM en su interior.

El nombre de la clase contextual para los elementos <p> y <ul> no es primordialmente para darle estilo, aunque puede servir, sino para luego adjudicarle un evento onclick como veremos. Por ahora diremos que al hacer click sobre esos elementos, o sus hijos, se abre un menú contextual que nos permitirá ver algunas cosas sobre el elemento. Es importante ver que no es necesario etiquetar con la clase contextual a todos los hijos, sino al elemento padre que los contiene, pues el evento onclick se va a heredar a todos sus hijos. De hecho esto podría hacerse en el <body> de un documento y tendríamos el menú contextual para todos los elementos de la página. Este emergente contextual se ha implantado en el window.onload de este documento así:

...
var emergeContextual = null;
...
window.onload = function() {
    ...
    //EJEMPLO DEL FORMULARIO PARA MENÚ CONTEXTUAL ---------------
    //Este es el emergente para el contextual. Se abre con
    //pantalla y sin botones.
    emergeContextual = new formEmerge("emergeContextual", "", true, 0);
    //Desactivamos la barra del título del emergente
    emergeContextual.form("Barra").style.display = "none";
    //Aplicamos un evento a la pantalla para que cuando hagamos click
    //se cierre el contextual
    emergeContextual.form("IDPRE" + "pantalla", true).onclick = cerrarFormularios;
    //Adjudicamos eventos a todos los elementos del documento que sean de
    //la clase "contextual". La función arrayClassName() la hice para
    //IE que no admite getElementsByClassName().
    var elementosContextuales = arrayClassName("contextual");
    for (var i=0; i<elementosContextuales.length; i++){
        elementosContextuales[i].onclick = abreContextual;
    }
    //Adjudicamos evento contextmenu al contenedor que alberga los elementos sobre
    //los que vamos a ejecutar el ejemplo. El evento se transmite del contenedor a 
    //todos sus hijos.
    document.getElementById("contenedor-contextual").oncontextmenu = abreContextual;
}

En primer lugar creamos un emergente emergeContextual con pantalla y sin botones y a continuación hacemos estas tres cosas:

  1. Desactivar la barra superior del emergente con emergeContextual.form("Barra").style.display = "none". El método this.form() nos permite obtener referencias al formulario y sus elementos (ver más en acceso a los controles del formulario).
  2. Aplicar un evento sobre la pantalla para que se desactive con un sólo click: emergeContextual.form("IDPRE" + "pantalla", true).onclick = cerrarFormularios. La pantalla se puede desactivar siempre con un doble click, pero para un menú contextual es usual que cuando pinchemos por fuera del mismo con un único click el menú desaparezca. La función cerrarFormularios() es una global del archivo form-emerge.js donde se encuentra la clase emergeForm que, además de cerrar todos los formularios abiertos, desactiva la pantalla.
  3. Por último hemos de adjudicar eventos onclick a todos los elementos de la clase contextual:
    var elementosContextuales = arrayClassName("contextual");
    for (var i=0; ielementosContextuales.length; i++){
        elementosContextuales[i].onclick = abreContextual;
    }
    //Adjudicamos evento contextmenu al contenedor que alberga los elementos sobe
    //los que vamos a ejecutar el ejemplo. El evento se transmite del contenedor a 
    //todos sus hijos.
    document.getElementById("contenedor-contextual").oncontextmenu = abreContextual;
    

La función arrayClassName es una construcción propia para emular document.getElementsByClassName() que IE no tiene. Simplemente si existe ésta se devuelve la colección de elementos por la clase y si no se devuelve un array con elementos haciendo una búsqueda en el DOM. Por otro lado la función global abreContextual() está en el script del encabezado y tiene el siguiente código:

//En esta variable global se guarda el elemento
//que genera el contextual
var elementoContextual = null;
/* Al abrir el contextual se guarda la referencia
 * al elemento sobre el que se hizo click.
 */
function abreContextual(event){
    var evento = event||window.event;
    var msie = false;
    if (evento.preventDefault){
        evento.preventDefault();
    } else {
        //Para IE8
        evento.returnValue = false;
        msie = true;
    }
    if (msie || (evento.button == 2)){
        //Buscamos el evento con mi función recogeEvento()
        //para unificar diferencias en IE, FF, OP y SA.
        //Actualizamos la referencia elementoContextual 
        //y obtenemos el punto x,y del evento
        var evt = recogeEvento(evento);
        elementoContextual = evt.element;
        var izquierda = evt.x;
        var arriba = evt.y;
        //Seleccionamos el menú que queremos presentar según el
        //contexto. En este ejemplo hacemos una diferenciación para
        //los elementos input.
        var interior = menuGeneral;
        if (elementoContextual.tagName.toLowerCase() == "input"){
            interior += "<hr />" + menuInput;
        }
        //Abrimos el menú contextual
        emergeContextual.abrir(interior, "", izquierda, arriba);
    }
}

Disponemos de la variable global elementoContextual que guarda la referencia del elemento sobre el que hayamos hecho click y abierto el menú. Luego esa variable será utilizada en la función que luego veremos contextual(queHacer) para ejecutar algo. Ese "algo" puede tener o no relación con el elemento sobre el que se hizo click, pero en todo caso ya tenemos la referencia al elemento. Como vemos la referencia se obtiene a partir del elemento que porta el evento. Sin embargo hay diferencias en la forma que actúa Firefox con el resto Internet Explorer, Opera y Safari. Entonces uso una construcción propia recogeEvento(evento) que trata el objeto event devolviendo un objeto Object con las propiedades event, element, x, y que son el mismo evento devuelto, el elemento que lo causó y las coordenadas donde se produjo.

Antes de llamar al emergente emergeContextual que nos va a presentar el menú, hemos de personalizarlo. En nuestro ejemplo hemos dispuesto un menú general para todo tipo de elementos y cuando sean <input> le agregamos una par de entradas para ver sus atributos value y type. Por eso agregamos al menuGeneral el menuInput con una regla <hr> por medio.

Las variables menuGeneral y menuInput contienen literales HTML. Se trata de una relación de vínculos <a> separados por retornos de carro. Podemos separar grupos con la regla <hr>. Esto es un simple ejemplo de aplicación, pero puede servir cualquier otra cosa que ejecute algo en esa entrada de menú.

//Entradas de menú para toda clase de elementos
var menuGeneral = "<a class='a-contextual' " +
"href='javascript: contextual(\"tag\")'>Tag</a><br />" +
"<a class='a-contextual' " +
"href='javascript: contextual(\"dom\")'>Analiza DOM</a><hr />" +
"<a class='a-contextual' " +
"href='javascript: contextual(\"html\")'>Html</a><br />" +
"<a class='a-contextual' "+
"href='javascript: contextual(\"texto\")'>Texto</a>";
//Entradas de menú para elementos <input>
var menuInput = "<a class='a-contextual' " +
"href='javascript: contextual(\"valor\")'>Valor</a><br />" +
"<a class='a-contextual' " +
"href='javascript: contextual(\"tipo\")'>Tipo</a>";
    

La clase a-contextual es para darle estilo, que se encuentra también en el elemento <style> de la cabecera de este documento:


/* Este contenedor-contextual es un ID que le hemos puesto al contenedor que
   alberga los elementos donde vamos a usar el contextual. Por un lado nos
   sirve para adjudicarle el evento contextmenu. Por otro para dar estilo de
   no seleccionable a todo su interior, pues de otra forma en los móviles
   no podremos activar el menú contextual pues aparecerá la utilidad del
   móvil para seleccionar texto.
*/
div#contenedor-contextual {
    -webkit-user-select: none;
    -moz-user-select: none;
    -o-user-select: none;
    -ms-user-select: none;
    user-select: none;
    } 
a.a-contextual {
    padding: 0.1em;
    text-decoration: none;
    font-family: Arial;
    font-size: 0.9em;
    color: black;
    }

a.a-contextual:focus, a.a-contextual:hover, a.a-contextual:active  {
    background-color: rgb(49, 99, 98);
    color: white;
    }

Como vemos se trata de quitarle los decorados del vínculo y que cuando nos posicionemos con el ratón se ponga un fondo azul y letra de color blanco. Por otro lado su atributo href lleva a un código Javascript para ejecutar la función contextual("tipo") que también se encuentra en el script del encabezado de este documento, pero por fuera del window.onload y que será la que finalmente ejecute lo que deseemos:

/* Con esto ejecutamos las entradas del contextual.
 * El argumento queHacer trae uno de los posibles valores
 * para ejecutar una acción de menú.
 */
function contextual(queHacer){
    switch (queHacer){
        //ENTRADAS DE MENÚ GENERAL
        case "tag": {
            //Esto simplemente da un alert sobre el tagName
            alert("Este elemento es un <" +
            elementoContextual.tagName + ">");
            break;
        }
        case "dom": {
            ...ejecuta analizaDOM() (VER NOTA)...
        }
        case "html": {
            ...ejecuta esto...
        }
        case "texto": {
            ...ejecuta esto...
        }
        //ENTRADAS DE MENÚ PARA LOS INPUT
        case "valor": {
            //Esto nos da el atributo value de un input
            alert("Su valor es \"" +
            elementoContextual.value + "\"");
            break;
        }
        case "tipo": {
            //Esto nos da el atributo type de un input
            alert("Su tipo es \"" +
            elementoContextual.type + "\"");
            break;
        }

    }
} 

Esta función global contextual(queHacer) se encarga de ejecutar la acción declarada en los elementos vínculo del menú. Estos son ejemplos particulares que hemos puesto para este caso, pero en otra aplicación aquí habría que poner la ejecución que quisiéramos con cada entrada de menú. De hecho sólo señalamos algunos y otros los obviamos para aclarar el concepto general (puede ver el código de la página y de esa función contextual()). Por ejemplo, pasando "tag" nos dará un mensaje del navegador con el tagName del elemento sobre el que hicimos click.

NOTA sobre analizaDOM(): En una de las entradas de menú se llama a analizaDOM(). Se trata de una función en JavaScript con objeto de practicar detalles sobre el manejo del DOM (Document Object Model, Modelo de Objetos del Documento). Esta función analiza el nombre tag de un elemento, sus hijos, los atributos y también el estilo actual (currentStyle para Internet Explorer y getComputedStyle para Firefox y otros). Aunque no viene al caso explicarlo ahora, puede ver su código fuente.