Similar Posts
Detectar cambio de tamaño de letra en Javascript
La verdad es que lo sencillo es lo mejor, y para cuando estés en la necesidad de detectar si se produce un cambio en el tamaño de la letra, nada mejor que el script que nos ofrece la gente de A List Apart.
Te puedes preguntar por qué vas a querer detectar el cambio de tipo de letra. Si te interesa tener un sitio accesible a gente con discapacidades, pues es buena idea que pienses en ello, ya que suele ser algo que pueden hacer con frecuencia.
Además de detectar ese cambio, puede ser necesario realizar alguna acción. Por ejemplo, si usamos una imagen para un botón, si cambiamos el tamaño de la letra, la imagen no cambia, por lo que el botón quedará demasiado pequeño para el resto del texto, ¿solución?, si hay cambio de tamaño de letra, sustituimos la imagen por un elemento input botón.
Al principio decÃa que la solución es sencilla, lo cual la hace aún mejor. Se trata de crear una capa que contenga un espacio dentro y que esté oculta. Se guarda el tamaño de la capa y cada cierto tiempo se detecta si ha habido un cambio en este tamaño, si es asÃ, se ha producido un cambio en el tamaño de la letra.
Text-Resize Detection
Demo
Código y ejemplos
Backgrounds animados con jQuery
Interesante script para jQuery que usa el plugin para modificar la posición del background y que nos permite hacer efectos con el background similares a los que se suelen hacer con Flash.
Mediante un fondo de mayor tamaño que el elemento y con una forma irregular (esquinas, ondas, degradado, …) se trata de que al mover el fondo, el efecto que se produzca sea el de una animación.
El script sería algo así:
$('#nav a')
.css( {backgroundPosition: "0 0"} )
.mouseover(function(){
$(this).stop().animate(
{backgroundPosition:"(0 -250px)"},
{duration:500})
})
.mouseout(function(){
$(this).stop().animate(
{backgroundPosition:"(0 0)"},
{duration:500})
})
Using jQuery for Background Image Animations
Vía / Script & Styles
Testear páginas web con AVA y PhantomJS
Estoy colaborando junto a @jlantunez y @belelros en WebSlides, un proyecto open source que permite crear presentaciones usando un navegador web de forma increíble.
Para hacer las cosas bien, vamos a incluir pruebas de testing, y para ello he mirado cómo hacerlo con AVA y PhantomJS. El problema con el que me he encontrado ha sido que todo es asíncrono y a veces da un poco de problemas esperar a cargar la página para que AVA empiece a realizar las pruebas.
Además no es plan de cargar la página en cada una de las pruebas, por lo que cargo la página una vez y luego realizo las pruebas necesarias. Esto me obliga a que las pruebas sean secuenciales en vez de en paralelo, pero bueno, tampoco es mucho problema.
Como me he roto la cabeza intentado averiguar cómo hacer, ya que soy un tanto novato en esto, pongo el código para aquel que lo necesite, aunque bueno, en breve estará en GitHub:
// Cargo las librerías
let phantom = require("phantom");
import test from 'ava';
// Para almacenar lo que PhantomJS necesita
let ph_, page_, status_;
// Función que carga la página
const load = async () => {
await phantom.create().then(async ph => {
ph_ = ph;
return await ph_.createPage();
}).then(page => {
page_ = page;
return page_.open('http://webslides.tv/');
}).then(status => {
status_ = status;
return true;
}).catch(e => console.log(e));
}
// Tests
test.serial("Page loaded", async t => {
await load();
t.is(status_, 'success');
});
test.serial('#webslides exits', async t => {
await page_
.evaluate( () => document.querySelector('#webslides') != null )
.then( ws => { t.truthy(ws); } );
});
test.serial('WebSlides object exits', async t => {
await page_
.evaluate( () => window.ws != null )
.then( ws => { t.truthy(ws); } );
});
/**
* Last test
*/
test.serial('Closing', async t => {
await page_.close();
ph_.exit();
t.true(true);
});
Manejar y generar excepciones en Javascript
Los que hemos trabajado con Java estamos acostumbrados a tratar y lanzar excepciones para controlar los errores, algo que en Javascript no es muy común, pero en librerías algo elaboradas podría ser muy útil.
// Clases de errores
function DivisionByZeroError() {
this.name = "DivisionByZeroError";
}
function DivisionByStringError() {
this.name = "DivisionByStringError";
}
// Funcion que devuelve un error
function divisionCanFail(a, b) {
if (b == 0) {
throw new DivisionByZeroError();
}
if (typeof b == "string") {
throw new DivisionByStringError();
}
return a / b;
}
// Funcion de test
function decoratedDivision(a, b) {
try {
alert(divisionCanFail(a, b));
} catch (error if (error.name == "DivisionByZeroError")) {
alert("A division by zero...");
alert("Exception class: " + error.name);
} catch (error if (error.name == "DivisionByStringError")) {
alert("Exception class: " + error.name);
}
}
decoratedDivision(5, "isThisANumber?!");
decoratedDivision(5, 0);
Tutorial básico de HTML storage
Una de las características más interesantes de HTML5 es el browser storage, el cual nos permite almacenar datos en el navegador del cliente.
A parte de su uso básico:
localStorage.setItem('name', 'arman');
var value = localStorage.getItem('name');
localStorage.removeItem('name');
Me gustaría destacar dos puntos importantes: detectar si el navegador lo soporta y añadir eventos:
var webStorageSupported = ('localStorage' in window) && window['localStorage'] !== null;
if (window.addEventListener) {
window.addEventListener("storage", handleStorageChange, false);
} else {
window.attachEvent("onstorage", handleStorageChange);
}
function handleStorageChange(event) {
alert("Algo esta cambiando en el almacenamiento");
}
El resto del tutorial explica todo paso a paso
Hapi.js + Vue.js accediendo a mongodb
Como ya dije, esta aplicación estará basada en Mongodb, y usaremos mongoose como ODM.
El primer paso es instalar mongoose:
npm i mongoose
Una vez instalado crearemos un controlador que nos permita usar la BD en toda la aplicación Hapi.js. Para ello haremos uso de los decorate del servidor. Los decorations permite extender objectos ofrecidos por Hapi.js, en nuestro caso server y request. Usando un plugin nos conectaremos a mongodb usando mongoose y añadiremos ese objecto con los decorate.
Creamos el fichero /plugins/db.js con el siguiente código:
/**
* DB controller
*
* It uses Mongoose and "stores" it in the server and the request using `decorate`
*/
const mongoose = require( 'mongoose' );
exports.plugin = {
name: 'db',
register: async function( server, options ) {
mongoose.connect( options.url, { useNewUrlParser: true } );
const db = mongoose.connection;
// eslint-disable-next-line
db.on( 'error', console.error.bind( console, 'connection error:' ) );
db.once( 'open', function() {
server.decorate( 'server', 'db', mongoose );
server.decorate( 'request', 'db', mongoose );
// eslint-disable-next-line
console.log( 'DB connected' );
} );
},
};
Para configurar la conectividad a mongodb tendremos que añadir los datos a la /config/index.js
const config = {
server: {
port: 3001,
},
website: {
name: `WP Desk`,
},
db: {
url: 'mongodb://localhost/wpdesk',
},
};
Y en el manifiest usado por glue, tendremos que añadir el nuevo plugin y las nuevas opciones de conexión:
const manifest = {
server: {
port: Config.get( '/server/port' ),
},
register: {
plugins: [
{
plugin: './api/home',
},
{
plugin: './plugins/db',
options: Config.get( '/db' ),
},
],
},
};
Ya tenemos casi todo configurado, ahora vamos a empezar con un ejemplo creando un esquema de moongose que nos permite acceder a colecciones de mongodb.
Lo más común es tener una colección de usuarios, que tendrá los siguientes campos:
- userName: de tipo String,
- firstName: de tipo String,
- lastName: de tipo String,
- email: de tipo String,
- role: que referencia a otro elemento de otra colección,
- isEnabled: de tipo Boolean,
- password: de tipo String,
- resetPassword: un objeto representado por:
- hash: de tipo String,
- active: de tipo Boolean,
También crearemos un método estático que devuelva todos los elementos de la colección users para realizar pruebas:
/**
* User model based on Mongoose
*/
const mongoose = require( 'mongoose' );
const Schema = mongoose.Schema;
// Mongoose schema
const userSchema = new mongoose.Schema( {
userName: String,
firstName: String,
lastName: String,
email: String,
role: Schema.Types.ObjectId,
isEnabled: Boolean,
password: String,
resetPassword: {
hash: String,
active: Boolean,
},
} );
/**
* User static model findAll
*
* @returns {array}
*/
userSchema.static( 'findAll', async function() {
const result = await new Promise( ( resolve, reject ) => {
this.model( 'User' ).find( {} ).exec( ( error, data ) => {
if ( error ) {
reject( error );
}
resolve( data );
} );
} );
return result;
} );
const User = mongoose.model( 'User', userSchema );
module.exports = User;
Ya está todo, ahora solo modificamos el handler de la ruta home.js para mostrar los valores de findAll:
/**
* Route handler
*
* @param {object} request
* @param {object} h Hapi object
* @returns {object}
*/
handler: async( request, h ) => { // eslint-disable-line
try {
const result = await User.findAll();
return result;
} catch ( error ) {
return { error: 500 };
}
},
Puedes bajarte el código aquí