Archivo de la etiqueta: Javascript

Por qué no devolver false en un controlador de evento en jQuery

[programación]

Durante mucho tiempo he abusado de devolver false en los controladores de eventos de jQuery.

Por ejemplo:

$( 'a.un-link' ).on( 'click',
  function ( oEvent ) {
    // Hacer algo aquí!

    return false;
  }
);

Ese return false; es equivalente a hacer:

oEvent.preventDefault();
oEvent.stopPropagation();

Mi impresión es que está haciendo demasiado, ya que es posible que queramos que el evento se propague a alguno de los contenedores superiores.

En la mayoría de casos lo único que estamos intentando es prevenir que al hacer click, se redireccione a la dirección en el href del enlace, y para eso con oEvent.preventDefault() sería suficiente. Es por eso que estoy siguiendo las siguientes pautas en mi código más reciente:

  • oEvent.preventDefault() al inicio del método.
  • No devolver nada.
$( 'a.some-link' ).on( 'click',
  function ( oEvent ) {
    oEvent.preventDefault();
    // Hacer algo aquí!
  }
);

Esto impedirá la redirección y permitirá a los controladores superiores tratar el evento.

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

[programación]

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

[programación]

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

[programación]

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

[programación]

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

[programación]

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

[internet] [programación]

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

[programación]

Ú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

[blog] [programación]

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

[fotografía] [programación]

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:

Fancybox plugin para 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

[ACTUALIZACIÓN] Al abandonar Wordpress, Fancybox ya no está instalado.