Un sencillo script realizado con jQuery que nos permite cargar contenido cuando llegamos al final del contenido mediante el scroll. Algo parecido os presenté hace ya tiempo, pero sin uso de librerías. En este caso, jQuery reduce el código para implementarlo.
Es importante recordar que el contenido importante no se debería cargar mediante Ajax, y si se hace así es necesario ofrecer una alternativa clásica. Load Content While Scrolling With jQuery
Vía / Ajaxline
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: asyncfunction( 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-lineconsole.log( 'DB connected' );
} );
},
};
Para configurar la conectividad a mongodb tendremos que añadir los datos a la /config/index.js
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 schemaconst 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', asyncfunction() {
const result = awaitnewPromise( ( 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:
En muchas aplicaciones web, la utilización de un campo fecha suele ser algo habitual. Es preferible que el usuario no tenga que escribir ninguna fecha, sino que esta se tenga que introducir mediante un control de tipo calendario, evitando asà que ocurran ciertos errores y facilitando la labor al usuario. Tened en cuenta que hay diversos formatos DD/MM/YYYY, MM/DD/YYYY, DD-MM-YYYY, …
Espero que esta lista de calendarios realizados mediante Javascript os pueda ser de utilidad:
The DHTML / JavaScript Calendar: visible mediante popup o en plano, adecuado para seleccionar fecha y hora, válido para la mayorÃa de los navegadores, admite CSS, themes, navegación por teclado, muestra los dÃas de los meses adyacentes, traducido a varios idiomas, dÃas especiales resaltados de distinta manera.
Calendar Popup: se muestra un popup mediante ventana o usando capas, implementado para que tenga el aspecto de Microsoft Outlook, fácil de usar.
Zapatec Calendar: script comercial, muy completo, admite varios meses, válido para la mayorÃa de los navegadores, permite varios formatos de fecha y multiple selección de dÃas.
ScriptCalendar: versión comercial, basado en objetos, fácil de usar y de modificar, válido para la mayorÃa de los navegadores.
CalendarXP: versión comercial, muy completo que a parte del calendario pequeño, muestra un calendario grande que admite más detalles.
Tigra Calendar: el que más me ha gustado, cada campo es seleccionable, se puede adjuntar a un campo existente, meses seleccionables mediante scrolling y muchas cosas más.
Epoch Calendar: básico, de aspecto atractivo y válido para ser usado en aplicaciones AJAX.
Interesante plugin para jQuery que permite retrasar la carga de imágenes para que la carga de la página sea más rápida. Para ello, cargará las imágenes sólo cuando se vean mediante el scroll. Un script que está pensado para páginas con gran número de imágenes pesadas.
En muchos sitios web de almacenamiento de imágenes se nos permite retocar las imágenes. Hoy vamos a explicar como recortar una imagen directamente desde una página web.
Para ello tenemos que crearnos una página web que nos permita seleccionar la zona de la imagen que queremos recortar y de un script PHP que usando la librería GD recortará la imagen y la devolverá en formato PNG.
Siempre viene bien hacernos un control para direcciones IP, que permita pegar toda la dirección ip y que se rellenen las cajas correctamente y que al pulsar el punto se mueva de caja, y la verdad es que tampoco es muy difÃcil de hacer.
Uno de los problemas que hay en el editor de WordPress es que algunas veces los themes tienen diseños específicos que no se muestran en el editor. Actualmente, el uso de Bootstrap está cada vez más extendido, por lo que es buena idea añadir la opción de meter columnas en los posts de forma sencilla.
Lo primero que deberemos hacer es añadir en el functions.php el código necesario para añadir un botón al TinyMCE:
add_action( 'init', 'sw_mce_buttons' );
// Filtros para añadir los botones
function sw_mce_buttons() {
add_filter( "mce_external_plugins", "sw_mce_add_buttons" );
add_filter( 'mce_buttons', 'sw_mce_register_buttons' );
}
// Añade el script del plugin tinymce
function sw_mce_add_buttons( $plugin_array ) {
$plugin_array['iqn'] = get_template_directory_uri() . '/js/tinymce-plugin.js';
return $plugin_array;
}
// Un nuevo botón que se identifica como 'bootstrap'
function sw_mce_register_buttons( $buttons ) {
array_push( $buttons, 'bootstrap' );
return $buttons;
}
// Añadimos el css de bootstrap y uno propio para personalizar cosas
function sw_mce_css($wp) {
$wp .= ',' . get_bloginfo('stylesheet_directory') . '/bootstrap/bootstrap.min.css'.',' . get_bloginfo('stylesheet_directory') . '/css/tinymce.css';
return $wp;
}
add_filter( 'mce_css', 'sw_mce_css' );
Después tenemos que crear el javascript para el plugin de TinyMCE:
(function() {
// Creamos el plugin
tinymce.create('tinymce.plugins.iqn', {
init : function(ed, url) {
// Muestra el dialogo que permite personalizar las columnas
// Mostrará una caja de texto donde se pondra el ancho de la columna
// de 1 a 12, y cuando se indique un valor, automáticamente se añadirá otra columna
function bootstrapDialog() {
var html = '<div class="bootstrap-dialog">';
html += '<p class="howto">Añade columnas basadas en el sistema <a href="http://getbootstrap.com/css/#grid">grid de Bootstrap</a></p>';
html += '<p>Rellena el ancho (1-12) de cada celda. Nuevas celdas aparecerán automáticamente</p>';
html += '<div class="columns_container"><input type="text" class="column_width" /></div>';
html += '<p><input type="checkbox" id="new_row" name="new_row" /> <label for="new_row">Añadir nueva fila</p>';
html += '</div>';
var panel = {
type: 'container',
html: html
};
// Abre el dialogo
win = ed.windowManager.open({
title: "Columnas de Bootstrap",
spacing: 10,
padding: 10,
items: [panel], // el panel creado antes
buttons: [ // Botones
{text: "Insertar", subtype: 'primary', onclick: function() {
var content = ed.getContent();
var html = ' ';
// Si se marca la casilla, se añade una fila
if (jQuery('#new_row:checked').length == 1) html += '<div class="row">';
// Por cada columna, se crea una capa
jQuery('.column_width').each(function() {
var $this = jQuery(this);
if ($this.val()) html += '<div class="col-sm-'+$this.val()+'">Columna tamaño '+$this.val()+'</div>';
});
if (jQuery('#new_row:checked').length == 1) html += '</div>';
ed.execCommand('mceInsertContent', false, html);
win.close();
}},
{text: "Cerrar", onclick: function() {
win.close();
}}
]
});
}
ed.addButton('bootstrap', {
title : 'Columnas Bootstrap',
onclick: bootstrapDialog
});
},
createControl : function(n, cm) {
return null;
},
getInfo : function() {
return {
longname : 'Bootstrap columns',
author : 'SentidoWeb',
version : "0.1"
};
}
});
// Register plugin
tinymce.PluginManager.add( 'iqn', tinymce.plugins.iqn );
})();
jQuery(document).ready(function() {
// Se crea una casilla nueva si se actualiza el contenido de la última
jQuery('body').on('keyup', '.column_width', function() {
var $this = jQuery(this);
var $inputs = jQuery('.column_width');
if($this.val()) {
if ($inputs.index(this) == $inputs.length - 1) {
$this.after('<input type="text" class="column_width" />');
}
}
});
});
Y ya por último, crearnos el fichero tiniymce.css que se incluirá en el contenido del editor. Yo simplemente he recuadrado los elementos para que se diferencien en el editor: