Contenido

Wordpress 2.6 y los desarrolladores de plugins

3 Jul

+ 5

Ozh, escribe un artículo en el que nos muestra los cambios más significativos de la nueva versión de Wordpress, la 2.6, en relación a los desarrolladores de plugins.

Puesto que han cambiado muchas de las opciones del núcleo de Wordpress, nos veremos obligados a realizar modificaciones de la mayoría de plugins.

1. El directorio wp-content

Vimos que Wordpress daba la posibilidad de sacar la carpeta wp-content/ de la carpeta web y esto ha ocasionado una gran cantidad de cambios entre ellos el nacimiento de dos nuevas constantes que se encargan de conocer la nueva ruta.

Actualmente usamos la constante ABSPATH para hacer referencia a la ruta de la raiz de nuestro Wordpress.

$plugin_path = ABSPATH . '/wp-content/plugins/' . plugin_basename(dirname(__FILE__));
$plugin_url = get_option('siteurl') . '/wp-content/plugins/' . plugin_basename(dirname(__FILE__));

Esta constante seguirá disponible, pero ya no tiene por que estar el directorio wp-content/ colgando de la raíz de Wordpress. Por ese motivo tendremos que reemplazarlo para tener un código más permisivo:

// Pre-2.6 compatibility
if ( !defined(’WP_CONTENT_URL’) )
	define( ‘WP_CONTENT_URL’, get_option(’siteurl’) . ‘/wp-content’);
if ( !defined(’WP_CONTENT_DIR’) )
	define( ‘WP_CONTENT_DIR’, ABSPATH . ‘wp-content’ );
// Cogemos la ruta
$plugin_path = WP_CONTENT_DIR.’/plugins/’.plugin_basename(dirname(__FILE__));
$plugin_url = WP_CONTENT_URL.’/plugins/’.plugin_basename(dirname(__FILE__));

Nacen WP_CONTENT_DIR y WP_CONTENT_URL, dos constantes que tendremos que tener muy presentes.

2. Incluyendo el fichero wp-config.php

El fichero wp-config.php tambien permite ser sacado de nuestra carpeta web, lo que significa que tenemos el mismo problema anterior, no debemos creer que todos los usuarios lo tendrán instalado en la raíz de su Wordpress.

Antiguamente, al estar wp-content/ en la raiz podíamos usar../../../ para llegar al directorio raíz y usar wp-config.php en nuestros plugins.

require_once('../../../wp-config.php');

Esto en Wordpress 2.6, tambien ha cambiado:

$root = dirname(dirname(dirname(dirname(__FILE__))));
if (file_exists($root.'/wp-load.php')) {
	// WP 2.6
	require_once($root.’/wp-load.php’);
} else {
	// Antes de 2.6
	require_once($root.’/wp-config.php’);
}

Poco a poco van cerrandose los tickets del Roadmap y va quajando más lo que tendremos los usuarios y desarrolladores de Wordpress 2.6, así que mientras tanto, tendremos que estar atentos a todos estos cambios.

Google comienza a indexar fichero Flash

1 Jul

+ 15

Hoy leo que Google va a indexar los ficheros flash. Por el momento solo será benficioso de cara al SEO, pero esto abre una puerta a navegadores accesibles capaz de leer el contenido de los elementos flash. ¿podría esto llegar a un renacimiento del flash? [Via]

4 extensiones para complementar Firebug

1 Jul

+ 9

Firebug, ya de por sí es (para mí) la mejor extensión existente para Firefox y de la que no podría prescindir en el día a día. Dispone de todas las herramientas necesarias para hacer un debug exhaustivo de nuestras aplicaciones web. Así y todo siempre se puede mejorar, todo se puede mejorar.

Con estas 4 extensiones podremos complementar unas opciones para que Firebug se convierta en “la única” de mi navegador.

  1. Jiffy, una extensión que mejora el apartado Net mostrando más detalladamente la información referente a la carga de la página.
  2. YSlow, extensión que testea una serie de reglas para comprobar el correcto rendimiento del sitio.
  3. FireCookie, integra un apartado extra llamado Cookies en el que podremos gestionar, manipular o eliminar las cookies que intervienen en cualquier página.
  4. FirePHP, nos permitirá interactuar desde PHP con nuestra consola Firebug.

via

JSON Diff, compara JSON de una forma muy visual

30 Jun

+ 0

JSON Diff, es una herramienta que nos permite comparar de forma visual dos ficheros JSON.

Solución a los problemas de multiples botones en IE6

30 Jun

+ 0

Hace más de un año, preguntabamos ¿Por que lo llamamos input cuando deberíamos llamarlo button?. Despues de varios comentarios vimos que uno de los problemas que nos llevan a depender de input's para hacer el trabajo de buttons es que Internet Explorer 6, al enviar todos los datos a la página siguiente hace exactamente eso, enviarlo todo, incluso otros elementos <button /> que podrían tener diferentes funcionalidades.

Para solucionar este problema, podemos optar por usar este código javascript únicamente para Internet Explorer 6.

function buttonfix() {
    var buttons = document.getElementsByTagName('button');
    for (var i=0; i<buttons.length; i++) {
        if(buttons[i].onclick) continue;

        buttons[i].onclick = function () {
            for(j=0; j<this.form.elements.length; j++)
                if( this.form.elements[j].tagName == ‘BUTTON’ )
                    this.form.elements[j].disabled = true;
            this.disabled=false;
            this.value = this.attributes.getNamedItem(”value”).nodeValue ;
        }
    }
}
window.attachEvent(”onload”, buttonfix);
// Solo para IE 6
<!–[if lt IE 7]>
    <script type=”text/javascript” src=”buttonfix.js”></script>
<![endif]–>

Este código, nos añadirá una funcionalidad que será ejecutada al hacer click sobre cualquier elemento button de la página y que desactivará todos los elementos <button /> que encuentre para que no sean el que hemos seleccionado.

Esta solución, lamentablemente nos obliga a tener el javascript activado, así que más que solución es un parche, habrá que esperar a que IE6 desaparezca.

Via.

Curioso bug en Internet Explorer 7

30 Jun

+ 12

Internet Explorer 7 solucionó mucho de los problemas que los usuarios de Internet Explorer 6 sufrían (y aún sufren), pero por otro lado nos encontramos con problemas curiosos que seguro en algún momento nos puede llegar a poner los pelos de punta.

El código

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
      <title>Test</title>
    	<style type="text/css">
      	ol li {height:40px;}
       </style>
</head>
<body>
<ol>
    <li>Esto</li>
    <li>es</li>
    <li>solo</li>
    <li>una</li>
    <li>prueba</li>
</ol>  
</body>
</html&gt;

Como podemos ver, únicamente se trata de un listado ordenado al que acada uno de sus elementos <li></li> le aplicamos un tamaño de 40px con la propiedad height, debido a esto obtenemos un listado numérico bastante peculiar.

Explicación del bug

Si revisamos el código vemos que el problema reside en que usamos un height para definir el tamaño de cada elemento <li></li> de la lista <ol></ol>, esto hace que se pierda la cuenta y aparezca como 1, cada elemento. El tamaño de cada item, es indiferente, incluso puede ser height:0px;

Demo

He montado el código en un fichero HTML para que lo podais probar vosotros mismos. Es necesario usar Internet Explorer 7 para ver el bug en acción.

Via

Dragtable, una tabla sortable y dragable (y algún palabro más)

27 Jun

+ 7

Dragtable es una vuelta de tuerca más a las tablas sortables (osea que se pueden ordenar mediante Javascript), con esta además, podemos mover las columnas ordenando los resultados a voluntad.[Demo]

Layout multicolumnas líquido compatible con iPhone

26 Jun

+ 4

Interesante layout completamente en CSS (sin hacks) con el que podremos disponer de una estructura líquida con multicolumnas. Ideal para los que queremos evitar las barras horizontales en nuetros diseños. Esta versión es compatible con el iPhone/iPod Touch por lo que el tamaño de la pantalla no supone un problema. [Demo][Descargar]

+50 menus de tabs para nuestras aplicaciones

25 Jun

+ 1

Los tabs se han ganado un puesto entre los sistemas de menú más interesantes y más cómodos para el usuario. Aunque entre estos 50 seguro que encuentras alguno que más que cómodo, vistoso.

Validar formularios con jQuery

25 Jun

+ 16

Hace unas semanas tuve que desarrollar una función que me permitiera validar formularios mediante Javascript de una forma fácil y rápida. Tenía que ser con jQuery por que es el framework que estamos usando ahora en el trabajo. Una de las premisas era que debido a la aplicación y a la tecnología, necesitaba que fuera lo más flexible posible, por ese motivo opté por el siguiente código:

El código

//Filtros
var filters = {
    requerido: function(el) {return ($(el).val() != ” && $(el).val() != -1);},
    email: function(el) {return /^[A-Za-z][A-Za-z0-9_]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/.test($(el).val());},
    telefono: function(el){return /^[0-9]*$/.test($(el).val());}};
// Extensiones
$.extend({
	stop: function(e){
        if (e.preventDefault) e.preventDefault();
        if (e.stopPropagation) e.stopPropagation();
    }
});
// Código
$(document).ready(function(){
	$(”form.validable”).bind(”submit”, function(e){
		if (typeof filters == ‘undefined’) return;
	    $(this).find(”input, textarea, select”).each(function(x,el){
	        if ($(el).attr(”className”) != ‘undefined’) {
	        $.each(new String($(el).attr(”className”)).split(” “), function(x, klass){
	            if ($.isFunction(filters[klass]))
	                if (!filters[klass](el))  $(el).addClass(”error”);
	        });
	        }
	    });
		if ($(this).find(”.error”).size() > 0) {
			$.stop(e || window.event);
			return false;
		}
	    return true;
	});
});
	

Explicación

Si no fijamos en el código podemos ver que este script, será ejecutado en cuando el contenido de la página esté completamente cargado, esto lo conseguimos gracias a $(document).ready(); que jQuery nos ofrece.

Una vez cargado el contenido, se encargará de recorrar todos los elementos y buscará todos los elementos <form class="validable">, a los que le añadirá un listener que será ejecutado en el momento que el formulario ejecute el método submit().

En ese momento, el script recoge todos los element <input />, <textarea /> y <select /> del formulario y revisa las clases de cada elemento. Dependiendo de la clase y si está está definida en el objeto filters, realizará una comprobación u otra.

El objeto filters, se compone de una serie de métodos que serán lanzados para validar cada uno de los elementos, por ejemplo:

//HTML
<input type=”text” name=”prueba” value=”" class=”requerido email noanieto” />

//Javascript (Filtros)
var filters = {
       requerido: function(el) {return ($(el).val() != ” && $(el).val() != -1);},
       email: function(el) {return /^[A-Za-z][A-Za-z0-9_]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/.test($(el).val());},
       noanieto: function(el){return !”anieto”.indexOf($(el).val());}
}

Como podemos ver el elemento <input />, le estamos indicando que es del tipo requerido, email y noanieto. Validaciones que definimos en el objeto filters. En caso de no existir una de las clases indicadas en el elemento <input /> (o cualquier otro), esta será omitida.

Si el elemento no cumple una de las condiciones, añadiremos una clase más al elemento (class="error") y pararemos la ejecución del submit().

Demo

He montado una pequeña demo para verlo funcionar. La podeis probar aqui.

Aclaraciones

Está claro que se trata de una validación Javascript y que su única función es mejorar la experiencia del usuario evitando que llegue a submitar una página con datos erroneos, para hacer las cosas bien, la página receptora, debería hacer la misma comprobación y devolver a la página anterior en caso de error, así los usuarios que no tengan la capacidad de ejecutar javascript, tendrán un resultado igual a los que sí, aunque tengan que esperar a la carga de la página.

Versión para MooTools

Epplestun, me pasa una adaptación del script para MooTools. Muchas gracias!!!

$(document).addEvent('domready', function() {
       $(document.body).getElements('form.validable').addEvent('submit', function(e) {
               if (typeof filters == 'undefined')
                       return;

          this.getElements("input, textarea, select").each(function(el) {
               if (el.getProperty("class").length) {
                       el.removeClass("error");
                               el.getProperty("class").split(" ").each(function(filtro) {
                                       if (!filters[filtro](el))
                                               el.addClass(”error”);
                               });
               }
          });

          this.getChildren().each(function(el) {
               if(el.hasClass(”error”)) {
                               e = new Event(e);
                               e.stop();
                       return false;
               }
          });

          return true;
       });