Incrustar un SVG dentro del HTML directamente

Lo bueno de los SVG es que puedes modificarlos mediante CSS directamente en el HTML, el único problema es que el SVG debe estar incrustado en el HTML, no mediante una imagen <img>, ni mediante la propiedad content de CSS.

Encontré un script muy bueno que te modifica una etiqueta img que contiene un SVG por su contenido SVG real. El problema viene cuando yo añado el SVG como una propiedad content:

.class {
  content: url('imagen.svg');
}

Para ello he modificado el script anterior para que coja la propiedad content de los selectores CSS que se indiquen y añada el SVG directamente al elemento:

jQuery(document).ready(function() {
  var replaceWithSVG = function(selector, url) {
    jQuery('').appendTo('head');
    jQuery.get(url, function(data) {
      // Replace image with new SVG
      jQuery(selector).prepend(data.replace(/<\?xml[^>]+>/, ''));
    }, 'text');
  }
  var selectors = ['.site-title a', '.btn-video']
  for(var i in selectors) {
    var selector = selectors[i];
    var url = window.getComputedStyle(
    	document.querySelector(selectors[i]), ':before'
    ).getPropertyValue('content');
    url = url.replace(/url\(["']?([^'"\)]+)["']?\)/, '$1');
    replaceWithSVG(selectors[i], url);
  }
});

Añadir el sistema grid de Bootstrap al tinymce de WordPress

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.

boton_bootstrap

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 = '
'; html += '

Añade columnas basadas en el sistema grid de Bootstrap

'; html += '

Rellena el ancho (1-12) de cada celda. Nuevas celdas aparecerán automáticamente

'; html += '
'; html += '

'; html += '
'; 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 += '
'; // Por cada columna, se crea una capa jQuery('.column_width').each(function() { var $this = jQuery(this); if ($this.val()) html += '
Columna tamaño '+$this.val()+'
'; }); if (jQuery('#new_row:checked').length == 1) html += '
'; 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(''); } } }); });

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:

.row {padding: 4px; border: 1px dashed #bbb;}
.col-sm-1, 
.col-sm-2, 
.col-sm-3, 
.col-sm-4, 
.col-sm-5, 
.col-sm-6, 
.col-sm-7, 
.col-sm-8, 
.col-sm-9, 
.col-sm-10, 
.col-sm-11, 
.col-sm-12 {xmargin: 4px; border: 1px dotted #ccc;}

Y si modificáis el diseño del admin, podéis aprovechar ese css para añadir el css necesario para el botón.

i.mce-i-bootstrap {
	font: normal 20px/1 'dashicons';
	padding: 0;
	vertical-align: top;
	speak: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	margin-left: -2px;
	padding-right: 2px;
}
i.mce-i-bootstrap:before {
	content: '\f479';
}
.bootstrap-dialog p {padding: 5px 0;}
.bootstrap-dialog p a {color: #0074A2; text-decoration: underline;}
.mce-container .columns_container {border: 1px solid #F0f0f0; padding: 20px; border-radius: 4px; margin: 10px 0;}
.mce-container .columns_container input.column_width {
    margin-right: 5px;
    padding: 9px 3px;
    text-align: center;
    width: 39px;
}

Añadir Javascript relacionado con templates en WordPress

La jerarquía de las plantillas de wordpress permite definir diferentes plantillas para mostrar según el tipo de contenido. Por ejemplo, la template para mostrar el contenido de un post es single.php, pero si es un custom post type podemos crearnos la template single-miposttype.php y que use esa plantilla específica para mostrar los contenidos del custom post type. Si se trata de una página mostrará page.php, y así con todos los tipos de contenido.

Lo que nos encontramos en ocasiones es que queremos ejecutar un javascript específico asociado a esa plantilla, lo cual podemos hacerlo a la hora de añadir los scripts preguntando por el tipo de contenido. Pero si lo queremos hacer de una forma más automática, podemos añadir en el filtro template_include la acción de añadir el script.

add_filter('template_include', 'js_load_script_template');
function js_load_script_template($template) {
  // Obtenemos el fichero de la template que se usa
  $js = pathinfo($template);
  $js = $js['filename'];
  // Me gusta obtener la versión del theme para evitar caches
  $my_theme = wp_get_theme();
  $version = $my_theme->get( 'Version' );  
  // Si el fichero js existe, p.e. single-miposttype.js lo añadimos
  if (file_exists(get_template_directory().'/js/'.$js.'.js')) {
    wp_enqueue_script( $js, get_bloginfo('template_directory').'/js/'.$js.'.js', array(), $version );
  }
  // Tambien ejecuto el script relacionado con la plantilla generica, p.e. single.js
  $js_part = preg_replace('#^([^\-]+)\-.*$#', '$1', $js);
  if ($js != $js_part && file_exists(get_template_directory().'/js/'.$js_part.'.js')) {
    wp_enqueue_script( $js_part, get_bloginfo('template_directory').'/js/'.$js_part.'.js', array(), $version );
  }    
  return $template;
}

Añadir editor WYSIWYG al widget Texto de WordPress

Uno de los problemas que se pueden tener a la hora de desarrollar un plugin es que el cliente sepa editar los widgets añadiendo o modificando el HTML. Es por ello que he creado la posibilidad de añadir un pequeño plugin jQuery de edición WYSIWYG a los widgets Texto que vienen en WordPress por defecto, pero lo mismo se puede hacer para cualquier otro widget, incluído los que crees personalmente.

nicedit

Lo primero será bajarnos el plugin nicEdit, el cual permite de forma muy sencilla añadir un editor WYSIWYG a cualquier elemento. He elegido este plugin y no otro porque en el poco espacio que ofrece el textarea, poner otro plugin más completo, dificultaría su uso, de todas formas, si se quiere usar otro plugin, pues sin problema.

Yo me he creado un directorio /js donde he metido los dos ficheros de nicedit: nicEdit.js y nicEditorIcons.gif.

El siguiente paso es editar nuestro functions.php para añadir el siguiente código:

// El action in_widget_form es el encargado de llamar al método 
// form del widget, el que dibuja el formulario
// Comprobaremos si es un WP_Widget_Text y si es así
// añadiremos un checkbox para permitir que el textarea
// sea WYSIWYG
add_action('in_widget_form', 'set_nicedit_form_widget', 10, 3);
function set_nicedit_form_widget($obj, $return, $instance) {
  if (is_a($obj, 'WP_Widget_Text')) { ?>
		

/> 

base == 'widgets') { wp_enqueue_script( 'nicedit', get_bloginfo('template_directory') . '/js/nicEdit.js' ); wp_enqueue_script( 'admin', get_bloginfo('template_directory') . '/js/admin.js' ); wp_localize_script( 'admin', 'admin', array('path'=>get_bloginfo('template_directory')) ); wp_enqueue_style( 'admin', get_bloginfo('template_directory') . '/css/admin.css' ); } }

Ahora deberemos añadir la funcionalidad javascript al código que hemos metido en el widget (admin.js):

// Esta función es la encargada de añadir el WYSIWYG al textarea
function init() {
  // Busca todos los checkbox nicedit (le metimos un class) 
  // que estén seleccionados
  jQuery('input:checkbox.nicedit:checked').each(function() {
    var $this = jQuery(this);
    // Si ya tiene un nicedit nos lo cepillamos
    var niceditor = $this.data('nicedit');
    var $textearea = $this.parents('form:first').find('textarea');
    if (niceditor) niceditor.removeInstance($textearea.attr('id'));
    // Añadimos el nicedit al textarea, puedes meterle más botones, mira la doc de nicedit para ello
    var area = new nicEditor({buttonList : ['bold','italic', 'link', 'unlink', 'xhtml'], iconsPath: admin.path+ '/js/nicEditorIcons.gif'}).panelInstance($textearea.attr('id'));
    $this.data('nicedit', area);
  });
}

jQuery(document).ready(function() {
  // Si pulsamos el checkbox, añadimos o quitamos el nicedit
  // Almacenaremos el objeto nicedit para poder utilizarlo despues
  jQuery('.widget-liquid-right').on('click', 'input:checkbox.nicedit', function() {
    var $this = jQuery(this);
    var $textearea = $this.parents('form:first').find('textarea');
    var niceditor = $this.data('nicedit');
    if (niceditor) {
      niceditor.removeInstance($textearea.attr('id'));
      $this.data('nicedit', false);
    } else {
      var area = new nicEditor({buttonList : ['bold','italic', 'link', 'unlink', 'xhtml'], iconsPath: admin.path+ '/js/nicEditorIcons.gif'}).panelInstance($textearea.attr('id'));
      $this.data('nicedit', area);
    }
  });

  // nicEdit controla los submits para actualizar los valores,
  // pero en los widgets no funciona, por lo que antes del submit
  // forzamos la actualización del valor
  jQuery('#widgets-right').on('click', ':submit', function() {
    // Quizás se pueda utilizar el objeto nicedit almacenado anteriormente
    // pero esto lo hice así en una versión inicial menos genérica y no lo he tocado
    for(var i=0; i

Y por último solo nos falta meterle el css necesario, en este caso, el nicedit tiene un pequeño bug y si el textarea tiene un width = 100% no calcula el tamaño real, por eso se lo metemos por css (admin.css).


textarea.widefat {
  width: 400px;
  height: 100px;
}

Y listo, ya solo falta que el cliente no os dé mucho la lata.

Añadir contenido a los datepicker de jQuery UI

En algunas ocasiones es necesario añadir contenido al calendario que te ofrecer el datepicker de jQuery UI, por ejemplo añadir un combo que indice “horario mañanas/tarde”. Para conseguirlo será necesario ‘toquetear’ un poco el objeto jQuery.datepicker.

Tendremos que hacer dos cosas: primero deberemos evitar que cuando se selecciona un día se cierre automáticamente el popup con el calendario y después tendremos que modificar el HTML que devuelve la clase.

Para evitar el auto-cierre tenemos que añadir la opción showButtonPanel ya que nos ofrecerá el botón “Close” que nos permitirá cerrar el popup cuando hayamos indicado todos los campos necesarios. También es necesario modificar la función jQuery.datepicker._selectDate tal y como lo indican en StackOverflow:

// Añadimos datepicker al input que queremos
jQuery('.fecha')
  .datepicker({
    showButtonPanel: true,
    dateFormat: "DD, d MM, yy" 
  });

// Modificamos la funcion _selectDate
jQuery.datepicker._selectDateOverload = jQuery.datepicker._selectDate;
jQuery.datepicker._selectDate = function(id, dateStr) {
    var target = jQuery(id);
    var inst = this._getInst(target[0]);
    inst.inline = true;
    jQuery.datepicker._selectDateOverload(id, dateStr);
    inst.inline = false;
    this._updateDatepicker(inst);
    // Usar el .html() para luego usar el .text() es porque si usas el regional de datepicker, te salen entidades html en vez de letras acentuadas
    // Se le añade el valor del nuevo campo select que hemos incluido
    target.val(jQuery('
').html(dateStr).text()+' @ '+jQuery('#horario').val()); }

Bien, ya tenemos el evento onSelect modificado, ahora nos falta cambiar el HTML que se dibuja, para ello modificaremos la función jQuery.datepicker._generateHTML:

jQuery.datepicker._generateHTMLExtended = jQuery.datepicker._generateHTML;
jQuery.datepicker._generateHTML = function(inst) {
  var html = jQuery.datepicker._generateHTMLExtended(inst);
  var div = jQuery('
').html(html); div.find('table:first').after('

Horario:

'); return div.html(); } // Incluimos tambien un evento para que cuando se seleccione el horario, se modifique el campo input jQuery('#horario').live('change', function() { var $obj = jQuery('.fecha'); $obj.val($obj.val().replace(/@.*/, '@ '+jQuery(this).val())); });

Progreso de subida de ficheros únicamente con HTML5

Uno de los mayores problemas con los que nos hemos encontrado a la hora de hacer aplicaciones que suben ficheros, es mostrar al usuario cuánto se ha subido y así poder saber cuánto queda. Ahora con HTML5 y XMLHttpRequest Level 2 podemos mostrarlo sin necesidad de parte del servidor.

El script hace uso de Evento de Progreso de HTML5 para poder mostrar:

  • total: total de bytes
  • loaded: bytes subidos
  • lengthComputable: indica si el tamaño del fichero es conocido
  • transferSpeed: velocidad de transferencia
  • timeRemaining: tiempo que falta (en formato Date)

Por ahora solo es compatible con Firefox, Chrome y Safari.

En el post lo explican con gran detalle.

Html5 File Upload with Progress

JSZip: crear ficheros ZIP mediante Javascript

Interesante librería que nos permite crear ficheros ZIP desde Javascript, con unas simples líneas de código podemos crear zips con ficheros de texto, imágenes, crear directorios…

var zip = new JSZip();
zip.add("Hello.txt", "Hello World\n");
img = zip.folder("images");
img.add("smile.gif", imgData, {base64: true});
content = zip.generate();
location.href="data:application/zip;base64,"+content;

El único problema que hay es a la hora de generar el nombre del fichero: Firefox crea un fichero con un nombre extraño y acabado en .part, Safari lo nombra “Unknown” sin extensión, Chrome “download.zip” e IE directamente ni funciona la librería.

JSZip

Vía / @devongovett

PDF.js librería Javascript para leer PDF en Canvas

Interesante librería Javascript que nos permite mostrar en Canvas (HTML5) el contenido de un PDF. Puede venir muy bien para aplicaciones móviles, ya que en navegación en escritorio normalmente la gente tiene instalado un visor de PDFs.



  Simple pdf.js page viewer
  
  





  
/ --

PDF.js

Vía / @badass_js

Popcorn.js librería Javascript que permite sincronizar vídeo y contenido en HTML5

Popcorn.js es una librería que permite sincronizar la etiqueta <video> de HTML5 con contenido que deseemos mostrar. Para ello utiliza las propiedades, métodos y eventos nativos de HTMLMediaElement. Además ofrece un sistema de plugins desarrollados por la comunidad:

document.addEventListener("DOMContentLoaded", function () {
      // Create a popcporn instance by calling Popcorn("#id-of-my-video")
      var pop = Popcorn("#video");
      // play the video right away
      pop.play()
      // add a footnote at 2 seconds
        .footnote({
          start: 2,
          end: 6,
          text: "This footnote is the stepping stone of progress!",
          target: "footnotediv"
        });
    }, false);

Podéis ver algunos ejemplos bastante interesantes. Una librería muy útil para presentaciones y vídeos corporativos.

Popcorn.js

MathJax: librería javascript para mostrar fórmulas matemáticas

MathJax es una librería javascript que permite mostrar fórmulas LaTeX y MathML en nuestras páginas. Es compatible con casi todos los navegadores (menos IE5.5 lógicamente), permite copiar el código TeX y MathML de la página, utiliza fuentes CSS y no imágenes o Flash y muchas cosas más.




MathJax TeX Test Page




When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$

MathJax