Taula de continguts

Implementació a Wordpress d'un menú d'opcions amb desplaçament automàtic segons la posició del ratolí

Introducció

Aquest tutorial explica com fer un menú semblant o equiparable a aquest dins de Wordpress, i es basa en la documentació proveïda al mateix lloc web però també necessàriament en moltes altres pàgines visitades.

Malgrat la obvietat, pot estalviar algun maldecap fer saber que aquesta solució és útil quan l'espai que el conjunt de les opcions del menú ocupa és més gran que la grandària del menú definida dins el CSS. Si les opcions ocupen menys que el total del menú, òbviament no hi ha cap necessitat de desplaçar res, i la solució proposada no ho farà.

Al llarg de la implementació d'aquest menú a la pàgina d'un dels meus clients, em vaig trobar amb problemes principalment a causa del fet que a la mateixa pàgina ja hi havia un altre element que, com aquest menú, feia ús de llibreries extra de javascript, en aquest cas jQuery, i això semblava causar unes obscures incompatibilitats que, evidentment, em va caldre resoldre.

Bé, de fet em vaig trobar amb problemes molt abans, perquè pel camí he provat moltes altres opcions de desplaçament que m'han donat problemes similars, però al final he optat per aquesta.

Per què aquesta opció?

Comencem

La primera qüestió que cal tenir resolta és on anirà ubicat aquest menú. Això no s'aborda en aquest tutorial i és quelcom que hauràs resolt posicionant amb CSS. En el meu cas, el codi que necessitava per fer funcionar l'script i pel que fa a les etiquetes XHTML, dins els altres div posicionats oportunament, tenia aquest aspecte:

  <div class="retallMenuSupEsquerre">
  	<ul class="retallMenuSupEsquerre">
  		<li>
  			<a href="<?php bloginfo('url') ?>/?p=42">
  				<img src="<?php bloginfo('stylesheet_directory'); ?>/images/quelcom1.jpg" />
  				<span>quelcom 1</span>
  			</a>
  		</li>
  		<li>
  			<a href="<?php bloginfo('url') ?>/?p=45">
  				<img src="<?php bloginfo('stylesheet_directory'); ?>/images/quelcom2.jpg" />
  				<span>quelcom 2</span>
  			</a>
  		</li>
  		<li>
  			<a href="<?php bloginfo('url') ?>/?p=47">
  				<img src="<?php bloginfo('stylesheet_directory'); ?>/images/quelcom3.jpg" />
  				<span>quelcom 3</span>
  			</a>
  		</li>
  	</ul>
  </div>
Inclusió del CSS

Quan ja hem introduït els elements de l'XHTML, hem de declarar aquestes classes i especificacions en el CSS, a fi que després la funció de javascript pugui actuar d'acord amb els valors assignats. De la pàgina de la documentació extrec directament això, només canviant el nom de la classe per defecte pel nom que he utilitzat en el meu exemple:

  div.retallMenuSupEsquerre {
  	/* Set it so we could calculate the offsetLeft */
  	position: relative;
  	height: 145px;
  	width: 500px;
  	/* Add scroll-bars */
  	overflow: auto;
  	}
  	
  ul.retallMenuSupEsquerre {
  	display: block;
  	height: 110px;
  	/* Max width here, for users without Javascript */
  	width: 1500px;
  	padding: 15px 0 0 15px;
  	/* Remove default margin */
  	margin: 0;
  	background: url('navigation.png');
  	list-style: none;
  	}
  
  .retallMenuSupEsquerre li {
  	display: block;
  	float: left;
  	padding: 0 4px;
  	}
  
  .retallMenuSupEsquerre a {
  	display: block;
  	text-decoration: none;
  	}
  
  .retallMenuSupEsquerre span {
  	display: none;
  	margin-top: 3px;
  	text-align: center;
  	font-size: 12px;
  	color: #fff;
  	}
  
  .retallMenuSupEsquerre a:hover span {
  	display: block;
  	}
  
  .retallMenuSupEsquerre img {
  	border: 3px #fff solid;
  	-webkit-border-radius: 3px;
  	-moz-border-radius: 3px;
  	}
  
  .retallMenuSupEsquerre a:hover img {
  	filter:alpha(opacity=50);
  	opacity: 0.5;
  	}

Bona part d'aquests paràmetres es poden modificar al vostre gust, i fins i tot pot haver-n'hi alguns que no siguin estrictament necessaris. Conserveu, però, en el seu lloc la propietat overflow i el seu valor auto dins la definició de la classe div.retallMenuSupEsquerre, ja que el javascript ha de trobar definit aquest valor a fi de poder eliminar les barres d'scroll i desencadenar el desplaçament automàtic. Internet Explorer no executarà correctament l'script si falta aquest paràmetre, tot i que altres navegadors semblen ser més tolerants.

Tingueu present també que les propietats -webkit-border-radius i -moz-border-radius no estan incloses, diria, a la versió 2 de l'especificació de CSS. No estic segur si la propietat filter tampoc.

Inclusió de les funcions de Javascript

Com hem dit, aquest efecte és possible gràcies a les llibreries jQuery, que proporcionen un accés optimitzat a funcions i possibilitats avançades de Javascript. Aquestes llibreries, siguin solucions tipus jQuery o d'altres possibles com Prototype, s'han de referenciar. Per tant, tenim per una banda l'script que fa la màgia del moviment dins el menú, i per l'altra les llibreries que aquest script necessita per funcionar.

Tots dos elements, l'script i la referenciació a les llibreries, han d'anar inclosos dins l'element head de la pàgina, ja que aquest element comprèn tots els altres que necessiten ser carregats abans que els continguts pròpiament de la pàgina. L'element head es troba dins el fitxer header.php, per defecte, però pot ser que vosaltres l'hagueu inclòs dins una única pàgina index.php. Ja veurem, però, que la referenciació a les llibreries necessita algunes precisions i correccions, des del meu punt de vista, respecte el que es diu a la pàgina de la documentació original.

Incloure l'script és tan trivial com enganxar el codi següent dins el head i assegurant-nos que ho fem després (en l'estructura del document) de la crida

  <?php wp_head(); ?>

codi de l'script:

  <script type="text/javascript">
  <!-- inicialitzador de la funció per a l'scroll de les icones dins el menú superior esquerre -->
  jQuery(document).ready(function(){
  	//Get our elements for faster access and set overlay width
  	var div = $('div.retallMenuSupEsquerre'),
  		ul = $('ul.retallMenuSupEsquerre'),
  		ulPadding = 15;
  	
  	//Get menu width
  	var divWidth = div.width();
  
  	//Remove scrollbars	
  	div.css({overflow: 'hidden'});
  	
  	//Find last image container
  	var lastLi = ul.find('li:last-child');
  	
  	//When user move mouse over menu
  	div.mousemove(function(e){
  		//As images are loaded ul width increases,
  		//so we recalculate it each time
  		var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;	
  		var left = (e.pageX - div.offset().left) * (ulWidth-divWidth) / divWidth;
  		div.scrollLeft(left);
  	});
  });
  <!-- Final inicialitzador de la funció per a l'scroll de les icones dins el menú superior esquerre -->
  </script>

Si heu repassat la documentació original observareu que es fa servir

  $(document).ready(function()

en lloc de

  jQuery(document).ready(function()

Als enllaços esmentats al principi sobre CMS podeu veure diverses pàgines i articles que aborden per què majoritàriament cal evitar fer servir $ en les crides a jQuery i utilitzar directament jQuery.

Però el problema no s'acaba aquí. Resulta que la documentació original indica que cal referenciar jQuery utilitzant el següent element de referenciació d'scripts:

  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" type="text/javascript"></script>

El que això revela, si mirem les tripes de la nostra instal·lació de Wordpress en el cas de la versió 2.7, és que es fa servir una versió de jQuery més moderna de la que per defecte hi ha instal·lada. D'altra banda, alguns enllaços esmentats al principi sobre CMS aborden la qüestió de quina és la manera òptima de fer aquesta referenciació a les llibreries externes (encara que no siguin jQuery) en Wordpress. I la conclusió és que, a més del fet que des del meu punt de vista no és convenient haver de dependre d'uns fitxers proporcionats per pàgines de Google, cal referenciar les llibreries no dins el document header.php o index.php sinó en un fitxer ad hoc que hi ha a la instal·lació de Wordpress: functions.php, que es troba al directori de la plantilla default de Wordpress.

L'aspecte que té la primera línia d'aquest fitxer en el meu cas és el següent:

  wp_enqueue_script('jqueryUpd', '/wp-includes/js/jquery-1.3.2.min.js');

Com veieu, aquí es fa ús de la instrucció wp_enqueue_script per tal de referenciar globalment al sistema l'ús de la llibreria jquery-1.3.2.min.js. El que he fet simplement és descarregar de la pàgina proporcionada a la documentació el fitxer .js en qüestió, i posar-lo al directori que conté totes les llibreries js de Wordpress.

jqueryUpd és un identificador arbitrari que assigno a la llibreria que vull carregar i que ve a significar quelcom per l'estil de jQuery Updated. No estic segur que es pugui ser tant arbitrari en tots els casos, però en aquest no sembla donar problemes.

Si volguessim referenciar altres llibreries, relacionades o no amb jQuery, només caldria procedir de manera anàloga i referenciar-ho a functions.php. Tingueu present que les darreres versions de Wordpress ja vénen amb força llibreries instal·lades per defecte, com Prototype i scriptaculous, però probablement calgui referenciar-les explícitament per utilitzar-les.

Podeu veure més informació sobre wp_enqueue_script i totes aquestes qüestions abordades aquí dalt als enllaços sobre CMS que he indicat abans (encara no has obert la pàgina a una altra pestanya?!)

El fet que es referencïin en un fitxer extern aquestes llibreries és el motiu pel qual els scripts han d'anar després de

  <?php wp_head(); ?>

ja que aquesta és el codi que carrega, entre altres coses, les instrucciones incloses dins de functions.php. Per tant, quan l'script es declari ja han d'haver estat declarades les referències a les llibreries. Si no fos així, l'script no les podria utilitzar.

Pot ser revelador que mireu el codi font de la pàgina amb el PHP ja executat. Veureu que l'intèrpret ha inclòs les referències dins el fitxer functions.php en elements script src=“ruta/alavostra/llibreria” al document interpretat.

Finalment

Fet això el menú hauria de funcionar. Recomano molt que observeu i estudieu el codi font de la pàgina d'exemple del menú, tant per provar-ne el funcionament abans de tirar-vos-hi de cap, com per depurar els problemes si quelcom no funciona. Des del meu punt de vista, sovint és interessant assegurar-se que les coses funcionen fora d'un entorn dinàmic (sense parts interpretades amb PHP, per tant, ni inclusions a llibreries a través d'obscurs wp_enqueue_script) abans de passar a un entorn dinàmic.

Amb una mica de sort, doncs, tot el que restarà serà barallar-se amb el CSS perquè s'ajusti a les vostres necessitats