Menú Dinámico desde JSON

Utilidad: Cuando los menú son administrados con información proveniente de la base de datos, puedes hacer que este sea construido dinamicamente con JavaScrip, a partir de información suministrada con formato JSON. Desahogando así al servidor, delegando esta responsabilidad al cliente.


El siguiente código es el archivo index.html, en el cual se mostrará el menú.

Note que hace referencia a 3 archivos:

También note, que el llamado al archivo menu.css está comentado por ahora (será descomentado más adelante).

El código del menú será costruido dinámicamente en el elemento <nav>, a partir de un arreglo tridimencional recursivo a 4 niveles, con formato JSON, contenido en la función inicio(), ubicada en el archivo javascript del mismo nombre. Esta función es invocada desde el evento onload() del elemento <body>.

index.html

 <!DOCTYPE html>
 <html>
     <head>
         <title>JavaScript & JSON</title>
         <meta http-equiv=Content-Type content="text/html; charset=UTF-8">
         <script src="inicio.js"></script>
         <script src="menu.js"></script>
         <!--link rel="stylesheet" type="text/css" href="menu.css"-->
     </head>
     <body onload='inicio()'>
         <h1>Ej.: Construir Menú (Dinámicamente)...</h1>
         <nav></nav>
     </body>
 </html>


A continuación mostramos el contenido del archivo inicio.js y su función con el mismo nombre.

Inmediatamente declaramos la variable aJSON, se trata de un arreglo con formato JSON. Dicho arreglo contiene 4 arreglos y a su vez, cada uno contiene otro arreglo que significa una opción del menú. Cada opción del menú contiene un identificador único, un respectivo título y una ruta correspondiente. Observe que desde el segúndo nivel en adelante, hay 2 identificadores más. El primero es el identificador único (principal) y el segundo es el padre del primero (tipo recursivo).

Entonces, esta variable aJSON es pasada como parámetro dentro de los paréntesis de la función menu(), la cual es invocada al final de la función inicio().

inicio.js

 function inicio()
 {

     var aJSON = [
         [
             [ "1", "Google"   , "https://www.google.co.ve/" ],
             [ "2", "PHP"      , "#"                         ],
             [ "3", "JavaSript", "#"                         ],
             [ "4", "Data Base", "#"                         ],
             [ "9", "Salir"    , "../"                       ]
         ],
         [
             [ "20", "2", "FDSoil..." , "http://fdsoil.com.ve" ],
             [ "21", "2", "Larave..." , "https://laravel.com/" ],
             [ "22", "2", "Synfony...", "http://symfony.es/"   ],
             [ "30", "3", "JQuery"    , "#"                    ],
             [ "31", "3", "Vue"       , "#"                    ],
             [ "41", "4", "PostgreSQL", "#"                    ]
         ],
         [
             [ "122", "30", "Wikipedia - JQuery ...", "https://es.wikipedia.org/wiki/JQuery" ],
             [ "123", "30", "WebSite - JQuery ..."  , "https://jquery.com/"                  ],
             [ "124", "30", "GitHub - JQuery ..."   , "https://github.com/jquery/jquery"     ],
             [ "119", "31", "Wikipedia - Vue ..."   , "https://en.wikipedia.org/wiki/Vue.js" ],
             [ "118", "31", "WebSite - Vue ..."     , "https://vuejs.org/"                   ],
             [ "120", "31", "GitHub - Vue ..."      , "https://github.com/vuejs"             ],
             [ "126", "41", "Ver 9.6"               , "#"                                    ]
         ],
         [
             [ "63", "126", "Wikipedia - PostgreSQL... ", "https://es.wikipedia.org/wiki/PostgreSQL" ],
             [ "64", "126", "WebSite - PostgreSQL... "  , "https://postgresql.org.es"                ],
             [ "65", "126", "GitHub - PostgreSQL... "   , "https://github.com/postgres/postgres"     ]
         ]
     ];

     menu( aJSON );

 }


El siguiente archivo contiene la función que construye dinámicamente el menú:

menu.js

 function menu(arr)
 {

     this.doA = function(address)
     {
         var oBj = document.createElement("a");
         oBj.setAttribute( "href", address );
         oBj.setAttribute( "target", "_blank" );
         return oBj;
     }

     this.doLiA = function( tNodo, address )
     {
         this.doAtNodo = function( tNodo, address )
         {
             var oBj = doA(address);
             oBj.appendChild( document.createTextNode( tNodo ) );
             return oBj;
         }
         var oBj = document.createElement("li");
         oBj.appendChild( doAtNodo( tNodo, address ) );
         return oBj;
     }

     this.doLiASpan = function( tNodo, address )
     {
         this.doASpantNodo = function( tNodo, address )
         {
             this.doSpand = function(tNodo)
             {
                 var oBj = document.createElement("span");
                 oBj.appendChild( document.createTextNode( tNodo ) );
                 return oBj;
             }
             var oBj = doA(address);
             oBj.appendChild( doSpand( tNodo ) );
             return oBj;
         }
         var oBj = document.createElement("li");
         oBj.appendChild(doASpantNodo( tNodo, address ) );
         return oBj;
     }

     this.hasSon = function( dad, arrSon)
     {
         var resp = false;
         for ( var i = 0; i < arrSon.length; i++ )
             if ( dad == arrSon[i][1] ) {
                 resp = true;
                 break;
             }
             return resp;
     }

     var oUl0 = document.createElement("ul");
     oUl0.id='menu';

     for ( var i = 0; i < arr[0].length; i++ )
         if (!hasSon(arr[0][i][0],arr[1]))
             oUl0.appendChild(doLiA(arr[0][i][1],arr[0][i][2]));
         else {
             var oLi0 = doLiASpan(arr[0][i][1],"#");
             var oUl1 = document.createElement("ul");
             for ( var j = 0; j < arr[1].length; j++ )
                 if ( arr[0][i][0] == arr[1][j][1] ) {
                     if ( !hasSon( arr[1][j][0],arr[2]) )
                         oUl1.appendChild( doLiA(arr[1][j][2], arr[1][j][3]) );
                     else {
                         var oLi1 = doLiASpan( arr[1][j][2], "#" );
                         var oUl2 = document.createElement("ul");
                         for ( var k = 0; k < arr[2].length; k++ )
                             if ( arr[1][j][0] == arr[2][k][1] ) {
                 		if ( !hasSon( arr[2][k][0], arr[3]) )
                                     oUl2.appendChild( doLiA(arr[2][k][2], arr[2][k][3] ) );
                                 else {
                                     var oLi2 = doLiASpan( arr[2][k][2], "#" );
                                     var oUl3 = document.createElement("ul");
                                     for ( var l = 0; l < arr[3].length; l++ )
                                         if ( arr[2][k][0] == arr[3][l][1] )
                                             oUl3.appendChild( doLiA(arr[3][l][2], arr[3][l][3]) );
                                     oLi2.appendChild(oUl3);
                                     oUl2.appendChild(oLi2);
                                 }
                             }
                         oLi1.appendChild(oUl2);
                         oUl1.appendChild(oLi1);
                     }
                 }
             oLi0.appendChild(oUl1);
             oUl0.appendChild(oLi0);
         }

     document.getElementsByTagName("nav")[0].appendChild(oUl0);

 }


He aquí el ejemplo (sin estilo):


El archivo menu.css agrega el estilo, pero antes recordemos descomentar el llamado en el archivo index.html.


 <!--link rel="stylesheet" type="text/css" href="menu.css"-->

menu.css

 #menu
 {
     width: auto;
     margin: 0;
     margin-bottom: -2px;
     padding: 0 0 0 0;
     list-style: none;
     color: #2a3333;
     margin-left: 5px;
     background: #D8D8D8;
     float: left;
 }

 #menu li
 {
     float: left;
     padding: 0 0 0 0;
     position: relative;
     line-height: 0;
 }

 #menu a
 {
     float: left;
     padding: 3.5px 10px;
     color: #2a3333;
     font: bold 12px/25px Arial, Helvetica;
     text-decoration: none;
 }

 #menu li:hover > a
 {
     color: #78132b;
 }

 *html #menu li a:hover /* IE6 */
 {
     color: #78132b;
 }

 #menu li:hover > ul
 {
     display: block;
 }

 #menu ul
 {
     list-style: none;
     margin: 0 0 0 0;
     padding: 0;
     display: none;
     position: absolute;
     top: 32px;
     left: 0;
     z-index: 99999;
     background: #D8D8D8;
 }

 #menu ul ul
 {
     top: 0;
     left: 100%;
 }

 #menu ul li
 {
     float: none;
     margin: 0;
     padding: 0;
     display: block;
 }

 #menu ul a
 {
     padding: 7.5px;
     height: 10px;
     min-width: 150px;
     width: auto;
     height: auto;
     line-height: 1;
     display: block;
     white-space: nowrap;
     float: none;
     text-transform: none;
     font-size: 13px;
 }

 *html #menu ul a /* IE6 */
 {    
     height: 5px;
 }

 *:first-child+html #menu ul a /* IE7 */
 {    
     height: 5px;
 }

 #menu ul a:hover
 {
     background: #D8D8D8;
     color: #78132b;
 }

 #menu ul li:first-child > a
 {
     -moz-border-radius: 5px 5px 0 0;
     border-radius: 5px 5px 0 0;
 }

 #menu ul li:first-child > a:after
 {
     content: '';
     position: absolute;
     left: 30px;
     top: -8px;
     width: 0;
     height: 0;
     border-left: 5px solid transparent;
     border-right: 5px solid transparent;
     border-bottom: 8px solid #777;
 }

 #menu ul ul li:first-child a:after
 {
     left: -8px;
     top: 12px;
     width: 0;
     height: 0;
     border-left: 0;
     border-bottom: 5px solid transparent;
     border-top: 5px solid transparent;
     border-right: 8px solid #777;
 }

 #menu ul li:first-child a:hover:after
 {
     border-bottom-color: #777777;
 }

 #menu ul ul li:first-child a:hover:after
 {
     border-right-color: #777777;
     border-bottom-color: transparent;
 }

 #menu:after
 {
     visibility: hidden;
     display: block;
     font-size: 0;
     content: " ";
     clear: both;
     height: 0;
 }

 * html #menu             { zoom: 1; }
 *:first-child+html #menu { zoom: 1; }


He aquí el ejemplo (con estilo):


Tool developed at revolution, under free software. Copyleft 2017.