Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > PHP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-01-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Ajax.class.js - Sencilla forma de hacer peticiones HTTP en segundo plano

Hola,

Escribí hace tiempo una sencilla clase en JavaScript para tratar con el objeto famoso XmlHttpRequest. Es unan sencilla clase porque no pretende ir muy allá, y, sin embargo, llevo un par de días añadiendo y quitando alguna que otra cosa.

El caso es que he pensado que acaso vosotros podéis decir algo al respecto: que sobra algo, que podría añadírsele tal o cual cosa, en fin, lo que gustéis. A continuación copio el código de la clase JavaScript.

El código HTML, CSS, JS y su "funcionamiento" puede verse aquí: http://dec.clubdelphi.com/ajax.class.js/

Puede descargarse todo el código fuente (incluído PHP) desde aquí: http://dec.clubdelphi.com/ajax.class...x.class.js.zip

Código PHP:
/**
 * Sencilla clase para manejarse con el objeto XmlHttpRequest
 * de modo que podamos hacer peticiones HTTP Get y HTTP Post.
 * 
 * @author dec
 */
var Ajax =
{
    
/**
     * Realiza una simple petición HTTP Get. Este método permite determinar
     * una función que se ejecutará según progrese la petición HTTP, y otra
     * función que se ejecutará cuando dicha petición HTTP se complete.
     * 
     * @param {string} url
     * @param {string} destino
     * @param {function} funcProgreso
     * @param {function} funcFinal
     */
  
Get:function(url,destino,funcProgreso,funcFinal){                
      return 
this.HttpRequest(url,destino,'','get',funcProgreso,funcFinal);    
    },

  
/**
   * Igual que "Get", salvo que la petición es HTTP Post.
   * 
     * @param {string} url
     * @param {string} destino
     * @param {function} funcProgreso
     * @param {function} funcFinal
     */
    
Post:function(url,destino,funcProgreso,funcFinal){                
      return 
this.HttpRequest(url,destino,'','post',funcProgreso,funcFinal);    
    },
    
    
/**
     * Similar al método "Get" salvo que en este caso ha de incluirse la query
     * que ha de llevar consigo la petición HTTP Get.
     * 
     * @param {string} url
     * @param {string} destino
     * @param {string} query
     * @param {function} funcProgreso
     * @param {function} funcFinal
     */
    
GetQuery:function(url,destino,query,funcProgreso,funcFinal){                
      return 
this.HttpRequest(url,destino,query,'get',funcProgreso,funcFinal);    
    },

    
/**
     * Igual que "GetQuery", salvo que la petición es HTTP Post.
     * 
     * @param {string} url
     * @param {string} destino
     * @param {string} query
     * @param {function} funcProgreso
     * @param {function} funcFinal
     */
    
PostQuery:function(url,destino,query,funcProgreso,funcFinal){                
      return 
this.HttpRequest(url,destino,query,'post',funcProgreso,funcFinal);    
    },

  
/**
   * Este método se encarga de la creación del objeto XmlHttpRequest y de asig-
   * nar a este las propiedades oportunas y de llamar a los métodos correspon-
   * dientes. Podría considerarse este método como privado, en el sentido de
   * que para usar esta clase bastan los métodos anteriores.
   * 
   * @param {string} url
   * @param {string} idDestino
   * @param {string} query
   * @param {string} metodo
   * @param {function} funcProgreso
   * @param {function} funcFinal
   */
  
HttpRequest:function(url,idDestino,query,metodo,funcProgreso,funcFinal){
    
// Instanciamos un objeto XmlHttpRequest         
    
var request this.XmlHttp();
        
    
// Nos hacemos con un enlace al elemento de destino
    
var destino document.getElementById(idDestino);        
        
    
/* Comprobamos que contamos con un objeto XmlHttpRequest
     * y que también está disponible el elemento de destino.
     * De no ser así no hay para qué seguir...
     */
    
if (!request || !destino){ return false; }
    
    
/* Vamos a preparar la función "al vuelo" que se va a encargar
     * de "escuchar" el evento "onreadystatechange" del objeto Xml-
     * HttpRequest.
     */ 
        
request.onreadystatechange = function(){
            
            
/* "readyState = 1" con la tarea en progreso.
             * Si hay alguna función para tal fin la llamamos.
             */
            
if(request.readyState == 1){
              if(
funcProgreso) { funcProgreso(destino); }
          }
            
      
/* La propiedad "readyState" del objeto "XmlHttpRequest" nos
       * indica que la petición HTTP terminó de realizarse...
       */
      
if(request.readyState == 4){
                
                
/* Si contamos con una función para que esté atenta al final
                 * de la tarea la llamamos a continuación.
                 */
                
if(funcFinal) { funcFinal(request.status,destino); }
                
        
/* En este caso queda comprobar que el código de la propiedad
         * "status" del objeto XmlHttpRequest valga 200. Se trata del
         * código de resultado HTTP que indica que la petición se resol-
         * vió correctamente, esto es, que tenemos el recurso solicitado
         */
        
if (request.status == 200)
          
/* En este caso no nos quedaría sino escribir la respuesta de
           * la petición en el elemento HTML de destino. Ni más ni menos.
           */
          
destino.innerHTML request.responseText;
      }
    }        
    
// Comprobamos que el método de la petición HTTP es "get"
    
if(metodo.toLowerCase() === 'get') {    
      
/* Si es así preparamos la petición HTTP utilizando el método
       * "open" del objeto XmlHttpRequest. Nótese cómo indicamos primero
       * el método a utilizar, a continuación proporcionamos la URL junto
       * con la "query", y por último indicamos que la petición se realize
       * en segundo plano, es decir asíncronamente.
       */
      
request.open(metodourl+"?"+querytrue);
      
// Preparada la petición, no queda sino enviarla.
      
request.send(null);
    } 
    
// Si el método de la petición HTTP no es "get" ha de ser "post"
    
else if(metodo.toLowerCase() === 'post') {
      
/* Y en este caso los parámetros para el método "open" son los mismos,
       * excepto en lo que toca a la "query", que no va junto a la URL ahora
       */ 
      
request.open(metodourltrue);
      
/* Añadimos la cabecera HTTP que hará que la petición sea tratada de la
       * forma que nos interesa, esto es vía POST. Nótese que si el método es
       * Get no hace falta añadir cabecera alguna.
       */
      
request.setRequestHeader('Content-Type',
       
'application/x-www-form-urlencoded');
      
/* Y por último enviamos realmente la petición con el mismo método
       * "send" de antes, sólo que ahora pasamos como parámetro la "query".
       */
      
request.send(query);
    }
    return 
true;
  },

  
/**
   * Este método es privado. Lo usamos en el método anterior "HttpRequest"
   * para lograr una instancia del objeto XmlHttpRequest. Como puede verse
   * lo "intentamos" de varias formas, teniendo en cuenta que distintos na-
   * vegadores exponen dicho objeto de distinto modo.
   * 
   * Cuando uno de los intentos frutúe no hará falta continuar, y, en caso
   * de que los tres intentos fallen este método se limita a devolver "null".
   */
  
XmlHttp:function(){
    try { return new 
XMLHttpRequest();                   } catch(e) {}
    try { return new 
ActiveXObject('Msxml2.XMLHTTP');    } catch(e) {}
    try { return new 
ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
    return 
null;
  }
}; 
Ya sabéis que aunque el código fuente anterior es JavaScript aunque se incluya entre etiquetas PHP para resaltarlo mejor.

Ojo que la clase no pretende ser completa, en el sentido de aprovechar al máximo el objeto XmlHttpRequest. Se trata, al contrario, de conseguir una forma muy sencilla de usar dicho objeto, aunque nos perdamos algunas de sus características.

Una cosa que puedo decir ya que le falta a la clase Ajax (je) es que no "avisa" del progreso de la tarea. Es decir, que no sé muy bien cómo enfocar este tema. Por otro lado está el caso de que la tarea (petición HTTP) falle. Tampoco ante esto me parece muy claro el comportamiento de la clase.

Pero, en fin. Yo lo dejo ahí que parecía que no podía dejar de hacerlo. No os veáis obligados a comentar ni a decir ni a dejar de decir. Al fin y al cabo es un poco de código el que he puesto en este Hilo, por si le puede servir a alguien, por si alguien quiere comentar algo, pero, no pretendo ir mucho más allá.
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 10-01-2007 a las 17:12:34.
Responder Con Cita
  #2  
Antiguo 07-01-2007
Avatar de Emilio
*Emilio* Emilio is offline
Capo
 
Registrado: may 2003
Ubicación: Palma de Mallorca
Posts: 2.635
Poder: 10
Emilio Va por buen camino
Cita:
Empezado por dec
No os veáis obligados a comentar ni a decir ni a dejar de decir.
Hombre Dec, creo yo que ya que te has tomado la molestia, precisamente estaría bien que fueses tú el que comentase el código, puede ser tal vez evidente pero tal vez para mucha gente no lo sea.
__________________
Saludos
Emilio
Responder Con Cita
  #3  
Antiguo 07-01-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Eso está hecho. Si no lo hize antes es porque pensé que era acaso mejor así, sin comentarios, pero, tienes razón, y además no vendrá mal. Lo comento y lo subo comentado y edito el mensaje y actualizo el archivo Zip de marras en unos momentos...
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #4  
Antiguo 09-01-2007
|NoName| |NoName| is offline
Miembro
 
Registrado: ene 2007
Posts: 31
Poder: 0
|NoName| Va por buen camino
Una consulta dec, como se hace para capturar con tu libreria los valores de uno o mas inputs utilizando el metodo POST?
Responder Con Cita
  #5  
Antiguo 09-01-2007
[kayetano] kayetano is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Elche
Posts: 644
Poder: 21
kayetano Va por buen camino
Hola

Buen trabajo dec.
__________________
Salu2
KAYETANO

Cómo hacer preguntas de manera inteligente
Responder Con Cita
  #6  
Antiguo 10-01-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Veo muy bien la clase. En particular me gustan los "eventos" para el progreso y el final de la operación. Si no te parece mal, creo que puedo complementar tu clase con mi función parseForm que toma como parámetro un formulario HTML y devuelve el query que requiere tu método HttpRequest (o casi). Hace tiempo que no lo reviso y me parece que faltan cosas, pero ahí está la idea.

Primero, tenemos la clase HttpParams que básicamente es una lista de parámetros y valores:

Código PHP:
/**************************************************************************

  Clase HttpParams

  Almacena pares [key, value] para ser enviados en una petición HTTP

***************************************************************************/

function HttpParams()
{
  
this.items = new Array();
}

// Agrega un par a la lista
//
HttpParams.prototype.add = function(keyvalue)
{
  
this.items[this.items.length] = [keyvalue];
}

// Construye la cadena a ser enviada
//
HttpParams.prototype.getQueryString = function()
{
  var 
result '';

  for (var 
0this.items.lengthi++)
  {
    var 
item this.items[i];

    if (
result)
    {
      
result += '&';
    }

    
result += item[0] + '=' item[1];
  }

  return 
encodeURI(result);

El método getQuery es el que regresa la cadena ya lista para ser enviada por Ajax.

La función parseForm:

Código PHP:
/**************************************************************************

  Función parseForm
  
  Extrae la información de un formulario y la coloca en un objeto HttpParams

**************************************************************************/

function parseForm(form)
{
  var 
elements form.elements;
  var 
params = new HttpParams();
  var 
element;

  for (var 
0elements.lengthi++)
  {
    
element elements.item(i);

    if (!
element.name)
    {
      continue;
    }

    switch (
element.type.toLowerCase())
    {
      case 
'text': case 'password': case 'hidden': case 'textarea': case 'button':
        
params.add(element.nameelement.value);
        break;

      case 
'select-one':
        if (
element.value)
        {
          
params.add(element.nameelement.value);
        }
        break;

      case 
'select-multiple':
        
options element.options;

        for (
0options.lengthj++)
        {
          
option options.item(j);

          if (
option.selected)
          {
            
params.add(element.nameoption.value);
          }
        }
        break;

      case 
'radio': case 'checkbox':
        if (
element.checked)
        {
          
params.add(element.nameelement.value);
        }
        break;
    }
  }

  return 
params;

Un ejemplo de uso está aquí, en donde los datos del formulario a la izquierda se envían vía la clase de dec. El script php que procesa los resultados, simplemente muestra los valores.

// Saludos
Responder Con Cita
  #7  
Antiguo 10-01-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Cita:
Empezado por |NoName|
Una consulta dec, como se hace para capturar con tu libreria los valores de uno o mas inputs utilizando el metodo POST?
Pues Román puede que te haya dado ya una idea bastante completa de cómo lograrlo. En realidad lo que se pasa en el "query" son pares de claves/valor. En el ejemplo se utiliza sólo un par, pero, en la práctica pueden ser los que te sean precisos.

Respecto de la clase de marras... no sé. Al cabo se sale de madre. Si la intención era que no fuera menester utilizar muchos parámetros en los métodos "más completos", lo cierto es que no se consigue, puesto que al cabo hay que pasar hasta seis parámetros...

Lo cierto es que intenté limitar estos pasando a una sola función el objeto "request", y que fuera dicha función la que se encargara de completar la tarea, comprobando el "readyState" y el "status". Sin embago esto no funciona. No me pregunten porqué, pero, no funciona. Y el caso es que creo recordar haber intentado lo mismo hace tiempo... con el mismo nulo resultado.

No sé. Al cabo creo que lo suyo es tener más o menos claro cómo funciona el objeto "XmlHttpRequest", formar una clase básica para utilizarlo, y, a partir de ahí, ya saben, cada proyecto es un mundo...

En fin. Que creo que la clase es un éxito sólo relativo y quedan no pocos flecos por ahí que no convencen demasiado. Lo que propone Román es muy interesante, desde luego, y puede que en algunos casos fuera muy curioso hacer las cosas de ese modo: mandando todo el formulario en la petición HTTP y a partir de ahí obrar.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #8  
Antiguo 10-01-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por dec
Lo cierto es que intenté limitar estos pasando a una sola función el objeto "request", y que fuera dicha función la que se encargara de completar la tarea, comprobando el "readyState" y el "status". Sin embago esto no funciona. No me pregunten porqué, pero, no funciona. Y el caso es que creo recordar haber intentado lo mismo hace tiempo... con el mismo nulo resultado.
Me gustaría que detallaras más a ver si podemos ver por donde está el problema. Lo comento porque javascript es todo un mundo muy extraño. Sin ir más lejos, usas en tu clase (creo que variable es más adecuado) una notación identificador:function que yo jamás había visto, y eso que no estoy en cero en js. El caso es que en la clase Ajax que hice alguna vez, el "evento" de finalización (yo no tenía el de progreso), en lugar de pasarlo como parámetro de una función, lo asignaba como "propiedad" de la clase misma y eso generó algunos problemas porque this no es lo mismo here and there, .

En cuanto a lo que mencionas de muchos parámetros pues de cualquier manera has de pasarle información. Una forma de hacerlo es con parámetros y otra con propiedades del objeto, y no estoy seguro cual pueda ser más práctica.

// Saludos
Responder Con Cita
  #9  
Antiguo 11-01-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

A mí se me hace más práctico utilizar parámetros de una función. ¿Porqué? Bueno. Quizás porque cuando he venido utilizando JavaScript lo he hecho mediante PHP, y, bueno, quizás se me hace más sencillo algo como esto:

Código PHP:
echo '<a onclick="Funcion(parametros);" href="#" title="Muestra el total">Total</a>'
Sin embargo, en la práctica el "Funcion(parametros)" es una odisea, a poco que estos parámetros sean unos pocos... uno puede terminar desquiciado con las comillas, por ejemplo.

Ahora mismo acabo de dejar el asunto como sigue: cuatro funciones o métodos; todos ellos incluyen la posibilidad de indicar una función que muestre el progreso de la tarea y otra función que esté atenta al final de la misma.

En los dos primeros se asume el método a utilizar, de modo que no hace falta pasarlo como parámetro, y también se asume que la petición "GET" o "POST" no tendrá "query" alguna, por lo que tampoco hace falta pasar ese parámetro.

Lo siguiente es real y forma parte del ejemplo de la clase/variable/lo que sea:

Código PHP:
<a onclick="Ajax.Get('hora-actual.php', 'destino', ProgresoPeticionHttp, FinalPeticionHttp);" href="#" title="Get">Get</a
Cuatro parámetros: el Script receptor, el ID del elemento destino de la misma, la función para el progreso y la función para el final de la tarea.

Lo mismo para el método "Post", es decir:

Código PHP:
<a onclick="Ajax.Post('hora-actual.php', 'destino', ProgresoPeticionHttp, FinalPeticionHttp);" href="#" title="Get">Get</a
Y quedan dos métodos más, los cuales asumen vuelven a asumir el método a utilizar: se cuenta con un método para "get" y otro para "post". Estos dos métodos, sin embargo, requieren que se especifique la "query" a utilizar. Puede llamárseles así:

Código PHP:
<a onclick="Ajax.GetQuery('clave-valor.php', 'destino', 'clave=valor', ProgresoPeticionHttp, FinalPeticionHttp);" href="#" title="GetQuery">GetQuery</a
Son cinco parámetros, pero, en fin, en menos de momento no he sabido dejarlo. He quitado del medio los "Get" y los "Post" que únicamente tenían dos parámetros: el Script de la petición y el ID del elemento destino, puesto que dejaban fuera el progreso y el final de la tarea, y esto no creo que en una aplicación "real" tenga mucho sentido.

Respecto de la notación que puedes ver Román... yo no tengo mucha idea de JavaScript, no nos vamos a engañar, sin embargo, en algún sitio la ví y comenzé a utilizarla... comprendo que tú usas otra que también me consta que se utiliza... y que yo no uso porque me parece más liosa, sin duda por mi ignorancia.

PD. El ejemplo de todo esto sigue pudiéndose ver en: http://dec.clubdelphi.com/ajax.class.js/

Notar que el progreso de la tarea en realidad se fuerza usando la función "sleep" de PHP. En realidad las peticiones son tan sencillas y ocupan tan poco que no requieren prácticamente tiempo, pero, entonces no se vería "el progreso" tal como se vería en situaciones más reales.

PD2: Me dio por buscar si había forma de pasar un Array de PHP a JavaScript... por aquello de pasar un parámetro únicamente que los contuviera a todos... pero, aunque ví que había algo ya por ahí no quise ir más allá. Creo que con lo que hay ahora mismo podrían ya hacerse cosas...
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 11-01-2007 a las 01:32:29.
Responder Con Cita
  #10  
Antiguo 11-01-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por dec
Me dio por buscar si había forma de pasar un Array de PHP a JavaScript.
¿Qué entenderías por pasar algo de php a js?

¿O será que te refieres a algo como JSON? En el Sofa Naranja puedes ver un ejemplo del "paso" del array.

Por cierto, ¿qué hay de esto?

Cita:
Empezado por roman
Me gustaría que detallaras más a ver si podemos ver por donde está el problema.
// Saludos
Responder Con Cita
  #11  
Antiguo 11-01-2007
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Cita:
Empezado por Román
¿Qué entenderías por pasar algo de php a js?
Sí; tienes razón... ahora veo que lo que yo pensaba, simplemente, no iba por buen camino (y creo que tú sabes más o menos lo que yo pensaba).

Cita:
Empezado por Román
¿O será que te refieres a algo como JSON? En el Sofa Naranja puedes ver un ejemplo del "paso" del array.
Algo había leído... pero ni papa, la verdad. Sí; supongo que será algo así lo que podría hacerse... de seguir mi idea de pasar un "Array PHP" a JavaScript.

Cita:
Empezado por Román
Me gustaría que detallaras más a ver si podemos ver por donde está el problema.
Chico,... ahora mismo, no sé si es porque estoy resfriado o qué, tengo la cabeza que soy incapaz de hilvanar un par de pensamientos que parezcan razonables... Lo siento. El caso es que alguna idea ronda por mi cabeza... pero, son "problemas" que habría que tratar de resolver, y, total para qué...
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Librería para hacer peticiones HTTP para delphi 5 rlago Internet 3 06-11-2006 10:28:18
Ping en segundo plano toorbye Internet 5 19-10-2006 13:52:32
Programar en segundo plano Isako API de Windows 3 02-03-2005 14:31:20
Ayuda con Teclas en Segundo Plano Sundance Varios 12 29-08-2004 18:09:18
Ejecutar selects en segundo plano cartmanrules Firebird e Interbase 2 27-05-2004 19:08:56


La franja horaria es GMT +2. Ahora son las 12:03:05.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi