In questo articolo voglio affrontare un problema di personalizzazione di un tema WordPress. Più precisamente, si tratta di cambiare la presentazione della data di pubblicazione dei posts nella home del tema Twenty Eleven di WordPress, rispettando la ‘responsivity‘ del tema.

Cosa vogliamo realizzare

Nel layout originale di Twenty Eleven (TE nel seguito) la data di pubblicazione di un post nella front page (quando impostata per visualizzare gli ultimi posts pubblicati) è collocata sotto il relativo titolo. Invece il design desiderato prevede un elemento grafico, tipo clip, allineato alla sinistra del titolo e a bordo pagina. Alcuni riferimenti su questo tipo di designs sono:

Come detto nell’introduzione, questa modifica deve essere compatibile con il carattere “responsive” del tema. Questo significa che la clip della data deve sempre rimanere ancorata alla sua posizione a prescindere dalla larghezza della finestra che visualizza la pagina.

Inoltre, come ulteriori requisiti, vogliamo generare un markup che utilizzi il tag HTML5 <time> (usato nel markup originale di TE) e visualizzare un tooltip con la data completa (quindi anche con l’ora) quando l’utente passa sopra la data con il mouse.

Implementazione

Svilupperemo un child theme di TE con quattro files:

  • functions.php
  • style.css
  • js/post-date.js
  • img/post-date-clip.png

Esaminiamoli uno alla volta.

functions.php

add_action('template_redirect', 'on_template_redirect');

function on_template_redirect() {
	if (!is_home()) 
		return;
		
	wp_enqueue_script(
		'post-date', 
		'/wp-content/themes/twentyeleven-child/js/post-date.js', 
		array('jquery'), 
		'', 
		true);
}

function twentyeleven_posted_on() {
	if (is_home()) 
		printf(__(
			'<time datetime="%1$s" pubdate title="%2$s">' . 
				'<span class="month">%3$s</span>' . 
				'<span class="day">%4$s</span>' . 
			'</time>', 'twentyeleven'),
			esc_attr(get_the_date('c')),
			esc_attr(get_the_date('r')),
			esc_html(strtolower(get_the_date('M'))),
			esc_html(get_the_date('d'))
		);
	else {
		printf(__(
			'<span class="sep">Posted on </span>' . 
			'<a href="%1$s" title="%2$s" rel="bookmark">' . 
				'<time class="entry-date" datetime="%3$s" pubdate>%4$s</time>' . 
			'</a>' . 
			'<span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="%5$s" title="%6$s" rel="author">%7$s</a></span></span>', 'twentyeleven' ),
			esc_url( get_permalink() ),
			esc_attr( get_the_time() ),
			esc_attr( get_the_date( 'c' ) ),
			esc_html( get_the_date() ),
			esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
			esc_attr( sprintf( __( 'View all posts by %s', 'twentyeleven' ), get_the_author() ) ),
			get_the_author()
		);
	}
}

Il primo passo è l’inclusione dello script JavaScript, il cui scopo verrà esaminato dopo. A tal fine invochiamo la funzione wp_enqueue_script() con dei parametri che, oltre a fornire la locazione dello script, specificano la sua dipendenza da jQuery (anche se probabilmente la libreria dovrebbe essere già caricata nella pagina) e la sua posizione all’interno del documento con il parametro finale true, per ‘iniettare’ lo script a fine pagina, prima della chiusura del tag body.

Includiamo questo script solo quando serve, e cioè solo quando viene servita la home page. Per fare ciò usiamo l’hook ‘template-redirect’ e un conditional tag.

Poi abbiamo l’overriding della funzione twentyeleven_posted_on() che TE utilizza per l’output del markup per la data di pubblicazione. Override che anche in questo caso deve avvenire solo nella home, ancora una volta usando un conditional tag. Il markup che viene generato è un elemento <time> a cui viene applicato il tooltip con la full date e al cui interno annidiamo i tags per il mese ed il giorno.

CSS

/*
Theme Name:     Twenty Eleven Child
Theme URI:      http: //example.com/
Description:    Child theme for the Twenty Eleven theme 
Author:         Giulio Mainardi
Author URI:     http: //mgiulio.altervista.org
Template:       twentyeleven
Version:        0.1.0
*/

@import url("../twentyeleven/style.css");

.home .entry-header .entry-meta {
	position: absolute;
	width: 36px;
	height: 50px;
	padding: 0;
	top: 15px;
	overflow: hidden;
	background: url(img/post-date-clip.png) transparent no-repeat left top;
}
.home .entry-header .entry-meta time {
	display: block;
	height: 50px;
	padding: 0;
}
.home .entry-header .entry-meta .month {
	display: block;
	color: #fff;
	text-align: center;
	font-size: 9px;
}
.home .entry-header .entry-meta .day {
	display: block;
	color: #fff;
	text-align: center;
	font-size: 14px;
	font-weight: bold;
}

Agiamo sugli elementi .entry-header > .entry-meta, che TE utilizza per racchiudere le meta informazioni del post. Da notare il prefisso .home per applicare queste regole solo ai posts della home page.

Primo, assegniamogli una background-image con delle trasparenze per rappresentare la clip

Secondo, e più importante, l’uso del posizionamento assoluto per ‘estrarre’ dal layout del documento il suddetto elemento e posizionarlo nella locazione desiderata. Il contesto di questo elemento è l’<article> a cui esso appartiene. Applicando un piccolo offset con la proprietà top risolviamo l’allineamento verticale con il titolo del post. A questo punto dovremmo settare la componente orizzontale, con la proprietà left, impostando un offset negativo pari in valore assoluto alla distanza che intercorre tra il lato sinistro del post ed il bordo sinistro della pagina del documento. Il problema è che TE è un tema ‘responsive‘ e quindi tale gap è determinato con una percentuale applicata alla proprietà margin-left del #content e di conseguenza non può essere computata staticamente. Ecco spiegato il ricorso a JavaScript, che andiamo subito a vedere.

JavaScript

(function($) {
var
	dates = $('.entry-header .entry-meta'),
	page = $('#page'),
	post = $('#content > article.post')
;

$(window).on('resize', keepDateAligned);

keepDateAligned();

function keepDateAligned() {
	dates.css('left', -(post.offset().left - page.offset().left) - 5 + 'px');
}

})(jQuery);

Usiamo jQuery. Possiamo tranquillamente usare la versione 1.7.1 dato che è inclusa in WordPress 3.3.

Registriamo un handler per l’evento di resizing della finestra del browser, dove poter effettuare in maniera dinamica il calcolo della proprietà left per il corretto posizionamento orizzontale della data. Per determinare l’offset voluto ricorriamo al metodo .offset() dell’oggetto jQuery, che ritorna le coordinate relative al documento dell’elemento a cui è applicato. Aggiungiamo un ulteriore offset dipendente dal design della clip ed il gioco è fatto.

Conclusione

La soluzione presentata non è ‘La Soluzione’ ma ‘Una’ soluzione possibile. Per esempio, sarebbe interessante una soluzione senza JavaScript, che però non cambi troppo la struttura originaria del markup generato da TE.