a nil value

Blog sobre programación e informática en general (Por Guillermo Zafra)

Browsing Posts in trucos

Quizás en alguna ocasión hayamos querido mostrar una ventana “estilo modal” por encima del resto del formulario. Es algo muy usado en la programación web y que aumenta de forma considerable la usabilidad del interfaz. Sin embargo, en aplicaciones con muchos controles, nos hemos podido encontrar con un desagradable problema, y es que los controles asp.net DropDownList (Select en HTML) ignoran totalmente el estilo z-index de las capas, y como consecuencia aparecen por encima de nuestra ventana modal, estropeando todo el buen aspecto de la aplicación.

Existen dos soluciones conocidas al problema:

La primera, aunque funciona, conlleva la creación de un script que carga mucho trabajo a la aplicación, y según la cantidad de controles que tengamos, puede no ser una posible alternativa.

for (f = 0; f < document.forms.length; f++)
{
    var elements = document.forms[f].elements;
    // looping through all elements on certain form
 
    for (e = 0; e < elements.length; e++)
    {
        if (elements[e].type == "select-one")
        {
            elements[e].style.display = 'none';
        }
    }
}

Este script recorre todos los controles de nuestro formulario, ocultando aquellos que sean del tipo Select. Claro que si tenemos un número finito de este tipo de controles podemos obviar el bucle e ir directamente al grano.

Una vez los tengamos ocultos podemos mostrar nuestra ventana modal sin riesgo a que sea destrozada por los Select, que estarán ocultos.

Por supuesto hay que controlar que, una vez hayamos acabado con la ventana modal, hay que volver a mostrar estos controles usando el mismo sistema.

La segunda alternativa es mas interesante todavía, aunque parece más un “hack” que otra cosa, y desconozco hasta que punto sería compatible con todos los navegadores. Consiste en hacer uso del elemento “iframe”. Este elemento tiene la característica de aparecer siempre por encima de cualquier otro control web, es decir, incluso por encima de los DropDownList. Y diréis, ¿pero eso no sustituye un problema por otro? Nó exactamente, ya que este elemento admite el estilo z-index y ¡lo cumple!.

Vamos, que podemos mostrar una especie de panel separador entre los controles DropDownList y la ventana modal que queramos mostrar tan solo asignandole un z-index inferior al de nuestra ventana.

Primero añadiríamos el iframe dentro de la ventana que vamos a ocultar y mostrar. Tan solo se mostrará cuando mostremos la ventana.

<iframe id="iframe" class="iframeLayer" frameborder="0"></iframe>

Y segundo, añadiremos el estilo correspondiente tal que:

iframe.iframeLayer
{
    left:600px;
    top:300px;
    position: absolute;
    width: 200px;
    height: 100px;
    z-index: 10;
 
}

Hay que tener especial cuidado en especificar exactamente la misma posición y tamaño que la ventana modal. El iframe se mostrará como un area blanca y ocultará todo lo que esté debajo suyo, pero mostrará nuestra ventana siempre que tenga un z-index superior a 10.

El problema de este método es que queramos crear algo más complejo, o por ejemplo crear un fondo transparente, ya que en ese caso, en lugar de crear un iframe para el area de la ventana, tendremos que crear un iframe para el area de cada control DropDownList que tengamos, lo cual ya es otra historia.

La elección es vuestra. Un saludo

Fuente: CodeProject

Cuando creamos un instalador para alguno de nuestros proyectos de Visual Studio podemos necesitar incluir como requisito tener instalada algun paquete o complemento e incluso podermos querer añadirlo al instalador para que, si no está instalado, lo haga.

A esto se le conoce como Bootstrapping y es bastante sencillo.

Para ello lo primero que tenemos que hacer es crear un paquete personalizado para cada complemente que queramos añadir como prerrequisito a nuestro instalador. Por ejemplo, si queremos hacer un instalador para nuestra aplicacion y nos damos cuenta de que requiere el Adobe Reader, podemos hacer un paquete llamado AdobeReader con el redistribuible del Adobe Reader.

Antes de nada saber que estos paquetes se añaden desde Visual Studio a la hora de crear un instalador. Dentr del proyecto de instalación, si vamos a Propiedades del proyecto y ahí a Requisitos Previos obtendremos una lista de los paquetes por defecto que se incluyen en el SDK de Visual Studio, que será similar a la siguiente imagen:

Cada uno de estos requisitos equivale a una carpeta con un ejecutable, unos manifiestos (XML) y otros archivos opcionales de configuración.
Todos estos paquetes se encuentran en una ruta del disco que dependerá de la versión de Visual Studio que estemos utilizando:

Visual Studio 2005: C:\Archivos de programa\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages
Visual Studio 2008: C:\Archivos de programa\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages

Por lo que lo primero que debemos hacer es ir a la ruta que nos corresponda y crearnos una carpeta con el nombre de nuestro paquete, en nuestro caso “AdobeReader”.

El siguiente paso será meter en dicha carpeta el ejecutable que nos instala el AdobeReader. (Hay que tener en cuenta que existen dos versiones de este instalable, al igual que en muchos otros. Una completa que se instala completamente offline y otra online que descarga contenido desde Internet. La primera hara más pesado el contenido de la instalación pero no requerirá acceso a Internet, y la segunda pues obviamente lo contrario)

El tercer paso es crear el manifiesto “Product.xml”. Vamos, crear un XML con este nombre al que añadiremos lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<Product ProductCode="AdobeReader" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
  <PackageFiles CopyAllPackageFiles="false">
    <PackageFile Name="AdobeReader-setup.exe" Hash="F774D8891793C46BDDC1F9418D8E427B6CBAE26D" />
  </PackageFiles>
  <InstallChecks>
    <FileCheck Property="" SpecialFolder="ProgramFilesFolder" SearchPath="C:\Archivos de programa\Adobe\Reader 8.0\Reader" FileName="AcroRd32.exe" />
  </InstallChecks>
  <Commands Reboot="Defer">
    <Command PackageFile="AdobeReader-setup.exe">
      <ExitCodes>
        <DefaultExitCode Result="Success" String="Anunexpectedexitcodewasr" FormatMessageFromSystem="true" />
      </ExitCodes>
    </Command>
  </Commands>
</Product>

Este es el manifiesto obligatorio para que el paquete sea reconocido por el Visual Studio. Pero también tenemos el manifiesto “Package.xml” que añadirá información adicional a nuestro paquete tal como un EULA, o el idioma de la instalación:

<?xml version="1.0" encoding="utf-8" ?>
<Package
  xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"
  Name="AdobeReader"
  Culture="Culture"
  LicenseAgreement="eula.txt">
 
  <PackageFiles>
    <PackageFile Name="eula.txt"/>
  </PackageFiles>
 
  <Strings>
    <String Name="DisplayName">AdobeReader</String>
    <String Name="Culture">es</String>
    <String Name="NotAnAdmin">Debes tener permisos de administrador para poder ejecutar este paquete.</String>
    <String Name="GeneralFailure">A ocurrido un error al intentar instalar el paquete.</String>
  </Strings>
</Package>

En este caso, si añadimos una referencia a “eula.txt” tendremos que añadir el correspondiente fichero con el texto que se deberá mostrar en el EULA.

El cuarto paso es importante, y es que si tenemos el Visual Studio instalado en la lengua de Shakespeare, tendremos que añadir un manifiesto por defecto para dicho idioma. Bastará con crear una carpeta llamada “es” dentro de nuestro paquete y poner una copia del fichero “Product.xml” dentro.

Y ya está! Si volvemos a la ventana del Visual Studio donde se mostraban los prerrequisitos por defecto veremos que aparece nuestro paquete “AdobeReader”. Molto facile e divertente.

Y ahora viene la parte buena, que la he puesto al final para joder un poco, que hay que saber cómo funcionan las cosas y hacerlas a lo Clint Eastwood antes de recurrir a lo fácil. Y es que existe una maravillosa herramienta de Microsoft que nos hace todo el trabajo en unos cuantos clicks. Se llama Bootstrapper Manifest Generator y se puede obtener gratuitamente desde la siguiente URL:

http://code.msdn.microsoft.com/bmg

La aplicación es bastante sencilla y nos da la posibilidad de crear manifiestos mas complejos añadiendo condiciones y otros parámetros de configuración.

Espero que fuera de ayuda para alguien que lo necesite.

Un saludo

Cuando se trabaja de forma asíncrona con AJAX y UpdatePanels resulta imprescindible implementar procesos para informar al usuario de que se están efectuando actualizaciones en el servidor.

Por defecto, ASP.NET AJAX nos proporcionar el complemento UpdateProgress, que unido a un ScriptManager y un UpdatePanel permiten mostrar cualquier indicador mientras el UpdatePanel esta trabajando asíncronamente.

No obstante el UpdateProgress es limitado si queremos realizar tareas o efectos mas complicados. Por ejemplo posicionar el loader dinamicamente en la pantalla segun lo que se actualice, realizar alguna accion de Jscript antes de comenzar la actualización, o permitir al usuario cancelar el proceso.

Para ello existe un maravilloso y muy simple javascript que controla dos eventos importantísimos de la página; el comienzo y el fin del httprequest.

<script language="javascript" type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(
  function(sender, e)
  {
        $get('cargador').style.display="block";
   });
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
  function(sender, e)
  {
        $get('cargador').style.display="none";
   });
 
</script>

Donde “cargador” podría ser, por ejemplo:

<div id="cargador" runat="Server" style="display:none">
        <table width="200">
            <tr>
                <td height="50" valign="bottom" align="center">Cargando...</td>
            </tr>
            <tr>
            <td height="50" valign="top" align="center"><img alt="cargando..." src="../img/ajax-loader.gif" /></td>
            </tr>
        </table>
    </div>

add_beginRequest se lanzaría antes de comenzar el evento de solicitar información al servidor y add_endRequest justo despues de terminar todo el proceso.

Para cancelar el Request bastaría con mostrar un boton en el beginRequest que lanzara el siguiente script:

function CancelarPostback() {
    var man= Sys.WebForms.PageRequestManager.getInstance();
    if (man.get_isInAsyncPostBack())
        man.abortPostBack();
    }

Aunque ojo! con este “Cancelar” ya que, si bien cancelara el request y forzando el endRequest, el proceso en el servidor es muy probable que se haya ejecutado ya. Mi consejo es que se utilice unicamente para procesos de lectura y no de escritura.

Un saludo

Bueno, esta es sencilla y fácil de encontrar pero nunca se sabe cuando puede ser útil. Ahora bien, puede confundir al usuario.

<asp:CheckBox runat="server" ID="chkPrueba" onclick="cambiarTextoCheckBox(this);" />

Y la función Javascript:

function cambiarTextoCheckBox(checkbox)
{
  if (checkbox.checked)
    checkbox.nextSibling.innerHTML = 'Activado';
  else
    checkbox.nextSibling.innerHTML = 'Desactivado';
}

Siguiendo con la temática del artículo anterior sabemos que conseguir un postback es tarea fácil con la mayoría de los controles web de ASP.NET, pero puede ocurrir que queramos forzar a la página a realizar una acción de postback desde un lugar que no este preparado para ello.

Para conseguir esto utilizaremos la funcion __dopostback:

function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}

Donde eventTarget es el control que realiza el postback y eventArgument el argumento que queremos enviar junto con el postback (si es que queremos).

Llamando a esta función desde cualquier evento de cualquier control HTML conseguiremos enviar la página al servidor. Especialmente útil cuando si estamos generando controles dinámicamente que realicen postbacks al servidor y queremos controlarlas manualmente.

Un saludo

Si hemos jugado con las opciones de Google Chrome, nos habremos fijado en que este utiliza la misma configuración de red que Internet Explorer, es más, al abrir la configuración de red de Chrome nos abrirá la de Internet Explorer, impidiéndonos utilizar una configuración independiente para Chrome.

Esto es un problema si por ejemplo queremos utilizar Chrome para navegar a través de un proxy y Explorer unicamente para depurar nuestras aplicaciones web.

Podemos solucionarlo de manera sencilla añadiendo el parámetro –proxy-server en la ruta de ejecución del programa. Para esto haremos lo siguiente:

1.- Creamos un acceso directo a Google Chrome (Si no tenemos ya uno)
2.- Editamos sus propiedades
3.- Vamos a “Destino” y añadimos al final de la ruta despues del ejecutable chrome.exe lo siguiente: –proxy-server=[servidor]:[puerto] indicando obviamente el nombre o IP del servidor y número del puerto.

Por ejemplo:
“C:\Documents and Settings\usuario\Configuración local\Datos de programa\Google\Chrome\Application\chrome.exe” –proxy-server=localhost:8080

Si quisiéramos ignorar un proxy configurado en Internet Explorer bastaría con dejarlo vacio (EJ: –proxy-server=)

Un saludo

Una técnica frecuente cuando realizamos grandes proyectos web es crear un log o registro de todos los errores que suceden en el servidor de nuestra aplicación web, de manera que, aunque no estemos depurando podamos conocer cuando y donde falla nuestra aplicación. Es especialmente útil cuando es utilizada por un gran numero de usuarios, pues estos siempre acaban encontrando fallos.

Sin embargo, en muchos casos, nos habremos dado cuenta de que la descripción del error que nos aparece, a pesar de ser muy detallada, no nos da una información esencial, la clase donde ocurre el error y la linea.

Estos datos se obtienen facilmente en el equipo local cuando depuramos, pero se pierden cuando la aplicación se ejecuta en el servidor con el debug desactivado. Para añadir esta información a la descripción del error deberemos hacer dos cosas:

1.- En las propiedades del proyecto, dentro del Visual Studio, debemos ir a la pestaña Compilar y a Opciones de compilación avanzadas. Dentro cambiaremos “Generar información de depuración” a pdb-only.

2.- Ahora solo tenemos que volver a generar nuestra aplicación y recordar subir el fichero .pdb del proyecto que se genera junto a la dll en la carpeta “bin”.

Con este método obtendremos en la información del Stack, el nombre del fichero donde ocurre el error y la linea exacta en la que se lanzó la excepción.

Otro día explicaré el método entero parar generar un log de errores, pero esto, mediante un poco de Google, es bastante sencillo.
Saludos

Powered by WordPress Web Design by SRS Solutions © 2010 a nil value Design by SRS Solutions