Cómo todo el mundo sabe, javscript puede ser un lenguaje muy feo y sólo algunos habían conseguido exprimir la quintaesencia de este lenguaje, como se hacía en dhtmlcentral.com, cuyas librerías han sido toda una ayuda para los que programamos en javascript desde hace años. No obstante, eso fue una etapa y los tiempos cambian, y se han buscado nuevas formas que nos acerquen al tipo de lenguaje orientado a objeto propiamente dicho como es java o más actual, .net. Siempre se ha pensado que era imposible crear clases en javascript, y es así,jaja, pero han buscado formas de imitarlo mediante la creación de objetos, lo que se ha venido a llamar en el mundo anglófono, namespaced javascript o object Literal. Antes de entrar en materia, os haré un resumen de lo que estoy diciendo para que nos entendamos.
ANTES: Antes todo eran funciones y entonces siempre podía pasar que si incluíamos 2 archivos de javascript distintos pudieran compartir nombres de funciones similares, y al más frecuentes, variables globales similares, y por lo tanto, ambos scripts dejaban de funcionar. Como mencionaba, en dhtmlcentral.com y en otros sitios, propulsaron una forma propia de javascript de crear pseudo-classes, se hacía así: function bola() { this.moverx=moverx; this.movery=movery; } function moverx() { } function movery() { } nuevaBola=new bola();
O sea creábamos un objeto, que tenía asociado unos pseudo-métodos, pero el problema de que otro script tuviera una función con el mismo nombre seguía ahí.Había que fastidiarse. AHORA: Hoy día, con el surgimiento de Ajax se le está dando mucho bombo a otra forma de imitar las clases, y no es algo nuevo, pero lo cierto es que es cada vez más frecuente. La "nueva forma", el javascript con nombre de espacio, no crea clases, crea objetos a los que se les añade propiedades, que van a hacer las veces de variables locales por su puesto públicas (aquí no hay distinciones del tipo privada o protegida) y métodos, métodos que no van a poder pisarse por otros scripts, aunque por supuesto nada de métodos con la propiedad override ni sealed ni nada que se le parezca. Es un truco, no una solución final. Si has llegado hasta aquí, y no sabes de que estoy hablando, este ejemplo te haré comprender: myscript=new Object(); myscript.current=1; myscript.init=function(){ // some code } myscript.validate=function(){ // some code }
Otro ejemplo con el código más resumido, no voy a decir más elegante, pero mejor para tener todo en un sólo bloque: myscript={ current:1, init:function(){ // code }, validate:function(){ // code } } Por lo tanto, os animo aquello que hayáis tenido la suerte o la desgracia de llegar hasta aquí que para cuando tengáis tiempo en el trabajo de programar bien javascript y sea un proyecto algo complejo o reutilizable, cojáis las riendas de los nombres de espacio en javascript y empecéis a crear objetos.
|
|
Aquellos que hayáis programado en cualquier lenguaje medianamente aceptable, habrá podido apreciar que las funciones matemáticas math.floor y math.ceil o math.ceiling nos proporcionan métodos para redondear hacia abajo o hacia arriba, cosa que para algunos casos es vital. Pues bien, ASP ni lo huele. No obstante, siempre podemos crearnos unos métodos ingeniosos para conseguir casi los mismos resultados.
He creado 2 funciones que podemos llamar según queramos redondear hacia arriba o hacia abajo, llamadas roundDown y roundUp, y después una función con piloto automático y que decidirá si usar uno u otro método dependiendo de su decimal: autoRound.
La gran pregunta aquí es qué pasa si le paso 10,5, pues según ocurre por ejemplo en .NET se redondea hacia abajo, pero si está por encima, p.e., 10,51 se redondea hacia arriba. En un principio me plantee que examinaría el 2 decimal y si éste era mayor de 0 redondearía hacia arriba, pero que pasa si el número fuera 10,501. Con este método hubiera redondeado hacia abajo, y shlaf!! gran error, gran horror. Es por eso que en autoRound empleo un loop que me indicará si uno de los decimales a partir del segundo decimal es mayor de 0 pues se redondeará hacia arriba.
Esta función también lo toma en cuenta:
Function roundDown(dblValue) Dim myDec
myDec = InStr(1, CStr(dblValue), ",") If myDec > 0 Then roundDown = CDbl(Left(CStr(dblValue), myDec)) Else roundDown = dblValue End If
End Function
Function roundUp(dblValue) Dim myDec
myDec = InStr(1, CStr(dblValue), ",") If myDec > 0 Then roundUp = CDbl(Left(CStr(dblValue), myDec)) + 1 Else roundUp = dblValue End If
End Function
function autoRound(dblValue) Dim myDec,pos,ini,aux
ini=1 pos = InStr(1, CStr(dblValue), ",") myDec=left(mid(cstr(dblValue),pos+ini),1) aux=false
If myDec > 5 Then autoRound = roundUp(dblValue) Else if myDec = 5 then do while Len(myDec)>0 and aux=false and ini<100 ini=ini+1 myDec=left(mid(cstr(dblValue),pos+ini),1) if not isNumeric(myDec) then myDec=0 if myDec>0 then aux=true end if loop if aux=true then autoRound = roundUp(dblValue) else autoRound = roundDown(dblValue) end if else autoRound = roundDown(dblValue) end if end if
end function
Response.Write "<br>" Response.Write "10,66: " & autoRound("10,66") & "<br>"'El output será 11. Response.Write "10,1: " &autoRound("10,1") & "<br>"'El output será 10. Response.Write "10,55: " &autoRound("10,55") & "<br>"'El output será 11. Response.Write "10,5555: " &autoRound("10,5555") & "<br>"'El output será 11. Response.Write "10,5: " &autoRound("10,5") & "<br>"'El output será 10. Response.Write "10,51: " &autoRound("10,51") & "<br>"'El output será 10. Response.Write "10,501: " &autoRound("10,501") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10. Response.Write "10,5001: " &autoRound("10,5001") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10. Response.Write "10,5000: " &autoRound("10,5000") & " Este estaría mal si no hiciéramos el loop<br>"'El output será 10. Response.Write "10: " &autoRound("10") & "<br>"'El output será 10.
|
|
Para los que procedáis de PHP como yo mismo, le habréis dado algunas vueltas antes de encontrar el equivalente a Exit en ASP. Cómo que no funciona la famosa etiqueta? Cuál será la solución? Antes de que empecemos a sudar, la solución es simplemente: Response.End
|
|
Como regla general, recomiendo utilizar chr para las sustituciones de tipo replace para los caracteres especiales, por ejemplo, si quiero sustituir unas comillas, pensemos en el siguiente código:
dim strPrueba
strPrueba="texto ""de prueba"""
strPrueba=replace(strPrueba,"""","")
No queda claro porque hay un barullo de dobles comillas propio de un lenguaje como asp.
En su lugar yo utilizaría algo más elegante: strPrueba=replace(strPrueba,chr(34),"")
Podemos buscarle utilidades interesantes al método chr, el más útil diría yo que es el carácter que indica retorno de carro. Esto es útil cuando el texto ha sido insertado desde un textarea. Se trata del carácter 13, el 13 es tu número como dicen en las pelis americanas. Con el siguiente source podrás convertir esos caracteres a saltos de html.
textArticle= replace(strPrueba, chr(13),"<br>")
Otra utilidad muy interesante es sustituir barras inclinadas hacia un lado por otras hacia el otro lado.
Otro truco al respecto, podéis saber a qué corresponde cada caracter así:
for i=0 to numMax step 1
Response.Write (i & ":" & chr(i) & "<br>")
next
|
|
|
Como no podía faltar, os presento aquí una función que os será utilísima para aquellos que pasáis de procedimientos almacenados o que no os viene bien o no podéis o... bueno, paro ahí.
Se trata de una función o método para combartir el SQL INJECTION. Como todos sabéis, es un ataque a través de la barra de navegación o a través de cajas de texto en vuestra web etc... en el que se inyectan códigos malignos tipo DELETE etc... para dañar vuestra web o simplemente para acceder a sitios restringidos.
Bueno sin enrollarme más y agradeciendo la refinación de la función a mi compañero Andrés os dejo aquí esta función que deberíais incluir en vuestra librería de utilidades:
Function AntiSqlInjection(cadena)
dim charReplace, valuesBanned, x
'constantes de caracteres a eliminar
Const CHARS = "'%/\<>()"
For x = 1 To Len(CHARS)
charReplace = MID(CHARS, x, 1)
cadena = Replace(cadena, charReplace, " ")
Next
'no queremos estos valores prohibidos
valuesBanned=Array("select","delete","update","insert", "truncate", "drop", "--")
for each valuesBanned in valuesBanned
cadena=Replace(lcase(cadena),valuesBanned,"")
next
AntiSqlInjection=cadena
End Function
|
|
En mi artículo anterior os hablaba de las prendas y virtudes de Ajax, y me quedé con la sensación de haberme quedado muy corto en mis explicaciones y en las implicaciones que conlleva este método (no lo llamaré tecnología tal y como explica Jesse James Garrett en http://www.adaptivepath.com/publications/essays/archives/000385.php.
No obstante, ahora que ya tenemos más o menos claro qué es Ajax, cómo se hace con javascript etc... Llega el "momento API"!!!!!
El momento API es el momento de perfeccionamiento de una técnica o de cualquier tipo de programación. Es el momento en el que todo ese código diseminado, "scattered", forma un conjunto y se vuelve algo profesional.
Yo he optado por tomar prestado una API que hasta el momento ha atendido todas mis necesidades. Se trata de la API de Sarissa:
https://sourceforge.net/projects/sarissa/
Es un proyecto "open source" con el que unificamos el uso de Ajax para diferentes navegadores, no sé si Opera y otros, pero sí para Mozilla e Internet Explorer, y KHTML(Konqueror y Safari).
APIs javascript
Quien nunca haya utilizado una API de javascript, pensará una API de javascript? Ese lenguaje horrible que no puede depurarse como los verdaderos lenguajes de programación? Eso no puede traer nada bueno!!
Pues bien, se equivocan, por supuesto, javascript no es perfecto, pero conocer javascript para un programador web es como el volante para un conductor, y sin javascript, no hay programador web. Suena obvio pero no es tanto así, porque el programador web tiende a aferrarse al lenguaje de servidor y aunque en una gran empresa todo el trabajo está dividido y seguramente no le toque escribir ni una línea de javascript, para optimizar la navegación del usuario, resulta necesario al 100%.
Al igual que antes los locos del javascript debieron adaptarse a los descubrimientos más óptimos de las CSS, ahora que xmlhttpRequest está dando fuerte, a los programadores ya no les queda otra que aprender javascript o se quedarán obsoletos. De hecho, todos los programadores tenemos que reintepretar la web y la forma de programar, y se debe invertir un período en reflexiónar al respecto.
Beneficios de una API: -Una API de javascript hace como cualquier otra API, centraliza el código, ahorra código y se edita con facilidad
porque sólo hay que modificarlo una vez.
Negativos de una API: -El código se vuelve más difícil, el programador tiene que aprender nuevos códigos y sin una buena documentación es de difícil modificación.
Tomando todo esto en cuenta, yo principalmente opto por las APIs de javascript pero no las totalizadoras, que hacen todo lo que quieras en tu web, sólo en casos concretos, donde las diferencias de códigos entre navegadores se vuelve más dispar.
El caso más claro de una buen API es la maravillosa y famosa API de dhtmlcentral.com. Es una API que me ha acompañado siempre y que he mejorado con el tiempo.
Qué conseguimos con una API si javascript hace unas tareas muy sencillas? Pues simplemente, unificamos el javascript que utilizan todos los navegadores. Por ejemplo, para ocultar una capa se hace diferente en IE4 que en IE6, Mozilla o Netscape 4.5. Con la API de dhtmlcentral escribimos una línea y lo hace compatible para todos.
Esto mismo conseguimos con Sarissa, más otras tareas relacionadas con el DOM.
Sarissa, la API para Ajax
En este tutorial, voy a tratar 2 métodos de cargar XML con Ajax. Uno utilizando XmlhttpRequest y otro cargando XML con el objeto load, que en IE pertenece al ActiveX Msxml2.DOMDocument, y que en Mozilla se implementa de otra manera. No obstante, como decía más arriba, no nos vamos a preocupar de las diferencias entre navegadores porque Sarissa hará los deberes por nosotros.
El resultado con ambos métodos es el mismo. No obstante, xmlhttpRequest, nos ofrece un mejor control sobre el estado de la carga del xml, porque podemos utilizar la propiedad ReadyState.
Como último apunte, Sarissa no se implementa creando una clase Sarissa, sino que se llama de manera estática.
Empecemos de lleno: 1.-Bajamos la API de su web.
2.-Incluimos los js: <script language="javascript" src="sarissa.js"></script> <script language="javascript" src="sarissa_ieemu_xpath.js"></script>
3.-Creamos el formulario que describía en mi último tutorial sobre Ajax, pero incluyendo un nuevo enlace que llama a getDatosXML para cargar XML utilizando load:
<div id="lblError"> </div> <form id="detalles" name="detalles" method="post"> <table cellpadding="0" cellspacing="0" border="0"> <tr> <td nowrap="nowrap" class="items" style="visibility:hidden">Metatags:</td><td> <textarea cols="40" rows="1" name="metatags" id="metatags"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items" style="visibility:hidden">Descripción:</td><td> <textarea cols="40" rows="1" name="descripcion" id="descripcion"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items" style="visibility:hidden">Descripción larga:</td><td> <textarea cols="40" rows="1" name="descripcionlarga" id="descripcionlarga"></textarea> </td> </tr> </table> <div class="buttons1"><a href="javascript:getDatos()">Llenar</a></div> <div class="buttons1"><a href="javascript:getDatosXML()">LlenarXML</a></div> </form>
4.-Ahora incluyamos las funciones getDatos y getDatosXML: var xmlhttp=null;
function getDatos(){ if(xmlhttp && xmlhttp.readyState!=0 && xmlhttp.readyState!=4){ alert("espere mientras la conexión anterior termina") return; } strUrl="xmlhttp_select.cs.asp?docid=4"
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", strUrl, true); xmlhttp.onreadystatechange=handlergetDatos xmlhttp.send(null);
}
function getDatosXML(){ strUrl="xmlhttp_select.cs.asp?docid=4"
respuestaXML= Sarissa.getDomDocument(); respuestaXML.async = false; respuestaXML.load(strUrl);
mostrarDatos(1)
}
Como vemos más arriba, hemos reducido mucho el código, ya no tenemos ninguna función que se encarga de crear la compatibilidad del objeto xmlhttpRequest. De esto se encarga Sarissa, que ha redefinido el objeto, un poco como se hace con los métodos en .Net con la propiedad "override".
De momento, ya vemos un ahorro de código, y además el sistema está mejorado porque Sarissa para IE, va a hacer un loop a través de los diferentes Activex que utiliza IE para crear el xmlHttpRequest hasta que encuentre el apropiado. Es decir, los activeX:
"Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP.
Para la función getDatosXml. También ahorramos porque la forma de crear el objeto, lo hará de modo conveniente dependiendo del navegador, y además para IE mejorará el método haciendo un loop buscando la clase apropiada entre:
"Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"
En mi código, he incluido una mejora:
if(xmlhttp && xmlhttp.readyState!=0 && xmlhttp.readyState!=4){ alert("espere mientras la conexión anterior termina") return; }
Con lo cual nos aseguramos que las diferentes conexiones no se pisan.
5.-Incluyamos la función que controla la carga de datos del xmlhttprequest:
function handlergetDatos(){
if(xmlhttp.readyState==2) { document.getElementById("lblError").innerHTML="Cargando datos"; } if(xmlhttp.readyState==3) { document.getElementById("lblError").innerHTML="Datos cargados"; }
if(xmlhttp.readyState==4) { document.getElementById("lblError").innerHTML="Carga de datos completada"; if(xmlhttp.status==200) {
respuestaXML=xmlhttp.responseXML
mostrarDatos();
}else{
alert("no se encuentra el documento xml") }
}
}
Aquí hemos mejorado la forma de hacer un seguimiento del estado de la conexión.
Un detalle a tener en cuenta es que al final la función mostrarDatos, va a utilizar el objeto respuestaXML. En el caso de cargarlo como documento XML usando load. La respuesta xml ya estaá contenida en el objeto mismo,pero en el caso de xmlhttpRequest, respuestaXML equivale a xmlhttp.responseXML.
Desde ese momento ambos XML son iguales y se tratan igual.
6.-Incluimos la función mostrarDatos:
function mostrarDatos(){ numNode=0; document.getElementById("lblError").innerHTML=""; try{ if(respuestaXML.parseError!=0){ throw "Posible formato erróneo:" + respuestaXML.parseError; } xmlmetatags=Sarissa.getText(respuestaXML.selectNodes("root/message/metatags")[numNode]) xmldescripcion=Sarissa.getText(respuestaXML.selectNodes("root/message/descripcion")[numNode])
xmldescripcionlarga=Sarissa.getText(respuestaXML.selectNodes("root/message/descripcionlarga")[numNode]) Sarissa.clearChildNodes(document.getElementById("metatags")) Sarissa.clearChildNodes(document.getElementById("descripcion")) Sarissa.clearChildNodes(document.getElementById("descripcionlarga")) document.getElementById("metatags").appendChild(document.createTextNode(xmlmetatags)) document.getElementById("descripcion").appendChild(document.createTextNode(xmldescripcion)) document.getElementById("descripcionlarga").appendChild(document.createTextNode(xmldescripcionlarga)) } catch(e) { document.getElementById("lblError").innerHTML="error cargando xml."+e+"<br>Lea la descripcíon del error y
póngase en contacto con su departamento técnico:<br>"+Sarissa.getParseErrorText(respuestaXML); }
}
Esta es la función que crea la magia.
Después de haber comprobado que se ha cargado sin problemas, seguimos haciendo comprobaciones:
if(respuestaXML.parseError!=0){
Con esto vamos a saber si el xml está mal formado. Sarissa en este sentido nos ofrece 1 propiedad: respuestaXML.parseError que debería ser 0 si no hay error.
Y un método para recuperar el error: Sarissa.getParseErrorText(respuestaXML)
Ahora es cuando utilizamos el segundo .js que incluimos sarissa_ieemu_xpath.js: xmlmetatags=Sarissa.getText(respuestaXML.selectNodes("root/message/metatags")[numNode])
Con el método getText vamos a recuperar el valor del nodo que le indiquemos. Para eso utilizamos el selectNodes si hay
más de una misma etiqueta (en este caso metatags) con un índice (numNode), o si fuera sólo uno, selectSingleNode.
Fin Hasta aquí llega mi tutorial, un método muy bueno que utiliza google, ver: http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html
Es utilizar en vez de una respuesta xml, una respuesta de texto, y ejecutarla como javascript, así: eval(_xmlHttp.responseText)
Pero el lado de la fuerza incluye muchos otros métodos relacionados con hojas de estilo XML ( http://www-128.ibm.com/developerworks/xml/library/x-xslt/?article=xr ) que exploraremos otro día.Sólo mostraros un ejemplo de diccionario basado en Google Suggests: http://www.objectgraph.com/dictionary/
Miguel Ángel. Programador.
|
|
Hay muchos programadores que después de comprarse un flamante portátil último modelo con más caballos que un porsche, se llevan la ingrata sorpresa de que su sistema operativo Windows XP Home no soporta IIS!!!!!!
Al principio, piensan que es un espejismo, se frotan bien los ojos, pero efectivamente no aparece en "Agregar componentes de Windows". Poco después, cogitan, y buscan por todos los lados y el IIS sigue escondido, el muy bribón!
Pero lo cierto es que esos dólares que diferencian la versión Professional de la Home crean un antes y un después a la hora de comprar el sistema operativo.
Tal vez a aquellos que usan piratería normalmente esto les importe un rábano, pero los legales y aquellos que no tienen ganas de ponerse a formatear su portátil y agenciarse el sistema profesional, puede ser realmente un inconveniente molesto.
Pero relajémonos, la comunidad web, en concreto Richard Sandoz, nos ofrece una alternativa con un fantástico hack que podéis encontrar por internet en inglés (www.15seconds.com/issue/020118.htm).
Las explicaciones de R. Sandoz son muy diversas y desordenadas, además de omitir algunos pasos, y por lo tanto, altamente frustantes!! El hackeador se merece un premio pero el profe suspenso!!
Es mejor y más detallada la explicación de adamV.com: http://adamv.com/dev/articles/iis-on-xp-home
Os hago un pequeño resumen, que yo mismo he probado (o sufrido), y os doy unas referencias para que investiguéis. Cuando terminéis este artículo, con suerte, tendréis vuestro IIS funcionando en el XP home!!
Antes de nada decir una evidencia, no por conseguir el IIS en el Home estamos pasando un Home a Professional. Estas 2 ediciones del famoso OS tienen muchas más diferencias, sobre todo en seguridad. Para ver un buen resumen:
www.winsupersite.com/showcase/windowsxp_home_pro.asp
Lo más impresionante del hack es que vamos a utilizar en realidad el IIS del Windows 2000 pro (necesitas el CD) para utilizarlo en el XP Home!!! Antes de llegar a este punto, hagamos el trabajo sucio.
Empecemos: 1.-Localiza: C:WINDOWSINFSYSOC.INF
Busca la entrada: iis=iis.dll,OcEntry,iis.inf,hide,7
Sustitúyela por: iis=iis2.dll,OcEntry,iis2.inf,,7
2.-Copia los archivos iis.dl_ and iis.in_ (el guión bajo existe y no es un fallo, esto signifca que es un dll comprimido) del disco de Windows 2000 pro. Se encuentran en la carpeta i386 del disco de instalación.
3.-Copia el iis.in_ en C:WINDOWSINF y el iis.dl_ en C:WINDOWSSYSTEM32SETUP.
4.-Abre una consola msdos y bajo cada uno de esos directorios de arriba, escribe bajo C:WINDOWSINF en msdos: expand iis.dl_ iis2.dll
Escribe bajo C:WINDOWSSYSTEM32SETUP en msdos: expand iis2.in_ iis2.inf
Con lo cual, hemos descomprimido los archivos que copiamos en las carpeta idóneas, y el archivo sysoc.inf indicará a windows que busque esos archivos.
5.-Ahora ya sólo nos queda ir a agregar/quitar programas>agregar componentes de windows, y buscar en esa lista el IIS. Marcamos la opción y desmarcamos la casilla de SMTP, este servicio nos dará problemas si lo instalamos.
6.-Siguiente. Nos pedirá el CD. Utiliza el CD de Windows 2000 pro. Y busca la carpeta i386.
7.-Una vez se haya instalado todo. Hemos hecho el camino más duro, pero caminante no hay camino, y queda aún un trecho.
De esta parte se olvidan casi todos los tutoriales que hay en internet pero es fundamental y no todo el mundo está al tanto.
Al instalar un IIS del Windows 2000, este IIS va a utilizar la forma que tenía de gestionar la seguridad bajo aquel sistema operativo, pero en la edición XP home ha variado. Ahora para el usuario anónimo, se necesita especificar el nombre de la máquina. En W2k sólo hace falta el IIS_NAME como usuario anónimo, cuando en XP home es NAME/IIS_NAME ("NAME" es el nombre de tu máquina, que puedes ver en propiedades de mi PC).
Teletranspórtate a "Administrador de servicios Internet" o sea al Manager del IIS,y cliquea botón derecho sobre el icono de tu ordenador.
a.-Junto a Servicio WWW, cliquea Modificar. b.-elige la pestaña Seguridad de directorio c.-verifica las casillas de acceso anónimo y seguridad de windows integrada. d.-cliquea Modificar de acceso anónimo. e.-En el formulario de Cuenta de Usuario Anónimo desverifica "permitir que IIS controle contraseñas" f.-Ahora Examinar, y tienes que buscar el usuario IUSR_NAME ("NAME" es el nombre de tu máquina), lo seleccionas, aceptas las pantallas precedentes y ahora aparecerá el usuario NAME/IUSR_NAME ("NAME" es el nombre de tu máquina). g.-Acepta todas las pantallas y OK.
8.-Comprueba escribiendo un archivo asp bajo wwwroot, y http://localhost/NombreArchivo.asp.
Y voilà!!!!!
Con esto hemos efectuado un largo camino, para algunos tal vez demasiado pesado y antes de terminar el tutorial, han instalado el XP Pro.
Esto era la primera parte.
La segunda parte habla del Visual Studio 2003 y el IIS que hemos hackeado.
1.-Instalamos el Visual Studio 2003 (por supuesto y como es obligatorio, con todos sus "prerequisites" o requisitos previos).
2.-Depuramos y fallo, no se encuentra el filtro de ASP.NET.
3.-Esto no sólo nos pasa a nosotros los hackeadores de postín.
Tenemos que registrar la dll para que aparezca como filtro en los filtros Isapi del IIS, para navegamos a: <DRIVE>:WINDOWSMicrosoft.NETFramework<FRAMEWORK VERSION>
(normalmente: C:WINNTMicrosoft.NETFramework1.1.4322)
Y picamos:
asp_regiis -i
También funcionaría:
regsvr32 aspnet_isapi.dll
Este debería ser el fin de nuestros problemas, pero a mí me acosó otro error. Seguí sin hacer funcionar el .NET, y el motivo era que no tenía permisos para escribir en el wwwroot.
Esto se soluciona cambiando la carpeta raíz de nuestro IIS en el "Administrador de Servicios de Internet" a una nueva carpeta que creemos, o simplemente, cambiándole los permisos a la carpeta wwwroot.
Bueno, espero haber servido de ayuda, este artículo se lo dedico a todos aquellos que perdieron su tiempo para ayudar a los enmarronados del XP Home.
M.A. Programador.
|
|
|
A veces nos hemos preguntado. ¿Y si fuera más fácil y más claro en ASP hacer un datagrid sin tener todos los códigos html y asp entremezclados? Qué gran injusticia sentimos cuando programamos en asp, y no podemos utilizar el control DataGrid de .Net!!! Qué desgracia para un purista ver todos esos comandos enredados y apelogotonados!!
No nos quejemos que los códigos están en nuestras manos para intentar crear la ilusión de que todo se automatiza más. Los controles de .Net no son más que clases y por lo tanto cualquier otro lenguaje puede imitarlo, aunque sin el soporte de la magnífica plataforma de Visual Studio.
He programado una clase que tiene bastantes posibilidades, aunque no la he perfeccionado, quería ofrecerla aquí al mundo internauta y si alguien tiene el tiempo y la paciencia de perfeccionarla. Please, make me know!!
Vamos a producir un Datagrid con esta clase que pagina cada 30 ítems y que va a mostrar hasta 20 números a los que navegar, que además mostrará enlaces de "inicio", "anterior", "siguiente" y "fin.
dim updateGrid
set updateGrid=new HtmlDatagrid
updateGrid.arConexion=arConexion
updateGrid.arCampos= Array("idcentro","nombre","direccion","codigopost","prov","telefono")
updateGrid.strOrder="nombre ASC"
updateGrid.arCamposVisible=Array(0,1,1,1,1,1)
updateGrid.arThCampos=Array("id","Nombre","Dirección","Código Postal","Provincia","Teléfono")
updateGrid.btnPaginar=1 'con esto hacemos que aparezcan los botones de inicio etc...
updateGrid.numPaginar=30
updateGrid.numerosPaginacion=20
updateGrid.TableAttr="cellSpacing=""1"" id=""itemstable"" cellPadding=""1"" width=""100%"" border=""0"" style=""margin-top:30px"" summary=""Resultados de búsqueda de centros, dividido en: nombre, dirección y teléfono""" 'estilos de las filas
updateGrid.arAttr= Array ("valign='top' align='center'","valign='top'","valign='top'","valign='top' align='center'","valign='top'","valign='top'") 'estilos de la cabecera
updateGrid.arThAttr=Array("class=""fondocolorlogoclaro"" width=""60"" align=""left""","class=""fondocolorlogoclaro"" width=""120"" align=""left""","class=""fondocolorlogoclaro"" width=""160"" align=""left""","class=""fondocolorlogoclaro"" width=""100"" align=""center""","class=""fondocolorlogoclaro"" width=""120"" align=""left""","class=""fondocolorlogoclaro"" width=""120"" align=""left""")
updateGrid.display()
Como se ve es bastante sencillo.
Pero bueno, estudiemos el abracadabra-pata-de-cabra del código.
1.-Creamos la instancia de la clase.
set updateGrid=new HtmlEditDatagrid
2.-Le asignamos la conexión que debe ser un array con 5 valores:
updateGrid.arConexion=arConexion
tal que así:
Dim arConexion(5) 'array de conexion arConexion(0)="SQLOLEDB" 'proveedor de base de datos arConexion(1)="servidor" 'direccion del servidor arConexion(2)="basededatos" 'base de daots arConexion(3)="usuario" arConexion(4)="contraseña" arConexion(5)="tabla"
3.-Definimos los campos que vamos a recoger de nuestra consulta a la base de datos en un array, y cómo queremos que aparezcan ordenados:
updateGrid.arCampos= Array("idcentro","nombre","direccion","codigopost","prov","telefono")
updateGrid.strOrder="nombre ASC"
4.- Le colocamos el nombre de cabecera que se nos antoje, pero queremos que no aparezca una columna que se llame id, así que con la propiedad arCamposVisible le asignamos un 0:
updateGrid.arThCampos=Array("id","Nombre","Dirección","Código Postal","Provincia","Teléfono")
updateGrid.arCamposVisible=Array(0,1,1,1,1,1)
5.-Ahora definimos cómo queremos paginar:
updateGrid.btnPaginar=1 'igualado a 1, incluimos hiperenlaces a inicio, anterior,siguiente…
updateGrid.numPaginar=30 'mostrar 30 ítems
updateGrid.numerosPaginacion=20 'mostrar hiperenlaces a 20 páginas
6.-Lo demás: updateGrid.TableAttr, updateGrid.arAttr, updateGrid.arThAttr sirve para definir los estilos de la tabla, de las filas y la cabecera etc…
7.-Finalmente lo mostramos:
updateGrid.display()
Para realizar esta maravilla os dejo la clase más abajo, pero aviso, no está nada pulida, pero cubre bastantes de las necesidades del día a día del programador.
Con esta clase he podido hacer también que las filas sean editables, sin tocar casi nada, también se pueden separar las celdas por celdas de imágenes que no tengan ninguna funcionalidad, se pueden agrupar campos y colocarlos en uno sólo, se puede crear un filtro en la consulta (where x like '%x%'), etc…
Ya iré mostrando otros ejemplos sobre el uso de esta clase en el futuro.
CLASE HTMLDATAGRID:
class HtmlDatagrid public arConexion public arCampos public arCamposVisible public arFilter public strAdicional public strOrder public TableAttr public arThcampos public arThAttr public arAttr public numPaginar public numerosPaginacion public separadorCells public btnCampos public classTr public btnPaginar
function display()
Response.Write(me.createDataGrid())
end function
function createDataGrid()
Dim conn1 'la conexión Dim rs1 'el recordset Dim strQuery 'cadena de la consulta Dim strCells 'el resultado devuelto: las celdas Dim arCamposLen 'longitud del array de campos Dim pagina_actual 'por si estamos paginando recupera el valor de página actual
on error resume next
arCamposLen=Ubound(arCampos)
set conn1=Server.CreateObject("ADODB.Connection") conn1.ConnectionString="Provider=" & arConexion(0) & ";Data Source=" & arConexion(1) & ";Initial Catalog=" &arConexion(2) & ";uid=" & arConexion(3) & ";PWD=" & arConexion(4) conn1.Open
'----------------[creación de recordset]---------------
set rs1=Server.CreateObject("ADODB.Recordset")
'ordenación por strOrder rs1.Sort=strOrder rs1.ActiveConnection=conn1 rs1.CursorType=1 rs1.LockType=3 rs1.CursorLocation=3
'-----------construimos cadena de la consulta Dim i 'dummy Dim campo 'dummy for i=0 to arCamposLen
'si el campo es un array 'puede ser un array porque es posible que queramos agrupar 'varios campos en una fila if isArray(arCampos(i)) then for each campo in arCampos(i) strQuery=strQuery & campo strQuery=strQuery & "," next else 'si el campo no es un array strQuery=strQuery & arCampos(i) strQuery=strQuery & ","
end if next 'le quitamos la última coma strQuery=left(strQuery,Len(strQuery)-1) '------------------[filtramos según arFilter]
if isArray(arFilter) then Dim strFilter Dim strSeparadorIni Dim strSeparadorFin
'nuestro filtro incluye 3 campos así que saltamos de 3 en 3 for i=0 to Ubound(arFilter) step 3
'aquí es donde vamos a utilizar un tipo de operador u otro if arFilter(i+1)="like" then
strSeparadorIni="'%" strSeparadorFin="%'"
else strSeparadorIni="'" strSeparadorFin="'" end if
strFilter=strFilter & arFilter(i) & " " & arFilter(i+1) & strSeparadorIni & arFilter(i+2) & strSeparadorFin & "and "
next
'le extraemos el último "and" strFilter=left(strFilter,Len(strFilter)-4) strFilter=" where " & strFilter end if
strQuery="select " & strAdicional & strQuery & " from " & arConexion(5) & strFilter
'Response.Write(strQuery)
rs1.Source=strQuery
rs1.Open
if not rs1.EOF then 'if -rs1.eof '--------recuperamos la página en la que nos encontramos en caso de estar paginando
Dim strResults ' recoge los números de la paginación etc... Dim numRegistros 'número de registros del recordset numRegistros=rs1.recordcount
'Response.Write(numRegistros)
if numPaginar<>"" and numRegistros>numPaginar then '--------if-paginacion
if (request.queryString("page") <> "") then pagina_actual = request.queryString("page") else pagina_actual = 1 end if
'si existe algún resultado, ejecuta el resto
rs1.pagesize=numPaginar rs1.absolutePage = pagina_actual 'nos situamos en la página actual
'---------creamos el índice de páginas
'resultados strResults=strResults & "<br>Resultados <b>" & (pagina_actual*numPaginar-numPaginar+1) & " a " & ((pagina_actual*numPaginar)) & "</b>" strResults=strResults & "<br><br>" strResults=strResults & "<center>" if pagina_actual <>1 then
'hacemos que aparezcan los botones de inicio etc... if btnPaginar<>"no" then strResults=strResults & "<a href=""?page=1"" class=""paginar"" title=""ir a inicio"">[Inicio]</a>" strResults=strResults & "<a title=""Ir a pagina anterior"" class=""paginar"" href=""?page=" & (pagina_actual-1) & """>[Anterior]</a>"
end if
end if
'números de paginación
dim k 'dummy dim hrefClass 'la clase de los números k=1
dim numDiv 'nos va a servir para corregir un error dim numPag numPag=0 'guarda número del menu de las páginas que se muestra Do While k <= rs1.PageCount
numDiv=roundDown(pagina_actual/numerosPaginacion)
if pagina_actual mod numerosPaginacion = 0 then
numDiv=numDiv-1
end if
numPag=numDiv*numerosPaginacion
numPag=numPag+k 'sólo vamos a mostrar numerosPaginacion páginas if k<=numerosPaginacion and numPag<=rs1.PageCount then
'sólo vamos a mostrar numerosPaginacion páginas if rs1.PageCount>numerosPaginacion then
if numPag=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a> </b>"
else
if k=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a> </b>"
end if k=k+1
else exit do end if
Loop
'insertamos letreros de siguiente y fin if cint(pagina_actual)<> rs1.PageCount then if btnPaginar<>"no" then strResults=strResults & "<a href=""?page="& (pagina_actual+1) & """ class=""paginar"" title=""ir a página siguiente"">[Siguiente]</a>" strResults=strResults & "<a title=""Ir a página final"" class=""paginar"" href=""?page=" & (rs1.PageCount) & """>[Fin]</a>" end if end if
strResults=strResults & "</center>" strCells=strCells & strResults
end if '-------if-paginacion
'-------------------[loop: creación de cabecera]-------------------
strCells=strCells & "<table " & TableAttr & ">" dim j 'dummy
if isArray(arThcampos) then'if-arthAttr
strCells=strcells & "<tr>" for j=0 to arCamposLen
if arCamposVisible(j)=1 then strCells=strCells & "<TH " & arThAttr(j) & "><b> " & arThcampos(j) & "</b> </TH>" end if next
strCells=strCells & "</tr>"
end if'if-arthAttr
'----------------[loop: creación de tabla]---------------
if numPaginar="" then 'colocamos la paginación más allá de cualquier límite si no existe numPaginar=100000 end if
Dim cuentaRegistros cuentaRegistros=0 'contaremos cuántos registros muestra para que pare en numPaginar
dim cellValue 'valor de los campos, de no haber, se sustituye por en caso de que utilicemos bordes es útil dim m 'dummy dim boton 'variable que utilizaremos si hay botones dim campovalor'tambien lo utilizamos si hubiera botones
if classTr<>"" then classTr="class=""" & classTr & """" end if
do while not rs1.EOF and cuentaRegistros<numPaginar
cuentaRegistros=cuentaRegistros+1 'esto hará que se pare en numPaginar
strCells=strCells & "<tr " & classTr & " >"
'creamos las celdas for j=0 to arCamposLen 'for-arcamposlen cellValue="" 'si queremos que se vea if arCamposVisible(j)=1 then 'if -visible 'si es una agrupación de valores if IsArray(arCampos(j)) then m=0 for each campo in arCampos(j) cellValue=cellValue & rs1(campo)& arGroupFSeparators(m) m=m+1 next 'si es botón es que el campo es "' ' as" 'si es un alias para crear botones etc... elseif left(arCampos(j),1)="'" then boton=btnCampos(j) campovalor=arCampos(j) campovalor=mid(campovalor,2,1) campovalor=arCampos(campovalor) campovalor=rs1(campovalor) execute("cellValue=" & boton & "(""" & campovalor & """)" ) else if rs1(arCampos(j))="" or rs1(arCampos(j))=" " or rs1(arCampos(j))=" " then cellValue=" " else cellValue=rs1(arCampos(j)) end if end if
strCells=strCells & "<TD " & arAttr(j) & ">"& cellValue & "</td>"
end if'if -visible next 'for-arcamposlen strCells=strCells & "</tr>"
'si hay un separador de celdas que hayamos pasados como parámetro
if separadorCells<>"" then
strCells=strCells & separadorCells
end if
rs1.MoveNext
loop
'cerramos tabla strCells=strCells & "</table>"
'------------paginación 2 if numPaginar<>"" and numRegistros>numPaginar then strCells=strCells & strResults end if
else 'if -rs1.eof
Response.Write ("<br>No se ha encontrado ningún registro<br>")
end if 'if -rs1.eof
'--------------[destrucción de objetos]---------------
rs1.Close set rs1=nothing
conn1.Close set conn1=nothing
if err<>0 then
Response.Write("<font color=red>Ha habido un error en la ejecución de esta página. Inténtelo de nuevo</font>") end if On Error GoTo 0
createDataGrid=strCells
end function
end class
class HtmlEditDatagrid public arConexion public arCampos public arCamposVisible public arFilter public strAdicional public strOrder public TableAttr public arThcampos public arThAttr public arAttr public numPaginar public numerosPaginacion public separadorCells public btnCampos public classTr public btnPaginar
function display()
Response.Write(me.createDataGrid())
end function
function createDataGrid()
Dim conn1 'la conexión Dim rs1 'el recordset Dim strQuery 'cadena de la consulta Dim strCells 'el resultado devuelto: las celdas Dim arCamposLen 'longitud del array de campos Dim pagina_actual 'por si estamos paginando recupera el valor de página actual
on error resume next
arCamposLen=Ubound(arCampos)
set conn1=Server.CreateObject("ADODB.Connection") conn1.ConnectionString="Provider=" & arConexion(0) & ";Data Source=" & arConexion(1) & ";Initial Catalog=" &arConexion(2) & ";uid=" & arConexion(3) & ";PWD=" & arConexion(4) conn1.Open
'----------------[creación de recordset]---------------
set rs1=Server.CreateObject("ADODB.Recordset")
'ordenación por strOrder rs1.Sort=strOrder rs1.ActiveConnection=conn1 rs1.CursorType=1 rs1.LockType=3 rs1.CursorLocation=3
'-----------construimos cadena de la consulta Dim i 'dummy Dim campo 'dummy for i=0 to arCamposLen
'si el campo es un array 'puede ser un array porque es posible que queramos agrupar 'varios campos en una fila if isArray(arCampos(i)) then for each campo in arCampos(i) strQuery=strQuery & campo strQuery=strQuery & "," next else 'si el campo no es un array strQuery=strQuery & arCampos(i) strQuery=strQuery & ","
end if next 'le quitamos la última coma strQuery=left(strQuery,Len(strQuery)-1) '------------------[filtramos según arFilter]
if isArray(arFilter) then Dim strFilter Dim strSeparadorIni Dim strSeparadorFin
'nuestro filtro incluye 3 campos así que saltamos de 3 en 3 for i=0 to Ubound(arFilter) step 3
'aquí es donde vamos a utilizar un tipo de operador u otro if arFilter(i+1)="like" then
strSeparadorIni="'%" strSeparadorFin="%'"
else strSeparadorIni="'" strSeparadorFin="'" end if
strFilter=strFilter & arFilter(i) & " " & arFilter(i+1) & strSeparadorIni & arFilter(i+2) & strSeparadorFin & "and "
next
'le extraemos el último "and" strFilter=left(strFilter,Len(strFilter)-4) strFilter=" where " & strFilter end if
strQuery="select " & strAdicional & strQuery & " from " & arConexion(5) & strFilter
'Response.Write(strQuery)
rs1.Source=strQuery
rs1.Open
if not rs1.EOF then 'if -rs1.eof '--------recuperamos la página en la que nos encontramos en caso de estar paginando
Dim strResults ' recoge los números de la paginación etc... Dim numRegistros 'número de registros del recordset numRegistros=rs1.recordcount
'Response.Write(numRegistros)
if numPaginar<>"" and numRegistros>numPaginar then '--------if-paginacion
if (request.queryString("page") <> "") then pagina_actual = request.queryString("page") else pagina_actual = 1 end if
'si existe algún resultado, ejecuta el resto
rs1.pagesize=numPaginar rs1.absolutePage = pagina_actual 'nos situamos en la página actual
'---------creamos el índice de páginas
'resultados strResults=strResults & "<br>Resultados <b>" & (pagina_actual*numPaginar-numPaginar+1) & " a " & ((pagina_actual*numPaginar)) & "</b>" strResults=strResults & "<br><br>" strResults=strResults & "<center>" if pagina_actual <>1 then
'hacemos que aparezcan los botones de inicio etc... if btnPaginar<>"no" then strResults=strResults & "<a href=""?page=1"" class=""paginar"" title=""ir a inicio"">[Inicio]</a>" strResults=strResults & "<a title=""Ir a pagina anterior"" class=""paginar"" href=""?page=" & (pagina_actual-1) & """>[Anterior]</a>"
end if
end if
'números de paginación
dim k 'dummy dim hrefClass 'la clase de los números k=1
dim numDiv 'nos va a servir para corregir un error dim numPag numPag=0 'guarda número del menu de las páginas que se muestra Do While k <= rs1.PageCount
numDiv=roundDown(pagina_actual/numerosPaginacion)
if pagina_actual mod numerosPaginacion = 0 then
numDiv=numDiv-1
end if
numPag=numDiv*numerosPaginacion
numPag=numPag+k 'sólo vamos a mostrar numerosPaginacion páginas if k<=numerosPaginacion and numPag<=rs1.PageCount then
'sólo vamos a mostrar numerosPaginacion páginas if rs1.PageCount>numerosPaginacion then
if numPag=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & numPag & """ class=""" & hrefClass & """ href=""?page=" & numPag & """>" & numPag & "</a> </b>"
else
if k=cint(pagina_actual) then hrefClass="negrita" else hrefClass="paginarN" end if
strResults=strResults & " <b><a title=""ir a pagina " & k & """ class=""" & hrefClass & """ href=""?page=" & k & """>" & k & "</a> </b>"
end if k=k+1
else exit do end if
Loop
'insertamos letreros de siguiente y fin if cint(pagina_actual)<> rs1.PageCount then if btnPaginar<>"no" then strResults=strResults & "<a href=""?page="& (pagina_actual+1) & """ class=""paginar"" title=""ir a página siguiente"">[Siguiente]</a>" strResults=strResults & "<a title=""Ir a página final"" class=""paginar"" href=""?page=" & (rs1.PageCount) & """>[Fin]</a>" end if end if
strResults=strResults & "</center>" strCells=strCells & strResults
end if '-------if-paginacion
'-------------------[loop: creación de cabecera]-------------------
strCells=strCells & "<table " & TableAttr & ">" dim j 'dummy
if isArray(arThcampos) then'if-arthAttr
strCells=strcells & "<tr>" for j=0 to arCamposLen
if arCamposVisible(j)=1 then strCells=strCells & "<TH " & arThAttr(j) & "><b> " & arThcampos(j) & "</b> </TH>" end if next
strCells=strCells & "</tr>"
end if'if-arthAttr
'----------------[loop: creación de tabla]---------------
if numPaginar="" then 'colocamos la paginación más allá de cualquier límite si no existe numPaginar=100000 end if
Dim cuentaRegistros cuentaRegistros=0 'contaremos cuántos registros muestra para que pare en numPaginar
dim cellValue 'valor de los campos, de no haber, se sustituye por en caso de que utilicemos bordes es útil dim m 'dummy dim boton 'variable que utilizaremos si hay botones dim campovalor'tambien lo utilizamos si hubiera botones
if classTr<>"" then classTr="class=""" & classTr & """" end if
do while not rs1.EOF and cuentaRegistros<numPaginar
cuentaRegistros=cuentaRegistros+1 'esto hará que se pare en numPaginar
strCells=strCells & "<tr " & classTr & " >"
'creamos las celdas for j=0 to arCamposLen 'for-arcamposlen cellValue="" 'si queremos que se vea if arCamposVisible(j)=1 then 'if -visible 'si es una agrupación de valores if IsArray(arCampos(j)) then m=0 for each campo in arCampos(j) cellValue=cellValue & rs1(campo)& arGroupFSeparators(m) m=m+1 next 'si es botón es que el campo es "' ' as" 'si es un alias para crear botones etc... elseif left(arCampos(j),1)="'" then boton=btnCampos(j) campovalor=arCampos(j) campovalor=mid(campovalor,2,1) campovalor=arCampos(campovalor) campovalor=rs1(campovalor) execute("cellValue=" & boton & "(""" & campovalor & """)" ) else if rs1(arCampos(j))="" or rs1(arCampos(j))=" " or rs1(arCampos(j))=" " then cellValue=" " else cellValue=rs1(arCampos(j)) end if end if
strCells=strCells & "<TD " & arAttr(j) & ">"& cellValue & "</td>"
end if'if -visible next 'for-arcamposlen strCells=strCells & "</tr>"
'si hay un separador de celdas que hayamos pasados como parámetro
if separadorCells<>"" then
strCells=strCells & separadorCells
end if
rs1.MoveNext
loop
'cerramos tabla strCells=strCells & "</table>"
'------------paginación 2 if numPaginar<>"" and numRegistros>numPaginar then strCells=strCells & strResults end if
else 'if -rs1.eof
Response.Write ("<br>No se ha encontrado ningún registro<br>")
end if 'if -rs1.eof
'--------------[destrucción de objetos]---------------
rs1.Close set rs1=nothing
conn1.Close set conn1=nothing
if err<>0 then
Response.Write("<font color=red>Ha habido un error en la ejecución de esta página. Inténtelo de nuevo</font>") end if On Error GoTo 0
createDataGrid=strCells
end function
end class
|
|
Todo programador sabe apreciar la originalidad y buen hacer con el que Gmail, Google Groups, Google Suggest, Google Maps... se han programado, y todos los que saben un poquito hablan del maravilloso mundo del xmlhttprequest. Es como el amigo que uno tiene que hizo una cosa sorprendente pero que nadie conoce. En este artículo voy a intentar explicar un poco los entresijos de algo que puede ser verdaderamente beneficioso para cualquier cerebrito que quiera mejorar la navegación de sus páginas.
En primer lugar resaltemos algunas de las prestaciones que luce este nuevo planteamiento:
-xmlhttprequest es un objeto que nació en el Internet Explorer 5 como un ActiveX, y que después pasó a formar parte de los principales navegadores: Mozilla, Safari etc... Es un objeto que se crea desde javascript, y que apunta a una página en el servidor.
- no hace falta moverse de página para actuar en el servidor y responder al cliente. Para poner un símil, hace lo que las llamadas en Actionscript dentro de un flash hacen a otras páginas sin que el cliente lo perciba.
-xmlhttprequest además de poder actuar en el servidor, puede devolver datos, por ejemplo, XML, pero también texto que podemos utilizar a nuestro antojo. En el primer caso, por ejemplo, podríamos utilizar el DOM para reestructurar la web a partir de un documento xml, y en el segundo caso, si utilizamos texto, podría mandar de vuelta la confirmación de que todo fue bien en el servidor.
-Por último y no menos importante, hay una limitación de seguridad, y es que no se puede hacer una llamada a una página que no tenga el mismo dominio que la página que contiene el javascript. Es decir, que no podemos llamar a un web service directamente.
Todo esto llevado al séptimo arte es el motor principal de Gmail con un javascript supersofisticado, y creo que cualquiera puede apreciar la rapidez y amenidad con que se navega en el popular proveedor de correo.
Pero bueno, dejémonos de prolegómenos y hinquémosle el diente al asado!!!
1.- Creemos este formulario:
<form id="detalles" name="detalles" method="post"> <table cellpadding="0" cellspacing="0" border="0"> <tr> <td nowrap="nowrap" class="items">Metatags:</td><td> <textarea cols="40" rows="2" name="metatags" id="metatags"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items">Descripción:</td><td> <textarea cols="40" rows="2" name="descripcion" id="descripcion"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items">Descripción larga:</td><td> <textarea cols="40" rows="2" name="descripcionlarga" id="descripcionlarga"></textarea> </td> </tr> </table> <div id="grabar" class="buttons1"><a href="#">Grabar</a></div> </form>
2.-Como habremos visto, el hyperlink de "Grabar" es una llamada a una función updateDatos. Esta función pone en marcha todo el tinglado!!.
Antes de ver dicha función debemos crear el javascript siguiente:
function getHTTPObject() { var xmlhttp; if (!xmlhttp) { if(window.XMLHttpRequest) { try { xmlhttp = new XMLHttpRequest(); } catch(e) { alert("mensaje error 1.1") xmlhttp = false; } // branch for IE/Windows ActiveX version } else if(window.ActiveXObject) { try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {
alert("mensaje de error 1.2") xmlhttp = false; } } } } return xmlhttp; } var http = getHTTPObject(); // We create the HTTP Object
Lo que hemos hecho ha sido crear una instancia del objeto Xmlhttprequest, en el caso de Mozilla y Safari es el objeto XMLHttpRequest(), y en el caso de Internet Explorer, o ActiveXObject("Msxml2.XMLHTTP"); o ActiveXObject("Microsoft.XMLHTTP").
Todo lo demás son comprobaciones que son útiles para ofrecer una mayor capacidad de respuesta al cliente. Un buen sistema de aviso de errores, y esto lo digo para cualquier tipo de programación, debe contener el error y asignarle un número, que a su vez tendríamos referenciado, al estilo de programas de consola, para que el soporte técnico supiera enseguida de qué se trata.
Sigamos, creemos la función de updateDatos():
function updateDatos(){
var urldatos = "xmlhttp_insert.cs.asp?"; // The server-side script var metaValue = document.getElementById("metatags").value; var descripValue=document.getElementById("descripcion").value; var descriplargaValue=document.getElementById("descripcionlarga").value;
strUrl=urldatos + "metas=" +escape(metaValue) + "&descrip="+ escape(descripValue)+"&descriplarga="+escape(descriplargaValue); if(http) {
http.open("GET",strUrl, true); http.setRequestHeader('Accept','message/x-jl-formresult') http.send(null);
} else { alert("Hubo un problema al conectar. Consulte con soporte técnico");
} }
Aquí utilizamos la instancia del objeto xmlhttprequest y le asignamos la url de destino: http.open("GET",strUrl, true);
El string con todos los parámetros están añadidos a "urldatos". Por cierto, siempre hacer escape!! ya que se pasa por GET y así le damos el formato adecuado a la cadena.
http.onreadystatechange = handleHttpResponse; http.send(null);
Controlamos el estado de nuestra conexión con la url de destino de esta manera. La función handleHttpResponse actuara según si la conexión prospera o no.
function handleHttpResponse() {
if (http.readyState == 4) { // Split the comma delimited response into an array results = http.responseText; if (http.status == 200) { if(results=="OK" ){ alert("OK:<br>Base de datos actualizada."); } else{ alert("Hubo un problema actualizando, inténtelo de nuevo, y si devuelve error, por favor, consulte soporte técnico"); } }else{ alert ("Hubo un problema actualizando, inténtelo de nuevo, y si devuelve error, por favor, consulte soporte técnico"); } } }
"http.readyState == 4" nos dice que la conexión se ha realizado con éxito, y "http.status == 200" que la página existe. results=="OK", simplemente nos informa de cómo se realizó todo en el servidor.
Bueno, nada más me queda recomendaros el siguiente link donde se amplian bastantes conocimientos:
http://jibbering.com/2002/4/httprequest.html
y para los que queréis el código directamente, un ejemplo sencillito y que aproveche!!:
<script language="javascript" type="text/javascript">
function getHTTPObject() { var xmlhttp; if (!xmlhttp) { if(window.XMLHttpRequest) { try { xmlhttp = new XMLHttpRequest(); } catch(e) { alert("No se puede realizar la actualización de datos, consulte con soporte técnico") xmlhttp = false; } // branch for IE/Windows ActiveX version } else if(window.ActiveXObject) { try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {
alert("No se puede realizar la actualización de datos, consulte con soporte técnico") xmlhttp = false; } } } } return xmlhttp; }
function supportsDynamicLabels() { return document.getElementById && (window.attachEvent ||window.addEventListener) && null == navigator.appVersion.match(/Safari/d+$/); }
function handleHttpResponse() {
if (http.readyState == 4) { // Split the comma delimited response into an array results = http.responseText; if (http.status == 200) { if(results=="OK" ){ document.getElementById("loading").innerHTML="OK:<br>Base de datos actualizada."; } else{ document.getElementById("loading").innerHTML="Hubo un problema actualizando, inténtelo de nuevo, y si devuelve error, por favor, consulte soporte técnico"; } }else{ document.getElementById("loading").innerHTML="Hubo un problema actualizando, inténtelo de nuevo, y si devuelve error, por favor, consulte soporte técnico"; } setTimeout('document.getElementById("loading").style.display="none"',1500); } } function getHTTPObject() { var xmlhttp; if (!xmlhttp) { if(window.XMLHttpRequest) { try { xmlhttp = new XMLHttpRequest(); } catch(e) { alert("No se puede realizar la actualización de datos, consulte con soporte técnico") xmlhttp = false; } // branch for IE/Windows ActiveX version } else if(window.ActiveXObject) { try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {
alert("No se puede realizar la actualización de datos, consulte con soporte técnico") xmlhttp = false; } } } } return xmlhttp; } var http = getHTTPObject(); // We create the HTTP Object
function updateDatos(){
document.getElementById("loading").style.display="block";
var urldatos = "xmlhttp_insert.cs.asp?"; // The server-side script var metaValue = document.getElementById("metatags").value; var descripValue=document.getElementById("descripcion").value; var descriplargaValue=document.getElementById("descripcionlarga").value;
strUrl=urldatos + "metas=" +escape(metaValue) + "&descrip="+ escape(descripValue)+"&descriplarga="+escape(descriplargaValue); if(http){ //http.open("HEAD", "/faq/index.html",true); // http.onreadystatechange=function() { //if (http.readyState==4) { //alert("Status is "+http.status) //} //} http.open("GET",strUrl, true); http.onreadystatechange = handleHttpResponse; http.setRequestHeader('Accept','message/x-jl-formresult') http.send(null); } else{ alert("Hubo un problema al conectar. Consulte con soporte técnico"); } }
function addEvent(objObject, strEventName, fnHandler) { if (objObject.addEventListener) objObject.addEventListener(strEventName, fnHandler, false); else if (objObject.attachEvent) objObject.attachEvent("on" + strEventName, fnHandler); }
function setupLabels() {
addEvent(document.getElementById("grabar"),"click",updateDatos); }
if (supportsDynamicLabels()) { addEvent(window, "load", setupLabels); }
</script>
<BODY> <div id="loading" style="display:none;BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; FONT-WEIGHT: bold; FONT-SIZE: 12px; LEFT: 50px; BORDER-LEFT: black 1px solid; WIDTH: 200px; COLOR: crimson; PADDING-TOP: 20%; BORDER-BOTTOM: black 1px solid; FONT-FAMILY: verdana; POSITION: absolute; TOP: 50px; HEIGHT: 100px; BACKGROUND-COLOR: lightgrey; TEXT-ALIGN: center"> Actualizando </div> <div id="lblError"> </div> <form id="detalles" name="detalles" method="post"> <table cellpadding="0" cellspacing="0" border="0"> <tr> <td nowrap="nowrap" class="items">Metatags:</td><td> <textarea cols="40" rows="2" name="metatags" id="metatags"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items">Descripción:</td><td> <textarea cols="40" rows="2" name="descripcion" id="descripcion"></textarea> </td> </tr> <tr> <td nowrap="nowrap" class="items">Descripción larga:</td><td> <textarea cols="40" rows="2" name="descripcionlarga" id="descripcionlarga"></textarea> </td> </tr> </table> <div id="grabar" class="buttons1"><a href="#">Grabar</a></div> </form>
|
|
|
Blog
Categorías
Calendario
| <<
Abril 2006
|
| L | M | Mi | J | V | S | D |
| |
|
|
|
|
1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
Archivos
Sindicación
Apúntate
Enlaces
Alojado en

|