Javascript: cerrar una ventana automáticamente cuando se cierre el diálogo de impresión.

Veamos el caso práctico que me encontré: una aplicación web que para imprimir un documento abre un popup con la previsualización del mismo, cuando pulsas el botón de imprimir debería abrirse el diálogo de impresión y después de aceptar el popup debería cerrarse… pero resulta que si bien en el Safari y el Internet Explorer lo hace correctamente, en el Chrome o en el Firefox se cierra la ventana antes de que se abra el diálogo de impresión. ¿Cómo hacemos para que se cierre en todos los navegadores automáticamente esa ventana tras confirmar el diálogo de impresión?

Pues como el objeto window en Javascript es capaz de reconocer el evento de que se ha cerrado la ventana de impresión (evento onafterprint), bastará con que programemos que se ejecute window.close() cuando se de dicho evento. El código sería:

window.onafterprint = function () {
    window.close();
}

Sobreescribir la función javascript window.alert() nativa del navegador por una personalizada

Resulta me veía con una cuestión trabajosa: en una aplicación web tenía que hacer una ventana de alerta personalizada que sustituyera al window.alert() nativo del navegador. La parte de diseñar la nueva ventana no era tan laboriosa, la labor pesada y repetitiva venía del tener que localizar todas las ocurrencias de window.alert() diseminadas por el código y cambiarlas por la nueva función. Y ahí pensé «¿y si pudiera cambiar el window.alert() por la nueva función?«. Hay un fichero de javascript que está presente en todas las pantallas, así que solo tendría que introducirlo allí.

¿Y cómo reescribimos la función window.alert()? Pues simplemente así:

window.alert = function(){}

Asignando una nueva función a window.alert() sobreescribe su comportamiento nativo por el indicado. Veámoslo de nuevo con más o menos todo el código que lleva:

//alert personalizado, recibe el mensaje a mostrar y el elemento sobre el que poner el foco si es un mensaje de error
window.alert = function(msg,el,isError){
	var left = parseInt((screen.width - 750) / 2);
	var top = parseInt((screen.height-300)/2);
	var ventana = window.open("AvisoNuevo.asp?e="+isError+"&m="+msg,"modal","width=750,height=300,top="+top+",left="+left+",scrollbars=auto,resizable=no,menubar=no,toolbar=no");	
	if(isError && el!=null && el!="" && el!=false){			
		try {
		  document.getElementById(el).focus();
	    }
	     catch (e) { return; }
	}
}

Electron.js: Error «require is not defined» y conflictos entre require y jQuery.

Aquí sigo trabajando en mi primera aplicación corriendo sobre Electron.js y me están saliendo canas por diversos errores que me aparecen a la hora de integrar. Uno de ellos ha sido recibir constantemente el error «require is not defined«. Una de las causas de este error suele ser que la integración con NodeJS está deshabilitada, por seguridad este parámetro viene deshabilitado por defecto para evitar ataques que puedan, por ejemplo, borrar ficheros de nuestro equipo remotamente si cargamos una página no segura. En caso de que estemos cargando una aplicación local podemos ir al main.js y activarlo desde allí configurando las preferencias de nuestro ventana web:

 webPreferences: {
            contextIsolation: false,
            nodeIntegration: true,
            nodeIntegrationInWorker: true,                                                  
            enableRemoteModule: true                                                                     
 }

Es posible que esta configuración nos genere un nuevo conflicto entre jQuery y NodeJS ya que ambos intentan sobreescribir la función require(). Esto puede solucionarse añadiendo esta línea antes de la carga de jQuery:

<script>
		window.nodeRequire = require;
		delete window.require;
		delete window.exports;
		delete window.module;
</script>

Trasponer una matriz en Python

La definción técnica del término matriz traspuesta es «el resultado de reordenar la matriz original mediante el cambio de filas por columnas y las columnas por filas en una nueva matriz». Imaginemos que tenemos un array en Python tal que así:

x = [[1,2,3],
  [2,3,1],
  [3,1,2]]

Ahora queremos meter esa matriz en otra variable, pero tras trasponerla. Si bien en la mayoría de los lenguajes es posible trasponer la matriz utilizando una serie de bucles anidados, en Python podremos hacerlo de forma muy sencilla sirviéndonos de la función zip() y el operador *. Para almacenar la matriz traspuesta en otra variable bastaría con hacer:

y=zip(*x)

Y solo con esa línea ya habría traspuesto nuestra matriz original.

Electron.js: obtener el nombre, la versión o la arquitectura de nuestro sistema operativo

Bueno, pues hace unas semanas que en el trabajo estoy currando con el framework Electron.js, que básicamente nos permite transformar aplicaciones web en aplicaciones nativas de escritorio. En mi caso es para actualizar un software de intranet que dependía de ActiveX y de Internet Explorer en exceso. En todo caso vamos a ver algunas cosillas sobre Electron, una de ellas es ¿cómo puedo obtener los datos sobre mi sistema operativo? Pues Electron incluye un módulo para eso:

Lo primero será importar el módulo «os«, para que la aplicación pueda trabajar con el sistema operativo anfitrión. Para el ejemplo crearemos una variable llamada también os (por recordarlo bien) para almacenar dicho objeto:

var os = require("os");

Ahora veamos ¿cómo haríamos para ver la arquitectura de nuestro sistema operativo? Pues llamando al método arch().

var arquitectura = os.arch();

¿Y para ver el nombre del sistema operativo? Pues tenemos dos opciones: el método type() nos devolverá el tipo genérico (Linux, Darwin o Windows) y el método platform() nos devolverá un resultado más concreto (darwin,freebsd,sunos,win32…). Finalmente el método version() nos devolverá la versión del sistema operativo:

var tipo = os.type();
var plataforma = os.platform();
var version = os.version();

Acceder al último elemento de un array en Javascript

Algunos lenguajes nos permiten acceder al último elemento de un array usando el índice en negativo (es decir, poniendo la posición -1) pero no es el caso de Javascript. En ese caso ¿cómo accedo al último elemento de un array? Bueno, si se trata de un lenguaje donde podamos conocer la longitud del array como es Javascript (y la mayoría de lenguajes modernos realmente) basta con usar dicha longitud como índice. En el caso concreto de Javascript tendríamos que usar la propiedad length del array pero restándole una posición (porque nunca hay que olvidar que los arrays empieza en 0):

var ultimoElemento = myArray[miArray.length - 1];

Convertir texto en inglés a 1337 con Javascript

Si ayer veíamos cómo hacer con javascript una función que codifique/descodifique un simple cifrado ROT13 hoy vamos a con otro ejercicio de javascript simple: un conversor inglés-1337.

1337, leet, leet speak o 1337 5p34k es un tipo de escritura compuesta por caracteres alfanuméricos y relativamente popular en ambientes informáticos. No se trata de ningún tipo de cifrado de mensajes, simplemente se sustituyen las letras por número o por conjuntos de símbolos cuyo aspecto recuerde al de dicho caracter.

La función sería algo así: recibe un texto escrito en el alfabeto latino internacional y lo devuelve en 1337. Creamos un objeto con todos los valores a sustituir llamado leetAlph para que nos facilite el trabajo, luego solo recorremos la cadena que recibimos como si fuese un array (en esencia toda cadena es una array de caracteres) y vamos cambiando en cada posición la letra por el valor que le corresponda.

function textoALeet(texto) { 
  let leetAlph={a:'@', 
    b:'8', 
    c:'(', 
    d:'|)',
    e: '3',
    f:'ph', 
    g:'g',
    h:'#',
    i:'l',
    j:'_|',
    k:'|<', 
    l:'1', 
    m:"|'|'|", 
    n:'/\/', 
    o:'0', 
    p:'|D', 
    q:'(,)', 
    r:'|2', 
    s:'5', 
    t:'+', 
    u:'|_|', 
    v:'|/', 
    w:"|/|/'",
    x:'><', 
    y:'j', 
    z:'2'};

  texto = texto.toLowerCase();
  for (var i = 0; i < texto.length; i++) {
    if (leetAlph[texto[i]]) {
      text = texto.replace(texto[i], leetAlph[texto[i]]);
    }
  }
  return(texto);
}

Función para cifrado ROT13 con Javascript

ROT13 es un algoritmo para el cifrado de mensajes extremadamente, tan simple que no debería ser considerado nunca una opción válida para un cifrado seguro de nuestras comunicaciones. Basado en los cifrados que se decía que realizaba Julio César en la antigüedad, donde simplemente escribía intercambiando cada letra por otra situada N posiciones más adelante o atrás en el abecedario, ROT13 consiste en desplazar cada letra de nuestro mensaje 13 posiciones hacia delante.

En su día se popularizó en los foros de internet para introducir chistes y últimamente se ha utilizado para ocultar spoilers en foros sobre series.

¿Cómo implementamos esto en Javascript? Bueno, pues se me ha ocurrido que esta sería la solución más rápida, utilizando las funciones de javascript replace() para substituir caracteres dentro de una cadena en base a una expresión regular, charCodeAt() para obtener el código del caracter y la función fromCharCode() para crear una cadena con esos códigos que obtuvimos antes y a los que les aplicamos el desplazamiento. También usaremos toLowerCase() para convertir a minúscula y evitar conflictos con los códigos de las mayúsculas.

function str_rot13(mensaje){
    return mensaje.replace(/[a-zA-Z]/gi,function(s){
        return String.fromCharCode(s.charCodeAt(0)+(s.toLowerCase()<'n'?13:-13));
    });
}

Y ahí nos quedaría un traductor inglés-rot13/rot13-inglés. Si a la función le pasamos «hola» devolverá «ubyn» y si le pasamos «ubyn» devolverá «hola«. La expresión regular de la función replace() solo evalúa los caracteres del alfabeto latino internacional por lo que si le pasamos una cadena con acentos o con eñes no daría errores pero no convertiría esos caracteres, igual que hará si la cadena tiene números o símbolos. Es decir, si le pasamos la cadena «coño» devolvería «pbñb«.

Como ya comenté en la introducción se trata de un cifrado más bien «de andar por casa» o para jugar a los detectives, no algo que se pueda utilizar en el campo de la ciberseguridad y la confidencialidad de los datos.

SQL-Server: Generar un número aleatorio entre dos valores

¿Cómo genero un número aleatorio en SQL-Server? Con la función RAND(), que nos devuelve un valor float pseudoaleatorio entre 0 y 1.

¿Y cómo puedo acotar esto entre dos valores? Pues redondeando el valor de multiplicar el resultado de la función RAND() por la diferencia entre el valor más alto y más bajo que queremos usar como límites y sumándole finalmente el valor más bajo. Que así puesto solo como texto parece más lioso de lo que es, la fórmula es muy sencilla y sería:

SELECT FLOOR(RAND()*(valorHasta-valorDesde)+valorDesde);

Siendo valorHasta el valor más alto y valorDesde el más bajo entre los que queremos obtener el valor aleatorio.

Imagina que queremos un valor aleatorio entre 100 y 200:

SELECT FLOOR(RAND()*(200-100)+100);

Operaciones a bit a bit: NOT, AND, OR y XOR

Seguimos con la racha de entradas encadenadas. Si la entrada de los tipos de configuración RAID nos llevó a definir el concepto de información de paridad ahora a raíz de esa entrada vamos a hablar de las operaciones bit a bit.

Hablamos de operaciones a nivel de bit porque con ellas trabajamos directamente sobre los bits, dígitos binarios, a nivel individual. Este tipo de operaciones son muy utilizadas en computación, a la hora de cifrar datos o, como comentábamos en el otro artículo, para realizar los cálculos de paridad. Es posible que te suenen los nombres de estas operaciones, pues son operaciones lógicas que ya vimos en su día en un artículo sobre LibreOffice Calc o también en la entrada sobre el álgebra booleana.

NOT: La operación NOT también podría ser llamada complemento y es un operador unario. Realiza la negación lógica de cada bit, es decir, invierte su valor. Por ejemplo, la operación NOT 1010 daría como resultado 0101.

AND: La operación AND, o conjunción lógica, funciona de forma similar a una multiplicación: sólo nos devolverá 1 si todas las entradas son 1, en el resto de casos devolvería 0. Es decir 0 AND 0 es igual a 0, 1 AND 0 es igual 0 y solo 1 AND 1 es igual a 1. Por ejemplo: 100111001011010100111010 AND 010110100001101111011000 = 000110000001000100011000. Cuando hacemos la operación AND la secuencia que dará como resultado no puede ser más larga que la mayor de las secuencias operadas.

OR: La operación OR, o disyunción lógica, dará como salida 1 siempre que una o más de sus entradas sean 1. Es decir, 1 OR 1 es igual a 1, 1 OR 0 es igual a 1 y solo 0 OR 0 es igual a 0. Por ejemplo: 1000 OR 0011 = 1011. Cuando hacemos la operación OR la secuencia que dará como resultado no puede ser más corta que ninguna de las secuencias operadas.

XOR: La operación XOR, u OR exclusivo, dará como salida 1 siempre que solo una de las dos entradas sea 1. Es decir, que 0 XOR 0 será igual a 0, 1 XOR 1 será igual a 0 pero 1 XOR 0 o 0 XOR 1 serán igual a 1. Por ejemplo 1010 XOR 1001 = 0011 Dado que es complicado revertir su resultado es muy utilizada en algoritmos de cifrado.