Como integrar un menú responsivo hecho en CSS3 a #Genexus


Algo indispensable en nuestras aplicaciones web es el menú, ese componente que permite al usuario navegar por la aplicación de manera rápida y sencilla.
Pero en estos tiempos los usuarios navegan más desde sus smartphones, tablets y dispositivos móviles con pantallas pequeñas, lo cual nos obliga a adaptarnos y crear nuestras aplicaciones responsivas a cualquier tamaño de pantalla, lo que nos lleva a crear un menú el cual también sea responsivo.
En internet podemos encontrar muchos ejemplos de menús responsivos hechos en CSS3.

Menús responsivos CSS3 en Internet

En el siguiente enlace podemos encontrar varios ejemplos de menús responsivoshttp://www.html5xcss3.com/p/responsive-menus-tutorials.html, algunos como los siguientes:





Como integrar el menú en Genexus

Para este ejemplo utilizaremos el siguiente menú:
Lo encontraremos en el siguiente enlacehttp://tympanus.net/codrops/2013/05/08/responsive-retina-ready-menu/, la pagina nos muestra 2 botones, uno es para ver una demostración del menú, y la otra para descargar su código, descargamos el código.
Se nos descargara un archivo .zip, lo extraemos y nos descomprimirá las siguientes carpetas
Ahora copiamos las carpetas, css, fonts y js las cuales contienen los archivos necesarios para que funcione el menú, a nuestra carpeta web de nuestra aplicación:
En nuestra aplicación Genexus crearemos un nuevo Web Component llamado WCMenuResponsivo
En el Web Form agregamos un TextBlock llamado Contenedor con la propiedad Format = Raw HTML:
En el evento start llamamos a una subrutina que llena la variable &Script (LongVarchar) y a continuación se la asignamos al contenedor por medio del método caption:
En la subrutina ‘inicializar’ le concatenaremos las etiquetas del menú que encontraremos en el archivo index.html el cual venia en el arhivo .zip que descargamos, solo copiaremos el contenido de la etiqueta
Sub 'inicializar'
&Script = '<div class="main clearfix">'
+'<nav id="menu" class="nav">'
+'<ul>'
+'<li>'
+'<a href="#">'
+'<span class="icon">'
+'<i aria-hidden="true" class="icon-home"></i>'
+'</span>'
+'<span>Home</span>'
+'</a>'
+'</li>'
+'<li>'
+'<a href="#">'
+'<span class="icon"> '
+'<i aria-hidden="true" class="icon-services"></i>'
+'</span>'
+'<span>Services</span>'
+'</a>'
+'</li>'
+'<li>'
+'<a href="#">'
+'<span class="icon">'
+'<i aria-hidden="true" class="icon-portfolio"></i>'
+'</span>'
+'<span>Portfolio</span>'
+'</a>'
+'</li>'
+'<li>'
+'<a href="#">'
+'<span class="icon">'
+'<i aria-hidden="true" class="icon-blog"></i>'
+'</span>'
+'<span>Blog</span>'
+'</a>'
+'</li>'
+'<li>'
+'<a href="#">'
+'<span class="icon">'
+'<i aria-hidden="true" class="icon-team"></i>'
+'</span>'
+'<span>The team</span>'
+'</a>'
+'</li>'
+'<li>'
+'<a href="#">'
+'<span class="icon">'
+'<i aria-hidden="true" class="icon-contact"></i>'
+'</span>'
+'<span>Contact</span>'
+'</a>'
+'</li>'
+'</ul>'
+'</nav>'
+'</div>'   
+ 'cambiarClase();'
EndSub
Si se dan cuenta al final de la etiqueta
tenemos la siguiente línea// , lo que hace esta línea es llamar a una función la cual tiene el contenido de la etiqueta script que encontramos en el archivo index.html:
Este código lo copiamos en un archivo que llamaremos CambiaClase.js y el cual copiaremos en la carpeta js dentro de nuestra carpeta web de nuestro modelo.
El código es el siguiente:
function cambiarClase() {
//  The function to change the class
var changeClass = function (r,className1,className2) {
var regex = new RegExp(“(?:^|\\s+)” + className1 + “(?:\\s+|$)”);
if( regex.test(r.className) ) {
r.className = r.className.replace(regex,’ ‘+className2+’ ‘);
}
else{
r.className = r.className.replace(new RegExp(“(?:^|\\s+)” + className2 + “(?:\\s+|$)”),’ ‘+className1+’ ‘);
}
return r.className;
};
//  Creating our button in JS for smaller screens
var menuElements = document.getElementById(‘menu’);
menuElements.insertAdjacentHTML(‘afterBegin’,'<button type=”button” id=”menutoggle” class=”navtoogle” aria-hidden=”true”><i aria-hidden=”true” class=”icon-menu”> </i> Menu</button>’);
//  Toggle the class on click to show / hide the menu
document.getElementById(‘menutoggle’).onclick = function() {
changeClass(this, ‘navtoogle active’, ‘navtoogle’);
}
document.onclick = function(e) {
var mobileButton = document.getElementById(‘menutoggle’),
buttonStyle =  mobileButton.currentStyle ? mobileButton.currentStyle.display : getComputedStyle(mobileButton, null).display;
if(buttonStyle === ‘block’ && e.target !== mobileButton && new RegExp(‘ ‘ + ‘active’ + ‘ ‘).test(‘ ‘ + mobileButton.className + ‘ ‘)) {
changeClass(mobileButton, ‘navtoogle active’, ‘navtoogle’);
}
}
}

Agregar el menú a la Master Page

Ahora vamos a agregar el Web Component que creamos a nuestra Master Page, abrimos la master page RwdMasterPage, y agregamos en el start las siguientes líneas:

//Agregamos los .css que utiliza el menuform.HeaderRawHTML += ‘<link rel=”stylesheet” type=”text/css” href=”css/default.css” />’form.HeaderRawHTML += ‘<link rel=”stylesheet” type=”text/css” href=”css/component.css” />’//Agregamos el .js que utiliza el menuform.JScriptSrc.Add(“js/modernizr.custom.js”)//Agregamos el .js que creamos anteriormente 
form.JScriptSrc.Add(“js/CambiaClase.js”)
 En el evento Refresh asignamos al objeto WebComponent el componente WCMenuResponsivo



Para finalizar creamos un Wep Panel vacio al cual le asignamos la master page que acabamos de editar y ejecutamos:
Resolución 1080


Resolución 800×1280


Resolución 360×640


Espero les sea de ayuda y lo compartan.
Nota: Para cargar un menú de manera recursiva y usando la seguridad del GAM, lo pueden ver en la esta publicación http://jenexus.blogspot.mx/2016/09/menu-recursivo-con-seguridad-del-gam-en.html

Jesús Rodríguez

Consultor Genexus Senior - Scrum Master, Emprendedor, siguiendo mis sueños.

22 comentarios:

  1. Hola,
    Copie todo tal cual el tutorial pero no he tenido exito:

    One Content Placeholder control is needed in master pages

    ResponderBorrar
    Respuestas
    1. EStimado, Todos los master page deben tener un Content Place Holder

      Borrar
  2. Estimado,

    La Resolución 360×640 no esta funcionando, GX evo3 U10

    ResponderBorrar
  3. Amigo,

    En Genexus 15 me aparece el menu y al final el texto "cambiarClase();", copie y pegue el codigo de tu post.

    Saludos

    ResponderBorrar
    Respuestas
    1. Me parece que al copiar directamente del post se pierden algunos caracteres que pueden estar provocando que no tome en cuenta el texto cambiarClase, asi que te sugiero transcribir y no copiar el codigo

      Borrar
  4. menuform que tipo de componente es es un textbox o una Variable puede ayudarme

    ResponderBorrar
    Respuestas
    1. Hola, no es menúform es solo form. Por error se juntaron las palabras

      Borrar
  5. exelente ayuda quisiera implementar otro menu tiene algunos elementos mas
    no podrias ayudar en esta implementacion talvez dandonos algunos tips
    los menu que nos gustaria usar son
    https://tympanus.net/codrops/2013/07/30/google-nexus-website-menu/
    o
    https://tympanus.net/codrops/2013/08/13/multi-level-push-menu/

    ResponderBorrar
  6. buenas noches, donde cambio en genexus los iconos y como cambio los colores de cada boton ?

    ResponderBorrar
  7. Ademas cuando se hace pequeño desaparece. no se ve los "= menu""

    ResponderBorrar
  8. Estoy intentando utilizar el menú http://multi-level-push-menu.make.rs/, pero no funciona como Web Component, si lo hago como WebPanel incluyendo los css y js en el mismo WP funciona sin problemas, cuando lo convierto WComponent no se despliega correctamente, si incluyo los css y js en el masterpage no despliega nada. Es algo de la forma en que carga los css y js pero no se exactamente como resolverlo.

    Gracias y Saludos

    ResponderBorrar
  9. Hola, antes que nada felicitaciones por el tremendo aporte, y respecto al codigo genexus en cuestión, lo tendrías en algún blog de notas o algo por el estilo? porque evidentemente los caracteres se concatenan en el blog, desde ya saludos!

    ResponderBorrar
  10. Gracias por la idea, pero necesitaba algo con el menu GAM, gracias a esta informacion al fin logre hacerlo dinamico.

    Mas adelante posteare las rutinas y procedimientos en un video, primero tengo que elaborarlo para youtube

    ResponderBorrar
  11. Para los que tienen problemas al visualizar el menú en resolución pequeña (desaparece o les queda en blanco).

    El error es porque no se esta invocando la función CambiarClase", la pone como un texto al final del Menú, solo hay que hacer lo siguiente:

    Al generar el &Script, solo agregar dos tags, uno arriba y otro abajo de la sentencia de llamada como sigue:

    script y /script

    ResponderBorrar
  12. ESTO me funciona perfectamente, me abre el menu, y todo bien, ahora la pregunta que tengo es como llamo a un webpanel desde la opcon del menu resposive. como hago el call a un webpanel desde el menu. ayudeneme por favor ejemplo

    ResponderBorrar
  13. En la variable script donde escribes las etiquetas html del menu, busca la siguiente etiqueta a href="#" y ahi en lugar de eso, escribe a href="'+NombreWebPanel.Link+'"

    ResponderBorrar
  14. Jesús buen día, y gracias por tu aporte, podría preguntarte en la parte final del código del Refresh:a que te refieres con COmponent1?
    Component1.object=WCMenuResponsivo.Create()

    ResponderBorrar
    Respuestas
    1. Tengo la misma duda.. no se a que hace mención el Component1.Object

      Borrar
  15. Buen día, como puedo hacer para ingresar datos a través de un input y poder recibirlo en genexus?

    ResponderBorrar
  16. Tengo una duda, implementé otro tipo de menú pero al hacer la llamada a los objetos genexus pareciera que no conviven los códigos al mismo nivel, los objetos genexus quedan por encima del menú y no deja tener interacción al querer pasar a otra opción, alguna idea de por qué se da este problema.

    ResponderBorrar