15 - Cargar un control de tipo select


Confeccionaremos un problema que contenga dos controles de tipo select. En el primero almacenaremos una lista de carreras de estudio ("Analista de Sistemas","Telecomunicaciones" y "WebMaster")

Cuando se seleccione una carrera enviaremos una petición al servidor para que retorne todas las materias que tiene esa carrera y procederemos a la carga del segundo select.

El archivo HTML es el siguiente (pagina1.html):

<script src="funciones.js" language="JavaScript"></script>
</head>
<body>
<h1>Prueba de cargar un control de tipo select recuperando datos del servidor 
mediante AJAX</h1>
Seleccione la carrera:
<select id="carreras" name="carreras">
<option value="0">Seleccionar....</option>
<option value="1">Analista de sistemas</option>
<option value="2">Telecomunicaciones</option>
<option value="3">WebMaster</option>
</select><span id="espera"></span><br>
Materias de la carrera:
<select id="materias" name="materias">
</select><br>
</body>
</html>

Luego el archivo que contiene las funciones de JavaScript (funciones.js) es:

addEvent(window,'load',inicializarEventos,false);

function inicializarEventos()
{
  var select1=document.getElementById('carreras');
  addEvent(select1,'change',mostrarMaterias,false);
}

var conexion1;
function mostrarMaterias(e) 
{
  var codigo=document.getElementById('carreras').value;
  if (codigo!=0)
  {
    conexion1=crearXMLHttpRequest();
    conexion1.onreadystatechange = procesarEventos;
    conexion1.open('GET','pagina1.php?cod='+codigo, true);
    conexion1.send(null);
  }
  else
  {
    var select2=document.getElementById('materias');
    select2.options.length=0;
  }
}

function procesarEventos()
{
  if(conexion1.readyState == 4)
  {
    var d=document.getElementById('espera');
    d.innerHTML = '';
    var xml = conexion1.responseXML;
    var pals=xml.getElementsByTagName('materia');
    var select2=document.getElementById('materias');
    select2.options.length=0;
    for(f=0;f<pals.length;f++)
    {
      var op=document.createElement('option');
      var texto=document.createTextNode(pals[f].firstChild.nodeValue);
      op.appendChild(texto);
      select2.appendChild(op);
    } 
  } 
  else 
  {
    var d=document.getElementById('espera');
    d.innerHTML = '<img src="../cargando.gif">';  }
}


//***************************************
//Funciones comunes a todos los problemas
//***************************************
function addEvent(elemento,nomevento,funcion,captura)
{
  if (elemento.attachEvent)
  {
    elemento.attachEvent('on'+nomevento,funcion);
    return true;
  }
  else  
    if (elemento.addEventListener)
    {
      elemento.addEventListener(nomevento,funcion,captura);
      return true;
    }
    else
      return false;
}

function crearXMLHttpRequest() 
{
  var xmlHttp=null;
  if (window.ActiveXObject) 
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  else 
    if (window.XMLHttpRequest) 
      xmlHttp = new XMLHttpRequest();
  return xmlHttp;
}

En la primer función que se ejecuta luego de haberse cargado completamente la página definimos el evento change para el primer select:

  var select1=document.getElementById('carreras');
  addEvent(select1,'change',mostrarMaterias,false);

Es decir cuando hagamos la selección de un item del primer select se dispara la función mostrarMaterias.

La función mostrar materias:

function mostrarMaterias(e) 
{
  var codigo=document.getElementById('carreras').value;
  if (codigo!=0)
  {
    conexion1=crearXMLHttpRequest()
    conexion1.onreadystatechange = procesarEventos;
    conexion1.open('GET','pagina1.php?cod='+codigo, true);
    conexion1.send(null);
  }
  else
  {
    var select2=document.getElementById('materias');
    select2.options.length=0;
  }
}

Rescata el valor del primer select (es decir donde estan almacenadas los nombres de carreras. Si está seleccionada procede a crear un objeto de tipo XMLHttpRequest y le pasa como parámetro el código de la carrera respectiva.

En caso de seleccionar el primer item del select (contiene el texto "Seleccionar....") procedemos a borrar el contenido del segundo select.

La función procesarEventos:

function procesarEventos()
{
  if(conexion1.readyState == 4)
  {
    var d=document.getElementById('espera');
    d.innerHTML = '';
    var xml = conexion1.responseXML;
    var pals=xml.getElementsByTagName('materia');
    var select2=document.getElementById('materias');
    select2.options.length=0;
    for(f=0;f<pals.length;f++)
    {
      var op=document.createElement('option');
      var texto=document.createTextNode(pals[f].firstChild.nodeValue);
      op.appendChild(texto);
      select2.appendChild(op);
    } 
  } 
  else 
  {
    var d=document.getElementById('espera');
    d.innerHTML = '<img src="../cargando.gif">';  
  }
}

Rescata el contenido del archivo XML retornado del servidor:

    var xml = conexion1.responseXML;

Como sabemos el archivo XML contiene un conjunto de materias:

    var pals=xml.getElementsByTagName('materia');

Mediante un for las rescatamos y las agregamos al segundo select:

    for(f=0;f<pals.length;f++)
    {
      var op=document.createElement('option');
      var texto=document.createTextNode(pals[f].firstChild.nodeValue);
      op.appendChild(texto);
      select2.appendChild(op);
    } 

Nos queda el programa que se ejecuta en el servidor para generar el archivo XML con las materias de la carrera seleccionada por el visitante (para facilitar el problema no hemos dispuesto esta información en una base de datos.

pagina1.php

<?php
$car=$_REQUEST['cod'];
if ($car==1)
{
  $materias=array('Programacion I','Analisis Matematico',
                  'Estructura de las Organizaciones','Etica Profesional');
}
if ($car==2)
{
  $materias=array('Fundamentos de Fisica','Analisis Matematico 1',
                  'Ingles Tecnico I','Sistemas de Comunicaciones I
');
}
if ($car==3)
{
  $materias=array('Informatica I','Multimedia I','Bases de Datos');
}


$xml="<?xml version=\"1.0\"?>\n";
$xml.="<materias>\n";
for($f=0;$f<count($materias);$f++)
{
  $xml.="<materia>".$materias[$f]."</materia>\n";
}
$xml.="</materias>\n";
header('Content-Type: text/xml');
echo $xml;
?>

Según el código de carrera se genera un vector $materias con todas las materias de esa carrera.

Luego generamos la estructura del archivo XML respectivo y disponemos en la cabecera de la petición que se trata de un archivo XML:

header('Content-Type: text/xml');
echo $xml;