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>

jQuery: Poner el foco en el siguiente elemento usando una clase

Os cuento: un cliente pide que en un formulario que está rellenando, con varios campos de texto muy pequeños para un solo carácter, el foco salte de forma automática al siguiente campo cada vez que cubre uno. Es decir, en cada evento de levantar la tecla salta al siguiente. La cosa parecía simple usando la función next() de jQuery:

$(".cuadrito").keyup(function() {
  $(this).next('.cuadrito').focus();	
});

La función next() de jQuery salta al siguiente elemento «hermano» que aparezca. ¿Qué quiere decir hermano? Pues que tengan el mismo padre, esto es que estén contenidos en el mismo elemento del DOM. Y por eso esta práctica y elegante solución no me valía, porque resulta que los inputs están dentro de una tabla, de forma que al cambiar de celda cambia el «padre» en el DOM y ya no salta el foco. ¿Qué hacer entonces? Lo solucioné con la función index():

$(".cuadrito").keyup(function() {	            
  var ind = $(".cuadrito").index(this);
  $(".cuadrito").eq(ind + 1).focus();
});

¿Qué hicimos aquí? Creo que en el pasado ya vimos que jQuery nos permite tratar a los elementos como si de un array se tratase. Simplemente estoy mirando en la primera fila qué índice tendría el elemento en el que nos encontramos y, en la siguiente, poniendo el foco en el posterior sumando 1 al índice.

Modificar los atributos data de HTML5 con jQuery

Si en una entrada anterior vimos cómo leer los atributos data de HTML5 con jQuery hoy vamos a ver el otro caso: modificar dichos atributos.

El ejemplo va a ser el mismo que en el anterior artículo:

<div id='fruta' data-fruta='fresa'></div>

Ok, tenemos un div con el id fruta, el atributo data-fruta y en principio el valor fresa. ¿Cómo lo modifico haciendo uso de jQuery? Pues de nuevo con el método data(), pero en este caso pasándole dos parámetros en lugar de uno:

$("#fruta").data("fruta","pera");
window.alert($("#fruta").data("fruta"));

Si el método data() recibe solo el nombre del atributo al que queremos acceder nos lo devuelve, pero si recibe como segundo atributo una cadena entonces modifica el valor del atributo asignándole el de ese segundo parámetro que le pasamos.

Y voy a repetir exactamente el mismo párrafo que en el artículo anterior sobre la nomenclatura (para que no tengas que abrirlo): Fíjate que cuando le paso el nombre del atributo lo hago quitándole el prefijo data-. Y hay otra peculiaridad: si el nombre tiene varios guiones entonces estos desaparecen y escribimos el atributo siguiendo la convención camelCase.

<div id='fruta' data-fruta-oferta='pera'></div>
<script type="javascript">
$("#fruta").data("frutaOferta","fresa");
window.alert($("#fruta").data("frutaOferta"));
</script>

Acceder a los atributos data de HTML5 desde jQuery

En el pasado alguna vez utilizamos los atributos rel o class para incluir valores extra que usar luego en javascript. No era una buena práctica, pero a veces era la solución más práctica. HTML5 acabó con esto introduciendo los atributos data, que nos permiten vincular información extra a un elemento del DOM. Veamos un ejemplo:

<div id='fruta' data-fruta='fresa'></div>

En el div con Id «fruta» vamos a guardar un dato: que es una fresa (ok, ya se que el ejemplo no parece tener mucho sentido práctico). ¿Cómo accedo a este valor desde jQuery? Pues con el método data() puedo tanto definirlo como obtenerlo, pasándole como parámetro el nombre del dato.

window.alert($("#fruta").data("fruta"));

El ejemplo de arriba haría un alert mostrándonos el valor. Fíjate que cuando le paso el nombre del atributo lo hago quitándole el prefijo data-. Y hay otra peculiaridad: si el nombre tiene varios guiones entonces estos desaparecen y escribimos el atributo siguiendo la convención camelCase. Un ejemplo:

<div id='fruta' data-fruta-oferta='pera'></div>
<script type="javascript">
window.alert($("#fruta").data("frutaOferta"));
</script>

En próximas entradas veremos cómo escribir los atributos y cómo acceder a ellos desde Javascript sin usar jQuery.

Tratando los objetos jQuery como arrays.

Cuando con jQuery ejecutamos un selector sobre un elemento del DOM el resultado es un objeto de jQuery. Sin embargo, la librería hace que podamos trabajar con estos elementos como si de un array se tratara, dado que define índices y una longitud.

//recogemos en una variable todos
//los elementos de la clase link
var elementos = $(".link");

// ahora podemos recorrer la colección
for(var i=0;i<elementos.length;i++){
    console.log(elementos[i]);
}

La propiedad length nos permite de esta forma saber si la colección contiene algún elemento. Si es 0 está vacío, y si es mayor el resultado es la cantidad de elementos que contiene.

if(elementos.length){
    //si hay elementos hace lo pongamos aquí
}

Si bien jQuery nos da la función $.each() para recorrer una colección de elementos, hacerlo de esta forma con un for o un while es mucho más rápido.

Conocer el «peso» de tu página con jQuery

Vamos con una corta entrada rápida sobre jQuery ¿quieres saber cuántos elementos DOM hay en tu página? Con una simple línea con jQuery podemos mandar la cuenta a la consola del navegador, tal que así:

console.log( $('*').length );

Conocer el número de elementos puede ser útil si estás buscando la causa de una ralentización en la carga de una página.

Cambiar el src de una imagen con javascript o jQuery

Vamos con una entrada rápida de Javascript ¿Cómo cambio el src de una imagen de forma dinámica? No es lo más recomendable para una web por temas de posicionamiento, pero puede ser una solución útil para una aplicación web de uso interno.

Vamos a suponer que tenemos una imagen llamada image1.jpg y que al clickar en un elemento esta cambia por otra que se llama image2.jpg:

<img src="image1.jpg" id="img1" alt="primeraImagen" />

<script>
//así con JS normal
//accediendo directamente a src
function cambiarImagenJS(){
  document.getElementById("img1").src="image2.jpg";
}

//así con jQuery
//haciendo uso de la función attr()
function cambiarImagenjQ(){
  $("#img1").attr("src","image2.jpg");
}
</script>

La idea sería vincular la función a un evento (un click, el cambio de estado de un checkbox o radio, llenar un campo de texto…) y cambiar el valor. En el ejemplo damos por fijo el id del elemento, en la práctica seguramente sería mejor pasárselo a la función. En ese caso ya miráis que se adapta mejor a vuestras necesidades.

jQuery: comodines para los selectores

Una de las comodidades de jQuery es la versatilidad que nos da a la hora de trabajar con diversos selectores. Lo que muchos no saben, o lo intuyen pero no lo tienen claro, es que existen diversos comodines para usar los selectores de jQuery. Vamos a verlos:

Seleccionar por un prefijo: Tenemos la posibilidad de usar un selector que actúe sobre los elementos que tengan un atributo cuyo valor sea igual a la cadena que le pasemos, o que empiecen por esa cadena seguida de un guión. La sintaxis sería tal que así: jQuery( «[attribute|=’value’]» )
Lo vemos mejor con un ejemplo:

<div id="pepe">Some text</div>
<div id="pepe-paya">Some other text</div>
<div id="pepote">Some text</div>
 
<script>
//oculturía los dos primeros divs y dejaría el tercero
$( "div[id|='pepe']" ).hide();
</script>

Seleccionar por un fragmento de una cadena: Con esta opción lo que buscaríamos sería un fragmento de texto dentro del valor del atributo, en cualquier posición. La sintaxis sería tal que así: jQuery( «[attribute*=’value’]» )
Lo vemos mejor con un ejemplo:

<div id="casapepe">Some text</div>
<div id="pepepaya">Some other text</div>
<div id="pepote">Some text</div>
 
<script>
//oculturía los dos primeros divs y dejaría el tercero
$( "div[id*='pepe']" ).hide();
</script>

Seleccionar por una palabra aislada concreta: El título es un pelín confuso, lo se, pero te lo explico. Con esta opción buscaríamos dentro del atributo una palabra concreta, que puede estar delimitada por espacios o ser el valor único del atributo. La sintaxis sería tal que así: jQuery( «[attribute~=’value’]» )
Lo vemos mejor con un ejemplo:

<div id="casa pepe">Some text</div>
<div id="pepe">Some other text</div>
<div id="pepepaya">Some text</div>
 
<script>
//oculturía los dos primeros divs y dejaría el tercero
$( "div[id~='pepe']" ).hide();
</script>

Seleccionar por el final del atributo: En este caso lo que hacemos es buscar los elementos con un atributo cuyo valor termine con la cadena que le pasamos. La sintaxis sería tal que así: jQuery( «[attribute$=’value’]» )
Lo vemos mejor con un ejemplo:

<div id="casapepe">Some text</div>
<div id="pepemola">Some other text</div>
<div id="elpepepaya">Some text</div>
 
<script>
//oculturía el primer div y dejaría los otros dos
$( "div[id$='pepe']" ).hide();
</script>

Seleccionar por el principio del atributo: En este caso lo que hacemos es buscar los elementos con un atributo cuyo valor comience con la cadena que le pasamos. La sintaxis sería tal que así: jQuery( «[attribute^=’value’]» )
Lo vemos mejor con un ejemplo:

<div id="casapepe">Some text</div>
<div id="pepemola">Some other text</div>
<div id="elpepepaya">Some text</div>
 
<script>
//oculturía el segundo div y dejaría los otros dos
$( "div[id^='pepe']" ).hide();
</script>

jQuery: enviando un formulario con ajax

No sabía sobre qué escribir, pero esta semana me preguntaron por esto así que puede ser cosa buena contarlo también por aquí.

Bueno, el primer punto a tener en cuenta es que jQuery nos ofrece varios métodos para realizar envío por ajax: el método post() (que hace una petición por post), el método get() (lógicamente por get) o el método ajax(). Para este ejemplo usaremos este último.

jQuery, por otra, parte nos permite no enviar todo el formulario sino sólo una lista de valores que podemos coger nosotros de los campos para, por ejemplo, realizar validaciones que necesiten consultas del lado del servidor. Pero para el ejemplo enviaremos todo el formulario.

En este caso vamos a suponer que tenemos un formulario con el id formulario que tenemos que enviar a una página llamada procesa.php, que a su vez nos devuelve una cadena de texto informándonos del éxito de la operación. La acción del envío se activa cuando hacemos click sobre un elemento con el id enviar. Sobre la cabecera de nuestro formulario hay un div con el id resultado donde podemos informar al usuario del resultado de su envío. Vamos entonces con el código jQuery:

<script type="text/javascript">   
$(function(){
  $("#enviar").click(function(){
    $("#resultado").html("<p id='enviando'>Enviando datos</p>");
    $.ajax({
      method: "POST",
      url: "procesa.php",
      data: $("#formulario").serialize()
    })
    .done(function( msg ) {
      $("#enviando").hide();
      $("#resultado").html("Formulario enviado:" + msg);
    })
    .fail(function() {
      $("#enviando").hide();
      $("#resultado").html("Se ha producido un error y no se han podido procesar los datos");
    })
  });
});
</script>

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.