Archivo de la etiqueta: javascript

Error “TypeError: oldKeypath is undefined” en Ractive.js

Este es uno de esos raros casos en los que buscas un error en Google y no obtienes ningún resultado. El error es el siguiente:

TypeError: oldKeypath is undefined

Haciendo un poco de investigación descubrí que el causante del error era este input en una plantilla de Ractive.js.

<input type="hidden" name="element_order[]" value="{{ index + 1 }}">

El problema consiste en que realizo modificaciones en el orden de los elementos y también pueden ser eliminados. Ractive.js al hacer una vinculación an ambos sentidos del valor del input que contiene el índice actual, parece ser que no le gusta y lanza el error. La solución pasa por indicar a Ractive.js que no vincule el valor del input con el atributo twoway="false":

<input type="hidden" name="element_order[]" value="{{ index + 1 }}" twoway="false">

Valor por defecto para un parametro de una función en JavaScript

Es fácil encontrar la solución a esto, por ejemplo en StackOverflow, pero la he buscado ya tantas veces que he decidido dejarla aquí anotada:

function sampleFunction( sampleParameter ) {
    sampleParameter = typeof sampleParameter !== 'undefined' ? sampleParameter : false;
}

En el ejemplo comprobamos si el parámetro está definido, y en caso de que no lo esté le asignamos el valor false por defecto.

Generador de rango de color

Algo que siempre he encontrado difícil cuando trabajo en la parte visual de una aplicación web es encontrar el color adecuado para cada componente. A veces tienes un color base sobre el que quieres trabajar y quieres tener variaciones más claras o más oscuras de ese color. He encontrado algunas webs que ofrecen generar rangos de colores, pero suelen ser bastante farragosas y complicadas.

Así que como hago siempre en este tipo de situaciones, he creado mi propia aplicación para generar un rango de colores.

Generador de rango de colores

Como su nombre indica, a partir de un color base la aplicación genera un rango de colores más claros y más oscuros que el original.

El algoritmo javascript utilizado es creación de Pimp Trizkit, creado para responder a su propia pregunta en este hilo de StackOverflow.

Un parámetro de la directiva de AngularJS tiene valor undefined

Estaba modificando una directiva de un tercero y me estaba volviendo loco con un valor que siempre estaba undefined. La directiva era sencilla y no entendía cual era el error.

La definición del scope dentro de la directiva es esta:

scope: {
  searchParam: '=ngModel',
  suggestions: '=data',
  onType: '=onType',
  formId: '=formId',
  onSelect: '=onSelect',
  autocompleteRequired: '='
}

Y el uso de la directiva es este:

<autocomplete
    ng-model="vm.sCompanyName"
    data="vm.aInsuranceCompanies"
    form-id="bikeInsuranceAlert"
    on-type="vm.autocompleteChange">
</autocomplete>

El valor que me interesa obtener es el formId. ¿Veis el error? Es sutil…

form-id="'bikeInsuranceAlert'"

Faltaban unas comillas simples dentro de las dobles para obtener el valor del ID como una cadena. Lo que AngularJS estaba interpretando es que quería obtener el valor de una variable llamada bikeInsuranceAlert dentro del scope. Evidentemente esta variable no existe, y el valor asignado era undefined.

Que traicionero es AngularJS en ocasiones…

Guardar una cookie con JavaScript puro

AngularJS tiene un módulo para guardar cookies, pero por desgracia no permite establecer la fecha de expiración de la cookie, por lo que la cookie es borrada al final de la sesión.

Hay plugins para AngularJS y para JQuery que permite crear cookies de forma sencilla y establecer la fecha de expiración, pero no quería añadir una libraría más solo para guardar una cookie. Así que esta es la forma de hacerlo usando únicamente JavaScript puro:

var dExpirationDate = new Date();
dExpirationDate.setTime(dExpirationDate.getTime() + (365*24*60*60*1000));
var sExpirationDate = "expires=" + dExpirationDate.toUTCString();
document.cookie = "cookieName=cookieValue; " + sExpirationDate;

Cómo saber cuando se actualizó una web por última vez

Evidentemente esto solo funcionará en páginas estáticas, pero más de una vez me he encontrado con alguna librería de PHP o JQuery que no mostraban ninguna fecha de última actualización en su web. Para esas situaciones, podemos abrir el Firebug y en la consola escribir lo siguiente:

javascript:alert(document.lastModified)

Saltará una alerta con la fecha de la última modificación.

Desencriptar código PHP

Últimamente me ha tocado lidiar con código PHP que se encuentra encriptado y ofuscado. Se trata de un módulo para PrestaShop de la empresa Agile. En nuestro caso nos daba una funcionalidad muy próxima a lo deseado, pero menuda sorpresa al intentar corregir algunos elementos y descubrir que el código estaba encriptado y ofuscado.

En este caso el tipo de encriptación utilizado era hexadecimal. Tras buscar un rato, encontré esta página que realiza una desencriptación del código:

DDecode

Funciona bastante bien, pero en un par de casos parece que se queda a mitad fichero y no acaba de realizar la desencriptación. Buscando un poco más encontré en Stackoverflow este tema donde explican como desencriptar el hexadecimal utilizando JavaScript. Lo he probado y también funciona bastante bien, al menos este termina de desencriptar el fichero. Así que mi solución ha sido utilizar ambos métodos y comparar el código resultante para reconstruir el fichero original.

Por si a alguien re puede resultar este segundo método, he creado una sencilla página donde puede insertar el código para ser desencriptado. La encontraréis en:

Just Another Hex Decoder!

El retorno del SPAM

La solución con la base de datos de SPAM debo reconocer que fue ingeniosa. Está muy en mi línea de "matar moscas a cañonazos". El problema es que lo que se dice eficaz, no era. Digamos que el número de direcciones IP desde las que puede llegar SPAM, o el número de direcciones de correo o URLs que pueden usar en los comentarios están en un orden de magnitud tal que nunca voy a ser capaz de filtrar los comentarios basura.

Todo vuelve a la pregunta que me hice hace ya hace 9 meses: ¿Como estaban los bots de SPAM enviando comentarios saltándose el formulario de envío? Y por pura casualidad, encontré a que página están atacando. Probablemente están haciendo un POST directamente contra wp-comments-post.php.

Así que volvemos a la sencillez. ¿Como detectar un POST que llega a wp-comments-post.php sin pasar por comments.php? Fácil. Si los bots están lanzando un POST genérico para blogs en WordPress, añadamos un nuevo campo al formulario. Si en wp-comments-post.php detectamos que ese campo no está establecido, entonces se está saltando comments.php y debe ser SPAM. Está solución es tan eficaz que hace que mis dos soluciones anteriores queden obsoletas, así que para aligerar la página y reducir tiempo de procesado, elimino las modificaciones del código anteriores. El código definitivo quedaría de la siguiente manera:

Dentro de los ficheros del tema, en el fichero comments.php:

Añadimos un nuevo campo oculto al formulario:

<input type="hidden" id="comment_post_antirobot" name="comment_post_antirobot" value="0" />

Por si acaso el robot de SPAM está comprobando que campos tiene el formulario, cambiamos su valor por javascript:

<script type="text/javascript">
document.getElementById('comment_post_antirobot').value = "1";
</script>

En wp-comments-post.php:

Obtenemos el valor del campo oculto, y en caso de no estar establecido o no ser igual a 1, marcamos el comentario como SPAM modificando el contenido:

$comment_antirobot    = ( isset($_POST['comment_post_antirobot']) ) ? trim($_POST['comment_post_antirobot']) : null;

if( empty($comment_antirobot) || $comment_antirobot == '0'){
    // It's SPAM
    $comment_content = '[THIS#IS#SPAAAM!] '.$comment_content;    
}

En wp-includes/comment.php, en el método wp_insert_comment:

Comprobamos si contiene la marca de SPAM en su contenido, y en ese caso lo etiquetamos como SPAM:

if(strpos($comment_content, '[THIS#IS#SPAAAM!]') !== false){
    $comment_approved = 'spam';
}

De momento, el SPAM que está llegando se está etiquetando todo automáticamente como tal. A ver cuanto dura la solución… aunque en esta tengo bastante confianza!

Usando Fancybox y corrigiendo error en CKEditor usando typeof

Quiero empezar a poner más imágenes ilustrando los artículos del blog, así que hace unos días me puse a buscar algún plugin que permitiera ampliar las imágenes de los artículos. Encontré unos cuantos, pero todos eran bastante similares y tampoco encontré muchas demos de funcionamiento. Al final, como el que usa Baratijas Blog me gustaba, pues me he puesto el mismo:

http://wordpress.org/extend/plugins/fancybox-for-wordpress/

Al instalarlo, me he puesto a hacer pruebas, y en la página principal del blog funcionaba sin problemas, pero al pinchar en alguno de los artículos dejaba de funcionar. Pensaba que podía ser problema del tema, pero al mirar la consola de errores de Javascript, he visto que lo que fallaba era un script del plugin para integrar el CKEditor. El error que me daba era "getUserSetting is not defined" en el fichero ckeditor.utils.js. Es posible que este error ya esté solucionado en las nuevas versiones del plugin, pero como era una chorrada he realizado yo la corrección.

La modificación es sustituir esta línea:

if(ckeditorSettings.autostart && getUserSetting('editor') == 'tinymce'){

Por esta otra:

if(ckeditorSettings.autostart && typeof getUserSetting == 'function' && getUserSetting('editor') == 'tinymce'){

Lo que hacemos con la instrucción typeof es comprobar que el método getUserSetting está definido antes de intentar invocarlo.

Y con esto, ya no salta el error y el lightbox vuelve a funcionar. La prueba de concepto:

Una rosa

Acordeón Javascript para el listado de artículos

Esto es algo que tenía en el viejo blog, y me gustaba por la facilidad que da de ir a alguno de los artículos. Estuve buscando a ver si ya existía un plugin o widget que me ofreciera la funcionalidad, pero no encontré nada, así que lo vi como la oportunidad ideal de aprender a crear widgets para WordPress.

Buscando tutoriales, encontré unos cuantos, pero muchos están desfasados y solo cubren versiones anteriores de WordPress. Otros tantos están incompletos o dan información por supuesta, por lo que no son demasiados útiles para empezar. Al final encontré este que explica paso a paso la creación de un widget funcional:

http://www.packtpub.com/article/how-write-widget-wordpress-3

Siguiendo el tutorial, la creación del widget es muy sencilla, y pude reutilizar la mayor parte del código PHP que tenía para el viejo blog (excepto la obtención de los datos de los artículos que ahora pasa a hacerse a través de la API de WordPress). Lo que no es tan inmediato es la carga del Javascript necesario para el acordeón. Hay que usar un hook tal y como se explica en esta página:

http://noteslog.com/post/how-to-load-javascript-in-wordpress-plugins/

Indicando la URL del script de manera relativa al plugin/widget tal y como se explica en el codex de WordPress:

http://codex.wordpress.org/Function_Reference/plugins_url

El resultado sería algo similar a esto:

function load_into_head(){
    echo '<script type="text/javascript" src="'
    .plugins_url('accordion.js', __FILE__).'"></script>'."n";
    echo '<link rel="stylesheet" href="'
    .plugins_url('acc-styles.css', __FILE__)
    .'" type="text/css" media="screen" />';
}

add_action('wp_head', 'load_into_head');

Donde estoy cargando tanto el script del acordeón como una hoja con sus estilos en la cabecera de la página donde aparezca el widget.

En cuanto tenga un poco de tiempo limpiaré y comentaré el código y compartiré el widget por si alguien lo quiere utilizar. También me hará falta darle un nombre. De momento se llama "Article Accordion" que no es muy original, aunque es bastante autoexplicativo :P. ¿A alguien se le ocurre un buen nombre?