HTML5: Lograr que un campo number acepte decimales

Una de las características de HTML5 era que permitía definir campos de tipos variados que ampliaban las opciones respecto al tradicional tipo text del HTML clásico.  Estos campos, además tienen la capacidad de autovalidarse.

Estos nuevos campos, por otra parte, requieren conocer todas sus opciones para exprimirlos a tope. Por ejemplo, si declaras un campo como el siguiente:

<input type="number" name="numero" />

En este caso te encontrarás con que si pones un número decimal la validación del navegador te dirá que está incorrecto. Pero tú sabes que no lo está ¿por qué pasa esto? Bueno, puedes arreglarlo de una forma muy simple: con el atributo step.

La mayoría de los navegadores mostrarán dos flechas en los campos de tipo number, para aumentar y decrecentar su valor. En step podemos definir cuánto queremos que este valor suba o baje en cada click. Por ejemplo:

<input type="number" step="5" name="numero" />

De esa form el valor irá cambiando de 5 en 5.

Pero esto de momento no nos soluciona el problema ¿cómo logramos que trague un decimal? Pues definiendo en step que el valor sea decimal.Si ponemos el valor de step como «0.01» nos permitirá meter decimales con dos cifras. Entonces si ponemos nuestro campo:

<input type="number" step="0.01" name="numero" />

Así tenemos un campo que admite dos cifras decimales, que suele ser lo más habitual. Si queremos más precisión entonces metemos más decimales en el step. Otra opción es añadir directamente el valor any a step. De esta forma permitirá meter tantos decimales como queramos.

<input type="number" step="any" name="numero" />

Visual Studio 2015: Borrar una solución

Pues nada, que me han actualizado a Visual Studio 2015 y que andaba yo intentado borrar un proyecto, de hecho la solución completa, que me había liado creándolo… y no encontraba la manera de hacerlo. ¿Cómo va esto? ¿cómo borro toda la solución? Bueno, los menús los tengo en inglés, así que os cuento paso a paso:

  • En el explorador de soluciones (Solution Explorer) seleccionáis la solución que queréis borrar.
  • Después, en la barra de menú superior os váis a Archivo (File) y allí pulsáis Cerrar Solución (Close Solution).
  • Y para acabar, os vais a la carpeta donde teníais guardado el proyecto y allí borráis todos los archivos.

Y listo, solución borrada.

jQuery: pulsar F11 y evitar entrar en modo pantalla completa

Un cliente tenía una petición curiosa: quería que su web mostrara un menú al pulsar la tecla F11 (habían migrado de una aplicación de escritorio a una web y estaban acostumbrados a pulsar F11 y que saliera eso) ¿Qué ocurre? Pues que F11 es la tecla que activa el modo a pantalla completa del navegador.

¿Se puede hacer esto? Sí, tenía mis dudas pero sí. Tenía mis dudas porque las teclas de función no siempre pueden sobreescribirse para limitar el comportamiento del navegador (por ejemplo, creo que con F5 o con F1 no sería posible). Pero F11, al menos en IE10, Chrome y Firefox sí puede ser deshabilitada. Os dejo el código, es javascript usando la librería jQuery:

$(document).keydown(function(event) {
  event.preventDefault();
    if (event.keyCode == 122) { // 122 es el código de F11
      event.originalEvent.keyCode = 0;
      window.alert("no dejo maximizar");
    }
});

Lógicamente, en lugar del window.alert ahí ya pondríais el código que queráis ejecutar en vuestra aplicación web.

Javascript: convertir los saltos de línea de un textárea en un salto de línea html.

Se daba el caso hoy de que tenía que recoger el texto extraído de un textarea, mediante javascript, y mostrarlo dentro de un div al pulsar un botón en pantalla. ¿Y qué problema había? Que los saltos de línea desaparecían. ¿Cómo se puede solucionar? De dos formas: Hay con vertir el caracter ASCII(10), que se representa con el símbolo \n en una etiqueta br, o como otra opción meter el texto entre etiquetas pre para que sea interpretado por el navegador como texto preformateado. Veamos el ejemplo:

//usando jQuery
var texto = $('#idDelTextarea').val();
texto = texto.replace(/\n/g, "<br />");
$("#idDelDiv").html(texto);

//sin jQuery
var texto = document.getElementById("idDelTextarea").value;
texto = texto.replace(/\n/g, "<br />");
document.getElementById("idDelDiv").innerHtml = texto;

//con <pre>
//recogemos el texto con alguno de los métodos anteriores
texto = "<pre>" + texto + "</pre>";
//y lo metemos en el div

Una herramienta online para transliteración a alfabeto latino

La historia es corta: un cliente quiere una traducción de su web al ruso y ha mandado los textos, pero quiere que las secciones en la URL también estén en ruso. La mejor opción, para los buscadores y por las características del hosting, es la transliteración del alfabeto cirílico al latino. ¿Qué es la transliteración?  Simplemente representar los caracteres de un alfabeto utilizando otro.

¿Qué herramiente he usado para ello? Pues me he servido de esta web que os enlazo aquí. Además de ruso ofrece otras opciones como serbio, japonés, griego, armenio, georgiano, cheroqui. A mi me ha cumplido la función prefectamente.

Aprender Git (y GitHub) en 15 minutos

Git es un sistema de control de versiones creado por Linus Torvalds en su día para facilitar el trabajo en el desarrollo del núcleo de Linux. Su buen funcionamiento, su flexibilidad y el ser software libre ha facilitado su popularización entre los programadores y su uso tanto en el ámbito académico como empresarial.

GitHub logo

Los principales comandos de Git serían los siguientes:

  •  git fetch: para descargar los cambios desde el repositorio
  • git merge: permite unir dos «ramas» de un proyecto
  • git pull: básicamente unificaría las acciones de fetch y merge en un solo comando
  • git commit -am: confirma los cambios realizados. Se puede añadir como parámetro una cadena de texto con un título descriptivo para que al consultar el log veamos qué hemos heco de forma más sencilla
  • git push origin: nos permite subir una «rama» al servidor
  • git status: nos muestra el estado de una rama y qué cambios hay sin confirmar
  • git add: añadimos un archivo
  • git checkout -b: crea una «rama» nueva a partir de donde estamos, con el nombre que le asignemos
  • git checkout -t: en este caso nos permite crear una «rama» local a partir de una «rama» remota especificada.
  • git branch: nos permite listar las ramas locales
  • git branch -a: con este parámetro además de las ramas locales muestra las remotas.
  • git branch -d: borra la rama que le especifiquemos como parámetro
  • git remote: muestra los repositorios remotos
  • git remote -v: muestra los repositorios remotos y la url asociada a ellos
  • git remote prune origin: permite actualizar tu repositorio remoto desde tu versión local en caso de que alguien haya borrado una rama remota.
  • git push origin: :Ojo a esta sintaxis, te mando a la documentación para que la ojees porque es puñetera. La cosa es que borre una «rama» remota y es similar a la orden para subirla, pero con la diferencia de que añade los dos puntos (sí, no me equivoqué y los puse duplicados). Mira el enlace para verlo bien.
  • git reset –hard HEAD: elimina los cambios que no hayan sido objeto de un commit todavía
  • git revert: en este caso le pasamos el id de un commit para deshacer los cambios que realizamos en él.

El tema de listar los comandos es útil, pero yo te prometía aprender a usar Git, y por extensión la popular plataforma web GitHub, en 15 minutos. Y por mucho que te leas un listado de comandos no vas a aprender por ósmosis… pero aquí viene el recurso que necesitas: un minicurso de uso de Git a través de la plataforma GitHub. Pégale un ojo y la cosa te quedará mucho más clara, que seguro que la lista de arriba te ha dejado dudas. A través de sencillos ejercicios el tutorial te mostrará el funcionamiento de la plataforma en poco más de un cuarto de hora. Aprovecha ya y añade Git a tu lista de conocimientos, pues es una utilidad valiosa.

Las palabras reservadas let y const en javascript

No conocía la existencia de let, la descubrí ayer porque había usado una variable llamada let en un artículo de 2011 que hablaba sobre cómo validar un DNI con javascript, y me comentaron «let es una palabra reservada«. Mi cara fue como ¿ein? ¿desde cuando? Así que me puse a buscar… y sí, desde la irrupción de ECMAScript 6 en junio de 2015 tenemos una palabra reservada para definir variables que es let,  otra que es const para las constantes.

Sobre const no hay mucho que decir ya que el nombre es muy descriptivo: nos permite definir una constante. ¿Qué es una constante? Pues piensa en una variable pero que sólo puede recibir un valor en el momento de su declaración y que luego ya no puede ser modificada. Te pongo un ejemplo:

/*Declaramos PI como constante*/
const PI = 3.1415926;

/*Esto daría error*/
PI = 3.1416;
/*Porque no se puede volver a dar*/
/*valor a una constante*/

Vamos ahora con let, que tiene más chicha. Citando textualmente la documentación permite declarar variables limitando su alcance (scope) al bloque, declaración, o expresión donde se está usando. ¿Qué diferencia hay con var? Que var nos permite declarar una variable global o una variable local dentro de una función, pero no nos permite limitar su ámbito a un bloque de código concreto. Veamos un ejemplo:

/*Hagamos el ejemplo al viejo estilo*/
/*usando var*/
function PruebaVar() {
  var v = 45;
  if (true) {
    var v = 64;  // es la misma variable
    console.log(v);  // imprime 64
  }
  console.log(v);  // imprime 64
}
/*vemos como el v de dentro del bloque y el de fuera son
la misma variable. Si modificamos su valor dentro del bloque
fuera también está modificado */

/*vamos con let*/
function PruebaLet() {
  let l = 45;
  if (true) {
    let l = 64;  // diferente ámbito
    console.log(l);  // imprime 64
  }
  console.log(l);  // imprime 45
}
/*Con let en cambio la variable l de fuera del
bloque y la de dentro son tomadas como variables
diferentes, y cada una conserva el valor que
se le dio en su ámbito.*/

El uso de let y const sólo está disponible en bloques envueltos en una etiqueta <script type="application/javascript;version=1.7"> o en una versión superior.

Creando una tabla con los bordes redondos con CSS3

¿Cómo puede redondear los bordes de una tabla con CSS? Ponerle bordes al objeto table o al tr no va a funcionar, hay que hacerlo sobre el primer o el último td de la fila.

table { border-collapse: separate; }
td { border: solid 1px #000; }
/*PARA LA PRIMERA FILA TIENES DOS OPCIONES*/
/*Así sería la cosa
si has empezado con un tr
*/
tr:first-child td:first-child { border-top-left-radius: 10px; }
tr:first-child td:last-child { border-top-right-radius: 10px; }
tr:first-child td:only-child { border-top-right-radius: 10px;
border-top-left-radius: 10px; }
/*si en lugar de eso has usado la etiquetas thead y th es más
sencillo todavía*/
th:first-child { border-top-left-radius: 10px; }
th:last-child { border-top-right-radius: 10px; }
th:only-child { border-top-right-radius: 10px;
border-top-left-radius: 10px; }

/*Y ASÍ PONEMOS EL PIE*/
tr:last-child td:first-child { border-bottom-left-radius: 10px; }
tr:last-child td:last-child { border-bottom-right-radius: 10px; }
tr:last-child td:only-child { border-bottom-right-radius: 10px;border-bottom-left-radius: 10px; }

Obteniendo un objeto con los datos de un código postal en Google Maps

Van a venir una serie de entradas sobre Google Maps próximamente, y espero que también sobre Open Street Map. Vamos con una simple y cortita ¿cómo podemos obtener un objeto con los datos de un código postal concreto? El API de Google Maps nos permite pedírselos y nos los devuelve en formato XML o JSON.

Vemos dos ejemplos prácticos, el primero nos devuelve el JSON:
http://maps.googleapis.com/maps/api/geocode/json?address=15330&region=ES&sensor=false

Y este es la versión con XML:
http://maps.googleapis.com/maps/api/geocode/xml?address=15330&region=ES&sensor=false

La sintaxis sería la siguiente:

  • Primero la llamada al API de geocodificación de Google Maps: http://maps.googleapis.com/maps/api/geocode/
  • Seguidamente el formato, que puede ser xml o json
  • Como parámetros pasamos en address el código postal, y en region el país (si no buscará en los EEUU por defecto).

En los próximos días seguiremos tratando el tema.

Clase para prevenir ataques XSS en Java

Buscando información para aumentar la seguridad de una aplicación web basada en Java me encontré con esta clase para filtrar los posibles ataques XSS en la web de un veterano ingeniero llamado Ricardo Zuasti.

Su solución propone dos clases. La primera, que copio de su entrada original a continuación, lo que hace es filtrar las peticiones HTTP para que sean filtradas por la clase especializada creada para eso:

public class XSSFilter implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void destroy() {
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
    }
 
}

Tras esto propone la siguiente clase para realizar el filtrado. Esta clase sobreescribe los métodos getParameterValues(), getParameter() y getHeader() y utiliza una serie de patrones para evitar la entrada de código malicioso en tu web. El método stripXSS() es el que realiza la labor de filtrado.

import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
public class XSSRequestWrapper extends HttpServletRequestWrapper {
 
    private static Pattern[] patterns = new Pattern[]{
        // Script fragments
        Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
        // src='...'
        Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // lonely script tags
        Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
        Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // eval(...)
        Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // expression(...)
        Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
        // javascript:...
        Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
        // vbscript:...
        Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
        // onload(...)=...
        Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
    };
 
    public XSSRequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
    }
 
    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
 
        if (values == null) {
            return null;
        }
 
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = stripXSS(values[i]);
        }
 
        return encodedValues;
    }
 
    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
 
        return stripXSS(value);
    }
 
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        return stripXSS(value);
    }
 
    private String stripXSS(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
 
            // Avoid null characters
            value = value.replaceAll("\0", "");
 
            // Remove all sections that match a pattern
            for (Pattern scriptPattern : patterns){
                value = scriptPattern.matcher(value).replaceAll("");
            }
        }
        return value;
    }
}

Entre las recomendaciones que da en el artículo original está la de configurar este filtro como el primero en tu web.xml y también, en referencia al código que aparece comentado en la segunda clase, echarle un ojo a la librería ESAPI, que nos proporciona diversas soluciones de seguridad.

Desde aquí sólo me queda enviarle mi agradecimiento por su trabajo al señor Zuasti y animarle a recuperar su blog, que tiene material interesante pero hace tiempo que no actualiza.