Professional Documents
Culture Documents
En 20 clases te explicamos la base para poder explotar todas las capacidades de esta potente y popular plataforma para gestionar contenidos.
2013 - Summarg.com
Introduccin
Este taller pretende introducir a la creacin de themes WordPress a aquellos con poca experiencia en el tema, por ende utilizaremos un nivel bsico en lo referente al tema. Apuntamos a que el lector aprenda a instalar un servidor local y pasar un diseo de PSD (Photoshop) a theme WordPress compuesto por diversos formatos de archivos (PHP, JS, CSS, imgenes, etc.). Para modificaciones de nivel medio y superior, pueden chequear nuestra seccin de WordPress que contina en constante actualizacin. Existen varios tutoriales en la red que ofrecen crear themes en pocos pasos, en 15 minutos o sin esfuerzo. Nosotros elaboramos un temario que consiste en varias clases puesto que nuestra intencin es que el lector aprenda a crear los themes entendiendo cada paso del proceso para poder tener la libertad de iniciarse luego en temas mas complejos y para lograr resultados cada vez mas interesantes. Las siguientes herramientas sern necesarias para poder seguir el tutorial: Notepad++ (gratuito) u otro editor de cdigo como Dreamweaver. Photoshop u otro editor de imgenes. XAMPP (gratuito) servidor local. FileZilla (opcional gratuito) o cualquier aplicacin FTP para subir tu trabajo a un servidor remoto. JS Screen Ruler (opcional gratuito) regla para tu pantalla, ayuda a ajustar detalles. Abarcaremos todos los temas listados de a uno por clase, insertando los enlaces en cada entrega semanal. El temario est sujeto a cambios segn lo veamos conveniente.
Indice de clases
Clase 1: Introduccin: Instalar WordPress en un servidor local ------------- Pag 5 XAMPP Generar una base de datos desde PhpMyAdmin Contenido de pruebas para la plataforma Clase 2: Cmo encarar el diseo a partir de un archivo PSD ----------------- Pag 8 Presentamos nuestra plantilla. Introduccin a las partes de un theme. Clase 3: Comenzamos a maquetar! --------------------------------------------------- Pag 11 Comenzamos a maquetar el index.php Funciones bsicas de header.php El archivo de estilos CSS Clase 4: El bucle y jerarquas de templates ----------------------------------------- Pag 21 El bucle Funcionamiento de la jerarqua de templates El bucle en los templates Clase 5: El bucle avanzado: Query_posts ------------------------------------------- Pag 25 Mltiples bucles en la misma pgina Uso bsico de the_post_thumbnail Clase 6: El archivo header.php y los mens en WordPress ------------------- Pag 29 Funcin de wp_head() Introduccin a condicionales de template Aplicaciones de bloginfo Mens con wp_nav_menu Clase 7: Implementar Nivo-slider sin plugins --------------------------------------- Pag 36 Trabajar con jQuery Insertar Nivo-Slider y adaptarlo al theme Clase 8: Sidebar y widgets ---------------------------------------------------------------- Pag 40 Qu son y cmo funcionan los widgets? Aadir mas sidebars Clase Anexo: Aadir una sidebar horizontal -------------------------------- Pag 45 Clase 9: El archivo footer.php ------------------------------------------------------------ Pag 48 Funcin y usos frecuentes Aadir rea de widgets Aadir men secundario y link al inicio
Clase 10: La plantilla de entrada y de comentarios ------------------------------- Pag 54 Single.php, layout y contenidos Los comentarios Clase 11: La plantilla de pgina ---------------------------------------------------------- Pag 64 Pginas personalizadas Pginas y subpginas Plantilla de pginas con query_posts Clase 12: archive.php y plantillas por categora, fecha, autor, taxonoma, etiqueta ---------------------------------------------------------------------------------------------- Pag 72 Extra: Mostrar favicon y tags para Facebook Template Conditionals: Categoras por id Template Conditionals: Autor, Etiquetas Clase 13: Pgina de bsquedas: search.php e integracin con Google CSE ------------------------------------------------------------------------------------------------------- Pag 80 Search.php y personalizacin de la plantilla Incorporar bsquedas con Google CSE Clase 14: Paginacin, breadcrumbs y pgina de error 404.php -------------- Pag 85 Snippets para paginar y para colocar breadcrumbs sin usar plugin Clase 15: Framework para opciones administrativas e insercin de anuncios ------------------------------------------------------------------------------------------------------- Pag 90 Insercin de anuncios Insercin de campos de texto Clase 16: Custom Post Types: Portfolio y plantilla single-cpt.php --------- Pag 97 Metabox: Los custom fields de forma fcil La plantilla single-cpt.php Clase 17: Custom Post Types: Portfolio y plantilla de taxonoma ---------- Pag 108 Plantilla de Taxonoma Pgina personalizada para el portfolio con jQuery Isotope Clase 18: Custom Post Types: Formulario de bsqueda ---------------------- Pag 116 Clase 19: Plugins y snippets recomendados -------------------------------------- Pag 121 Clase 20: Conclusiones y descarga del taller completo ----------------------- Pag 129
4
Instalador de XAMPP
Con esta finalidad instalaremos XAMPP, un servidor disponible para varios sistemas operativos y cuya instalacin es muy sencilla. 1. Descargamos la versin de XAMPP que corresponda a nuestro sistema operativo desde aqu: http://sourceforge.net/projects/xampp/files/. El primer link que ofrecen es el del ltimo instalador para Windows disponible. 2. Lo ejecutamos y corremos la instalacin. Al finalizar, corremos la aplicacin y nos aseguramos de que estn corriendo los servicios Apache y MySQL. Ingresamos a http://localhost/ en nuestro navegador.
Es necesario saber que XAMPP es un servidor pensado en desarrolladores y no es recomendable para produccin (es decir, no se recomienda utilizar para abrir un website al pblico desde nuestra computadora). 3. phpMyAdmin es una aplicacin que nos permite gestionar todo lo referente a nuestras bases de datos, es una de las mas populares y gran parte de los hostings generalmente la ofrecen en sus paneles, as que es buena idea familiarizarse con la misma. Primero cambiaremos la contrasea, por defecto el campo viene vaco. Abrimos con nuestro Notepad++ el archivo c:/xampp/ phpmyadmin/config.inc.php, colocamos un usuario, su contrasea y cambiamos el valor de AllowNoPassword a false. $cfg[Servers][$i][user] = root; $cfg[Servers][$i][password] = ****; $cfg[Servers][$i][AllowNoPassword] = false; Ahora ingresamos a http://localhost/phpmyadmin y nos preparamos para crear una base de datos. Le asignaremos un nombre y cambiamos el cotejamiento de la base de datos a utf8_unicode_ci (es el ltimo select de la lista).
4. Nuestra base de datos ser wordpress, el usuario root y la contrasea la que hayamos definido en el config.inc.php arriba mencionado. Con esto completado ya podemos descargar la ltima versin de WordPress desde el sitio oficial y descomprimirlo dentro del directorio c:/xampp/ htdocs/. Abrimos el archivo wp-config-sample.php y editamos los siguientes datos. /** El nombre de tu base de datos de WordPress */ define(DB_NAME, wordpress); /** Tu nombre de usuario de MySQL */ define(DB_USER, root); /** Tu contrasea de MySQL */ define(DB_PASSWORD, tucontrasea); Guardamos el archivo con el nombre wp-config.php e ingresamos a http://localhost en nuestro navegador, nos llevar directo a la pantalla de instalacin de WordPress, en donde completamos
5. Para completar nuestra clase de hoy cargaremos algn contenido de pruebas en nuestro WordPress, de modo de que tengamos algunas entradas, categoras y pginas con diferentes formatos de texto para visualizar cuando trabajemos cada plantilla. En esta nota ya habamos hablado de este recurso que pueden descargar directamente de aqu https://wpcom-themes.svn.automattic. com/demo/test-data.2011-01-17.xml En nuestro panel de administrador nos dirigimos a herramientas > importar > wordpress. Subimos el archivo y aceptamos. Con esto ya tendremos nuestro WordPress instalado en un servidor local y podremos empezar a trabajar en l en nuestra prxima clase.
La activacin de los permalinks de WordPress en nuestro servidor local XAMPP, WAMPP o AppServ puede resultar fundamental para trabajar con comodidad. Por lo general bastar con activar los Permalinks desde Ajustes > Enlaces permanentes y crear el .htaccess con el contenido que WordPress nos facilita. En algunos casos el mdulo rewrite no est activado por lo que tendremos que buscar el archivo httpd.conf dentro de apache/conf/. La carpeta apache puede llamarse apache2 dependiendo del software que utilicemos. Utilizamos un editor como Notepad++ y buscamos la siguiente lnea: #LoadModule rewrite_module modules/mod_rewrite.so Removemos el signo #. Luego buscamos las siguientes lneas: AllowOverride All## Controls who can get stuff from this server.#Order allow,denyAllow from all Y nos aseguramos de que AllowOverride All no tenga numeral. Guardamos y reiniciamos XAMPP.
El set de conos sociales es Socialis21 y pueden encontrar el link de descarga aqu: Socialis21 En el pie de pgina pueden encontrar la paleta de colores utilizada para el theme y la compartimos para que puedan crear nuevas secciones dentro de la plantilla haciendo uso de la misma. Antes de empezar a maquetar conozcamos un poco lo que vamos a hacer. Los themes WordPress utilizan varios archivos a la vez para formar una pgina, que son llamados por funciones especficas de la plataforma para facilitar las cosas. Son similares a la funcin include de PHP y nos evitan tener que escribir la misma porcin de cdigo en varias plantillas. Por ejemplo, la seccin del encabezado del sitio siempre es igual, llevar un logo y una botonera que no deseamos que cambie. En un sitio construido ntegramente en HTML deberamos copiar este cdigo en cada una de las pginas. Pero en WordPress bastar con escribir todo el cdigo del encabezado dentro de header.php y luego solicitar el encabezado en cada seccin que lo necesite-
mos. Lo mismo cuenta para la barra lateral (sidebar.php) y el pi de pgina (footer.php). De ese modo cuando se lista el index de un sitio WordPress, ste estar compuesto de los archivos header.php, index.php, sidebar.php y footer.php. Para el caso de listar una pgina los archivos sern: header.php, page.php, sidebar.php y footer.php. Qu cambi? El inicio utiliza index. php para mostrar su contenido principal y una pgina utiliza el archivo page.php. Para solicitar desde el index.php los archivos en cuestin utilizaremos las funciones: get_header(); get_sidebar(); get_footer(); Entonces dividiremos el home (index.php) en 4 archivos que los marcamos a la derecha en la siguiente imagen (en el zip de descarga del theme encontrarn la imagen en tamao grande).
A la izquierda indicamos los elementos que consideramos necesario nombrar, con sus respectivos atributos class e id. De este modo el archivo header.php contendr, entre cosas, el elemento #header, que dentro de s contendr el un #menu-top, el #logo y el #menu. El contenido de la pgina (el fondo blanco con bordes redondeados) se llamar #content y el ancho del diseo ser fijo (960px). Todos los colores y bordes pueden definirse directamente desde el CSS, aunque si quieren ser fieles al diseo slo debern recortar un rectngulo pequeo con el fondo de la barra del men y el fondo gris de los productos destacados:
Para recortar las partes del theme en Photoshop, debern utilizar la herramienta mscara y seleccionar la seccin. En nuestro caso seleccionamos el logo. Luego seleccionan image > crop y guardan el resultado utilizando la opcin save for web & devices (guardar optimizado para la web) como logo.png. Tambin necesitarn repetir el proceso con los conos sociales.
10 La clase que viene comenzamos a maquetar esta pgina. Descarguen el archivo PSD y empiecen a ver como est compuesto.
11
Creamos los siguientes archivos en nuestro directorio /themetaller/: index.php, footer.php, header. php, sidebar.php y style.css.
Y respetando la divisin de establecimos la clase pasada, comenzamos a crear el cdigo del header.php. Vamos a agregar en el encabezado, entre etiquetas <head> el siguiente cdigo: <!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http:// www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd> <html xmlns=http://www.w3.org/1999/xhtml <?php language_attributes(); ?>> <head profile=http://gmpg.org/xfn/11>
<meta http-equiv=Content-Type content=<?php bloginfo(html_type); ?>; charset=<?php bloginfo(charset); ?> /> <title> <?php if ( is_home() ) { ?><?php bloginfo(name); ?> | <?php bloginfo(description); ?><?php } ?> <?php if ( is_author() ) { ?><?php bloginfo(name); ?> | Archivo por autor<?php } ?> <?php if ( is_single() ) { ?><?php wp_title(); ?> | <?php wp_title(); ?><?php } ?> <?php if ( is_page() ) { ?><?php bloginfo(name); ?> | <?php wp_title(); ?><?php } ?> <?php if ( is_category() ) { ?><?php bloginfo(name); ?> | Archivo por Categoria | <?php single_cat_title(); ?><?php } ?> <?php if ( is_month() ) { ?><?php bloginfo(name); ?> | Archivo por Mes | <?php the_time(F); ?><?php } ?> <?php if ( is_search() ) { ?><?php bloginfo(name); ?> | Resultados<?php } ?> <?php if (function_exists(is_tag)) { if ( is_tag() ) { ?><?php bloginfo(name); ?> | Archivo por Tag | <?php single_tag_title(, true); } } ?> </title> <?php wp_head(); ?> <link rel=stylesheet type=text/css href=<?php bloginfo(stylesheet_ url); ?> media=screen /> <link rel=alternate type=application/rss+xml title=RSS 2.0 href=<?php bloginfo(rss2_url); ?> /> <link rel=pingback href=<?php bloginfo(pingback_url); ?> /> </head> El cdigo para el encabezado contiene informacin sobre el DOCTYPE, HTML, los meta, el charset, se vincula la plantilla de estilos, se indican los links de los feeds y del pingback, se colocan varios condicionales para el title (dependiendo de la seccin que se visualiza, mostrar un ttulo diferente) y finalmente la funcin wp_head(), que es la funcin que utiliza la plataforma para cargar scripts desde plugins y otra informacin adicional. Ahora si, maquetamos lo que vimos en la imagen de la clase pasada:
12
El cdigo HTML ser el siguiente: <body> <div id=content-wrapper> <div id=header> <div id=logo> <img src=http://localhost/wp-content/themes/themetaller/images/logo.png /> </div><!-- end of logo --> <ul id=menu-top> <li><a href=#>Link 1</a></li> <li><a href=#>Link 2</a></li> <li><a href=#>Link 3</a></li>
<li><a href=#>Link 4</a></li> </ul> <ul id=menu> <li><a href=#>Inicio</a></li> <li><a href=#>Pgina esttica</a></li> <li><a href=#>Categora</a></li> <li><a href=#>Contctenos</a></li> </ul> </div> <!-- end of logo --> Para esta primera etapa no utilizaremos funciones WordPress, por lo que la ruta al logo es una ruta absoluta y los links de nuestros mens totalmente inventados, a modo de relleno para que nuestro primer trabajo posea algo de contenido y podamos ver la forma que toma. Para las imgenes de relleno utilizaremos el servicio de lorempixum.com, que nos permite tomar imgenes al azar indicando en el link el tamao de las mismas. El index.php comprenda esta seccin: 13
Al inicio de nuestro archivo vamos a llamar al header.php utilizando la funcin get_header(), y al final del mismo debemos insertar el archivo sidebar.php (con get_sidebar() ) y el archivo footer. php (con get_footer() ). <?php get_header(); ?> <div id=nivoslider> <img src=http://lorempixum.com/g/920/310 /> </div><!-- end of nivoslider --> <div id=featured> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3>
<p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> </div><!-- end of featured --> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <?php get_sidebar(); get_footer(); ?> El cdigo de sidebar.php: <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <li>Una noticia en la <li>Una noticia en la <li>Una noticia en la <li>Una noticia en la </ul> </div><!-- end of sidebar
14
Y el de footer.php, que llevar la funcin wp_footer(), similar a wp_header(). <div id=footer> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/
themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer --> </div><!-- end of content-wrapper --> <?php wp_footer(); ?> </body> </html> Hasta aqu el resultado ser una pgina con datos sin nada de estilo. Vale aclarar que todos los <div> que abrimos, llevan su correspondiente </div> de cierre con un comentario: <! end of nombre-div >. Esta prctica nos ayuda a tener mayor control sobre nuestras etiquetas, puesto que un sitio web puede volverse realmente complejo a medida que aadimos elementos. Cuantos mas comentarios tengamos, mas facil ser para nosotros luego encontrar errores cuando surjan. Adems recomendamos en todo momento hacer uso de la indentacin, separando los bloques de cdigo segn corresponda. Si colocamos themeTaller como el theme por defecto de nuestro WordPress en localhost ya deberamos ver todos los datos e imgenes, uno debajo del otro. Para que realmente tome forma tenemos que aadir el estilo, al cual debemos colocarle los datos del theme y un reset de estilo. /*Theme Name: themeTaller Theme URI: www.summarg.com Author: Nekko Description: themeTaller */ /* RESET */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } :focus { outline: 0; } body { line-height: 1; color: black; background: white;
15
} ol, ul { list-style: none; } table { border-collapse: separate; border-spacing: 0; } caption, th, td { text-align: left; font-weight: normal; } blockquote:before, blockquote:after, q:before, q:after { content: ; } blockquote, q { quotes: ; } Ahora si, procedemos a colocar el color de fondo de la pgina <body>, establecer las dimensiones, el color de fondo y los bordes redondeados de content-wrapper. Para este punto indicamos que nos ayudamos con aplicaciones online como css3generator.com para generar el cdigo CSS3 correspondiente a cada motor de navegador. body { background-color: #2d435a; font-family: arial, sans serif; font-size:12px; } #content-wrapper { width:960px; margin: 10px auto; background-color:white; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; overflow:hidden; display:block; } Escribimos el cdigo para los elementos del header: #header { padding: 5px 20px; } #logo img { float:left; width: 261px;
16
height: 53px; padding: 10px 0; } ul#menu-top { height:25px; width:220px; margin-top:0; float:right; } ul#menu-top li a { list-style-type:none; text-decoration:none; float:left; color: #7ec5ff; font-weight:bold; padding: 7px 10px; } ul#menu-top li a:hover { text-decoration:none; background-color: #7ec5ff; color:#fff; font-weight:bold; padding: 7px 10px; } ul#menu { float:left; width: 920px; margin: 0 auto; height:30px; background-image: url(images/menu_bg.png); background-repeat: repeat-x; background-color: #7ec5ff; } ul#menu li a{ float:left; list-style-type:none; text-decoration:none; color:#fff; font-weight:bold; padding: 10px 20px; border-left: 1px solid white; } ul#menu li a:hover { text-decoration:none; background-color: 8ed6ff; color: #f4f4f4; padding: 10px 20px; } Vayan visualizando el sitio para confirmar que cada paso est dado en la direccin correcta.
17
Ahora procedemos a dar estilo al espacio del slider, los bloques de productos-servicios destacados y de las noticias. #nivoslider { float:left; margin: 10px 20px; width: 920px; height: 310px; } #featured { float:left; width: 918px; height: 100px; margin: 0 20px; border: 1px solid #7b7b7b; border-right:none; background-image: url(images/destacado_bg.png); background-repeat: repeat-x; background-color: #dedddd; } .item { width: 295px; padding: 5px; height: 90px; overflow:hidden; border-right: 1px solid #7b7b7b; float:left; } .item h3 { font-family: arial, sans serif; font-weight:bold; font-size: 16px; line-height:30px; color: #7b7b7b; text-align:center; } .item p { font-family: arial, sans serif; font-weight:bold; font-size: 12px; line-height:20px; color: #7b7b7b; text-align:center; } Aqu hacemos un pequeo alto para introducir una aclaracin. Si ustedes visualizan el theme hasta aqu, vern que la tipografa ya no se ve igual que en nuestro PSD, en donde utilizamos la fuente Myriad Pro. Vale aclarar que en clases futuras podemos introducir fuentes mucho ms elegantes utilizando cufn o bien utilizar el servicio de fuentes de Google y @font-face. Seguimos
18
con el estilo de la seccin de noticias. .news { width: 293px; padding: 20px 0 10px 20px; float:left; } .news h2 { font-family: arial, sans serif; font-size: 22px; margin-top:10px; color: #7b7b7b; } .news p { font-family: arial, sans serif; font-size: 12px; line-height:18px; color: #7b7b7b; } Pasamos a dar estilo a los elementos de la sidebar. #sidebar { width: 293px; padding: 20px 20px 10px 0px; float:right; } #sidebar h3 { font-family: arial, sans serif; font-size: 18px; margin-bottom:10px; color: #7b7b7b; } #sidebar ul { list-style-type:none; } #sidebar ul li { padding: 5px 10px; border-bottom: 1px solid #7b7b7b; color: #7b7b7b; } Y finalmente el estilo del footer. #footer { float:left; background: #e6e6e6;
19
width: 920px; padding: 20px; height:100px; } ul.social { list-style-type:none; float:right; width:150px; } ul.social li{ float:left; } Para ir viendo la evolucin del trabajo instalamos un WordPress en SummArg en www.summarg. com/demos/themetaller. Les dejamos los archivos del ejercicio de hoy aqu ThemeTaller clase 3. Sientanse libres de plantear cualquier duda o comentarnos cmo lo haran ustedes tanto aqu como en nuestro foro. Nos vemos en la prxima clase!
20
ser ejecutado el bucle en una plantilla de categora, buscar las ltimas entradas de esa categora especfica. El mismo caso se dar en la plantilla de archivo por fecha (date), archivo por autor (author), etc. Un dato interesante es que WordPress tiene un sistema de jerarqua de plantillas, en donde primero busca una plantilla especfica y si no la encuentra cae en buscar una plantilla mas general para esa misma seccin. En caso de no existir una plantilla determinada, finalmente utilizar la plantilla index.php para mostrar el resultado del bucle de esa seccin.
22
Este esquema es una versin muy simplificada del complejo sistema de plantillas que posee WordPress 3.0 y que pueden visualizar aqu. Para poner en prctica lo visto hoy, insertaremos en nuestro ThemeTaller un bucle sencillo en la plantilla archive.php y veremos como reacciona cuando solicitamos diferentes categoras, archivos por fecha, por autor y tags. Mas adelante nos ocuparemos de personalizar algunas categoras en particular, hacer dos o tres templates diferentes para pginas y varias cuestiones mas. Para poder probar la efectividad del ejercicio tenemos que tener contenidos cargados en nuestro WordPress (en la primer clase vimos como importar algunos contenidos de prueba). Creamos el archivo archive.php y dentro colocaremos: <?php get_header(); ?> <div id=wrapper><?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=dos-tercios listado> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de bsquedas.</p>
<?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); ?> <?php get_footer(); ?> En este cdigo hemos cambiado the_content() que lista el contenido completo de una pgina, por the_excerpt(), que trae por defecto las primeras 55 palabras sin formato de la entrada. En el CSS aadimos las siguientes lneas: #wrapper {margin-left:20px;margin-top:20px;float:left;width:606px;} .dos-tercios {float:left;margin-bottom:20px;padding: 5px;width:596px;} .listado {border-bottom: 1px solid #7b7b7b;} Esta plantilla servir para ver: categoras, entradas por tags, entradas por autor, entradas por fecha, entradas por taxonoma y por post type. Podemos probar las siguientes URLs en nuestro servidor de pruebas (nosotros colocamos las URLs a nuestro WP de pruebas): http://www.summarg.com/demos/themetaller/?tag=post-formats http://www.summarg.com/demos/themetaller/?author=3 http://www.summarg.com/demos/themetaller/?cat=45 El mismo contenido sirve para los archivos single.php y page.php. Probemos colocar el mismo contenido de archive.php en page.php y en single.php cambiando the_excerpt() por the_content() y solicitemos una pgina. Como resultado tendremos una pgina con su respectivo ttulo, contenido completo, fecha y autor. http://www.summarg.com/demos/themetaller/?page_id=501 Y para avanzar un poco mas con el estilo del theme, podemos aadir valores para las propiedades bsicas que ubicaremos luego de body. Estas sern los headings (h1 a h6), p, a, cite, pre, ul, ol, li, table, etc. a, a:visited {color:#7ec5ff;text-decoration:underline;} a:hover {text-decoration: none;color:#8ed6ff;} small {font: normal 10px arial, Sans-serif;} img {border: none;margin: 3px;} p {font: normal 12px arial, Sans-serif;line-height:18px;padding: 0px 0px 15px 0px;margin: 2px 0;} table, td, tr {font: normal 12px arial, Sans-serif;line-height:18px;} td {padding:5px;} th {font: bold 13px arial, Sans-serif;line-height:18px;padding: 5px;} h1, h2, h3, h4, h5, h6 {color:#7ec5ff;padding:0px;} h1 {font: normal 26px/30px arial, Sans-serif;margin:0 0 5px 0;letterspacing:-1px;} h2 {font:normal 22px/24px arial, Sans-serif;letter-spacing:1px;margin:0 0 5px 0;} h3 {font:normal 20px/22px arial, Sans-serif;margin:0 0 10px 0;} h4 {font:bold 16px/24px arial, Sans-serif;margin:0;} h5 {font:bold 14px/22px arial, Sans-serif;margin:0;} h6 {font:normal 12px arial, Sans-serif;margin:0;} h1 a, h1 a:visited, h2 a, h2 a:visited, h3 a, h3 a:visited {color: #7ec5ff;text-decoration: none;} h1 a:hover, h2 a:hover, h3 a:hover {color: #7ec5ff;text-decoration: none;} h3 a, h3 a:visited, h4 a, h4 a:visited {color: #417394;textdecoration:none;}
23
form {margin:0px;padding:0px;} blockquote {padding: 10px 10px; margin:10px 0px 10px 0px; liststyle:none; border:1px solid #7ec5ff; background-color:#8ed6ff;font: normal 120%/100% Arial, sans serif; } ul{font: normal 12px arial, Sans-serif;list-style:circle;padding:0px; margin:0px;} ol{font: normal 12px arial, Sans-serif;list-styletype:decimal;padding:0px; margin:0px 0px 10px 10px; } li{margin: 0px 0px 0px 10px; padding: 0px;} table, tr, td {font-size:12px;} strong {font-weight:bold;}cite,em,i {font-style: italic;border: none;} pre{font-family:Courier New, Courier, monospace;font-size:12px;lineheight:15px;} En la prxima clase veremos como hacer consultas avanzadas con query_posts() para poder llenar los bloques de informacin del index.php que ya llevamos empezado. Ver el demo de esta clase | Descargar el theme con el ejercicio de esta clase 24
25
Tomamos la primer seccin en donde colocaremos los productos destacados y encontramos este cdigo HTML segn lo que trabajamos en la Clase 3: <div id=featured> <div class=item>
<h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> </div><!-- end of featured --> Creamos la categora Producto Destacado e insertamos tres entradas con ttulo y un poco de texto (slo unas lneas). Ahora reemplazamos por el bucle con query_posts, en donde los parmetros sern seleccionar tres posts (posts_per_page=3) de la categora Producto Destacado (category_name=Producto Destacado): <div id=featured> <?php query_posts(category_name=Producto Destacado&posts_per_page=3 ); while ( have_posts() ) : the_post(); ?> <div class=item> <h3><?php the_title(); ?></h3> <?php the_content(); ?> </div><!-- end of item --> <?php endwhile; wp_reset_query(); ?> </div><!-- end of featured --> Guardamos y probamos que nuestro theme nos muestre, efectivamente, nuestras tres entradas. Ahora procedemos a elaborar el segundo bucle que ser un poco mas complicado debido a que tiene imgenes con un tamao especfico. Para nuestras imgenes vamos a utilizar la funcin the_post_thumbnail disponible a partir de WP 3+ y que nos ofrece la posibilidad de gestionar miniaturas de tamaos personalizados sin necesidad de plugins. Para activar la funcin deberemos indicarlo en nuestro archivo functions.php, que hasta ahora no vimos, as que creamos un archivo llamado functions.php y dentro colocamos el siguiente contenido: <?php add_theme_support( post-thumbnails ); add_image_size( homepage-thumb, 290, 130, true ); ?> Con add_image_size indicamos a la plataforma que necesitamos un tamao personalizado al que llamaremos homepage-thumb y que deseamos que mida 290px de ancho por 130 de alto. Adems la imagen ser recortada y no redimensionada (el valor true final activa el crop, o re26
corte), de este modo evitamos que algunas imgenes se deformen. Ahora procedemos a crear la categora Noticias y subimos dos entradas las cuales tendrn una imagen que definiremos como destacada. En nuestro archivo index.php buscamos el siguiente cdigo: <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> Y lo reemplazaremos por nuestro segundo bucle, el cual modificaremos para que busque slo dos entradas en la categora Noticias. <?php query_posts(category_name=Noticias&posts_per_page=2 ); while ( have_posts() ) : the_post(); ?> <div class=news> <?php if ( has_post_thumbnail() ) { the_post_thumbnail( homepage-thumb ); } ?> <h2><a href=<?php echo get_permalink(); ?>><?php the_title(); ?></a></ h2> <?php the_excerpt(); ?> </div> <?php endwhile; wp_reset_query(); ?> Observen que en el lugar de la imagen ahora colocamos una llamada a the_post_thumbnail, especficamente a la miniatura homepage-thumb, cuyo valor definimos en el functions.php. Si ustedes desean cambiar el valor de las miniaturas una vez generadas, pueden hacerlo utilizando el plugin Regenerate Thumbnails, ya que una vez que WordPress genera las miniaturas cuando las subimos, no vuelve a regenerarlas al cambiar los valores mediante el functions.php. En nuestro segundo bucle usamos el ttulo (the_title) envuelto en la etiqueta <a> con un href que dentro contiene la funcin get_permalink. El resultado es el ttulo de la entrada con link a la misma. Y en vez de the_content (que nos trae el contenido entero de una nota, con el formato del texto incluido), utilizamos the_excerpt que nos traer las primeras palabras de la entrada sin formato. Los links que colocamos en cada funcin los llevarn directamente al codex de WordPress. org, herramienta fundamental para cualquier desarrollador que quiera avanzar en la creacin de themes o plugins para esta plataforma. Finalmente pasamos a nuestro tercer bucle, ubicado en la barra lateral. Creamos la categora Blog y generamos algn contenido (o reciclamos algo del contenido de pruebas que metimos
27
cambiando de nombre Uncategorized por Blog). Abrimos el archivo sidebar.php que contiene el siguiente HTML. <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br </ul> </div><!-- end of sidebar -->
E insertamos nuestro bucle con la nueva categora y solicitando 4 entradas. Tambin aadiremos el nombre del autor de cada entrada desde la funcin the_author. <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <?php query_posts(category_name=Blog&posts_per_page=4 ); while ( have_posts() ) : the_post(); ?> <li><a href=<?php echo get_permalink(); ?>><?php the_title(); ?></a> <br /> Por <?php the_author(); ?></li> <?php endwhile; wp_reset_query(); ?> </ul> </div><!-- end of sidebar --> Vern que en el caso de los ttulos que llevan links ahora los vemos en color celeste y con subrayado debajo. Eso se debe a que nunca definimos desde el style.css como deban verse, as que pasaremos a hacerlo. .news h2 a {color: #7b7b7b;text-decoration:none;} #sidebar ul li a{text-decoration:none;color: #7b7b7b;} Verificamos que se vea todo correctamente en nuestro servidor de pruebas y listo. http://www.summarg.com/demos/themetaller/ themeTaller clase 5 28
er(), y son de caracter obligatorios si pretendemos el correcto funcionamiento de nuestra plataforma. Se coloca de la siguiente manera: <head> <?php wp_head(); ?> </head> Aprovechando esta oportunidad, recordemos que en la Clase 3 colocamos la ruta a nuestro logo, en el header.php, de la siguiente manera: <div id=logo> <img src=http://localhost/wp-content/themes/themetaller/images/logo. png /> </div><!-- end of logo --> Ahora que tenemos conocimiento de como funciona bloginfo(), podemos aprovechar y ponerlo en prctica. Reemplazaremos la parte de la ruta que corresponde al theme por la funcin: <div id=logo> <img src=<?php bloginfo(template_url); ?>/images/logo.png /> </div><!-- end of logo --> De este modo la imagen se mostrar correctamente sin importar en que dominio se encuentra instalado el theme. 30
Finalmente pasaremos a los mens que ahora podemos crear desde el panel de control de forma muy sencilla. Por defecto la funcin no viene activada, sino que debemos hacerlo desde el functions.php de nuestro theme con register_nav_menu (para registrar un nico men) o con register_nav_menus (mltiples mens). Necesitamos dos mens, uno para el #menu-top y otro para el #menu. As que vamos a registrarlos en el functions.php de la siguiente manera: register_nav_menus( array( menu-top => Menu superior, menu => Menu principal )); Guardamos y ahora en el Escritorio nos dirigimos a Apariencia y veremos que aparece la seccin Mens. Creamos dos mens, clickeando en el signo mas en el cuadro derecho. Uno se llamar Menu Top y el otro Menu Principal.
Luego definimos las ubicaciones de cada men. En nuestro caso el nombre coincide con la ubicacin. Guardamos al finalizar.
Y finalmente les colocamos algo de contenido. En nuestro caso, vamos a copiar la estructura que hicimos en el PSD inicial. Recuerden guardar cada men luego de colocados los links. Utilicen las cajas de la izquierda (debajo de Ubicacin del tema) para aadir pginas, categoras o links personalizados.
31
Para mostrar nuestros mens en la plantilla header.php necesitamos de la funcin wp_nav_ menu(). Recordemos la estructura de nuestros mens dentro del HTML generado en la clase 3. <ul id=menu-top> <li><a href=#>Link <li><a href=#>Link <li><a href=#>Link <li><a href=#>Link </ul> <ul id=menu> 1</a></li> 2</a></li> 3</a></li> 4</a></li>
Necesitamos reemplazar las listas desordenadas por nuestros mens recin creados. Comenzaremos por borrar nuestra lista con id #menu-top (desde el <ul> de apertura hasta su </ul> de cierre) y reemplazarla por la funcin wp_nav_menu() con los siguientes parmetros: <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menu-top>%3$s</ul>, theme_location => menu-top )); ?> Estos parmetros, y muchos otros que podemos utilizar, estn explicados en el codex el cual les recomendamos aprender a utilizar por ser la fuente principal de aprendizaje para cualquier desarrollador de themes y plugins. Container nos permite definir el tipo de contenedor en que se coloca al menu, permite elegir entre div, nav y false, el cual deshabilita la funcin (fue nuestra eleccin. Items_wrap nos permite indicarle al men las caractersticas que tendr la etiqueta que envuelva al men y Theme_location nos permite seleccionar el men que colocaremos en esta posicin (definido en el functions.php). Ahora haremos lo mismo con el men principal. <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menu>%3$s</ul>, theme_location=> menu, )); ?> Dentro de uno de los items del men, en nuestro caso de Blog, aadiremos algunas categoras o pginas hijas. 32
Para que funcione correctamente, utilizaremos un poco de jQuery, librera que podemos descargar desde jQuery.com. En el archivo functions.php, hacia el final, aadimos: /* Mi jQuery */ function my_init_method() { if (!is_admin()) { wp_deregister_script( jquery ); wp_register_script( jquery, /wp-content/themes/themetaller/scripts/ jquery.min.js); wp_enqueue_script( jquery ); } } add_action(init, my_init_method); Colocaremos el archivo jquery.min.js en nuestra carpeta scripts, y luego aadimos dentro de las etiquetas <head> las siguientes lneas: <script type=text/javascript> $(document).ready(function() { $(#menu ul).css({display: none}); $(#menu li).hover(function(){ $(this).find(ul:first).css({visibility: visible,display: none}). show(300); },function(){ $(this).find(ul:first).css({visibility: hidden}); }); }); </script> Y en nuestro CSS eliminamos las lneas antiguas que hacan referencia a #menu y las reemplazamos por estas: /* Menu desplegable */ #menu { float:left; width: 940px; margin: 0; padding:0px; height:35px; background-image:url(images/menu_bg.png); background-repeat: repeat-x; background-color: #7ec5ff; position:relative; z-index:300; list-style-type:none; } #menu ul { list-style-type:none; } #menu a { float:left; display:block; text-decoration:none; 33
color:#fff; font-weight:bold; padding: 10px 25px 10px 10px; border-right: 1px solid white; } #menu a:hover { color:#fff; background: #8ed6ff; } #menu li { float:left; position:relative; } #menu ul { position:absolute; display:none; width:160px; top: 35px; left: -10px; } #menu ul a { float:left; background: #7ec5ff; border: 1px solid white; border-top:none; } #menu li ul{ border-top: 1px solid white; } #menu li ul a { width:150px; height:auto; } #menu ul ul { top:auto; } #menu li ul ul { margin:0px 0 0 10px; } #menu li:hover ul ul, #menu li:hover ul ul ul, #menu li:hover ul ul ul ul { display:none; } #menu li:hover ul, #menu li li:hover ul, #menu li li li:hover ul, #menu li li li li:hover ul { display:block; } Ahora el nuevo men debera estar funcional. Clase 6
34
35
36
En el sitio oficial de Nivo-Slider promocionan la venta de un plugin para WordPress que es por dems fantstico. Tambin en el repositorio oficial vimos algn que otro plugin para insertar el slider en WordPress bastante bien logrado. Pero nosotros no tomaremos esos caminos, sino que nos ensuciaremos un poco para entender como se aplican estos fantsticos recursos a nuestro theme. Primero descargamos Nivo Slider desde su sitio (desde aqu, selecciona la primer opcin llamada jQuery Plugin) y copiaremos la carpeta themes, el archivo jquery.nivo.slider.pack.js y nivo-slider. css a nuestra carpeta /scripts/.
37
Y ahora linkeamos nivo-slider.css y el estilo themes/default.css desde nuestro header.php utilizando parte de la ruta hasta nuestro theme con bloginfo(), como vimos en clases pasadas. <link rel=stylesheet type=text/css href=<?php bloginfo(template_ url); ?>/scripts/nivo-slider.css media=screen /> <link rel=stylesheet href=<?php bloginfo(template_url); ?>/ scripts/themes/default/default.css type=text/css media=screen /> Y en el footer.php vamos a linkear el archivo JS, justo antes del cierre de la etiqueta </body>. Tambin vamos a dejar preparado el script indicndole que queremos que se active en el <div> con id #nivoslider. <script type=text/javascript src=<?php bloginfo(template_url); ?>/ scripts/jquery.nivo.slider.pack.js></script> <script type=text/javascript> $(window).load(function() { $(#nivoslider).nivoSlider(); }); </script> Antes de continuar vamos a establecer el tamao de las imgenes que utilizaremos con the_ post_thumbnail(). En functions.php ubicamos nuestra seccin destinada a las imgenes. add_theme_support( post-thumbnails ); add_image_size( homepage-thumb, 290, 130, true ); Y debajo aadimos un tamao mas, con el nombre de homepage-slider. add_image_size( homepage-slider, 920, 310, true ); Guardamos y subimos al servidor. Ahora al subir una imagen, WordPress recortar este tamao extra. Generamos la categora slider y subimos dentro tres o mas entradas con su respectivo ttulo y una imagen que mnimo sea de 920px de ancho por 310px alto, las cuales marcaremos
como destacadas. No es necesario que las insertemos en la entrada, con slo marcarlas como destacadas ya alcanza.
38 Procedemos a abrir nuestro archivo index.php en donde vamos a trabajar desarrollando las primeras lneas: <div id=nivoslider> <img src=http://lorempixum.com/g/920/310 /> </div><!-- end of nivoslider --> El slider trae un archivo demo.html para que podamos copiar la estructura que necesita para funcionar. Lo copiamos dentro de nuestro id #nivoslider y vamos dejando libre la seccin en donde colocaremos el cdigo PHP para generar una consulta que traiga nuestras imgenes recin subidas. <div id=nivoslider> <div class=slider-wrapper theme-default> <div class=ribbon></div> <div id=slider class=nivoSlider> <!-- aqui va nuestra query... --> </div> </div> </div><!-- end of nivoslider --> Necesitamos efectuar una consulta que nos traiga tres entradas de la categora slider, y cuando lo haga deber mostrarnos la miniatura del tamao que le especificamos (homepage-slider) en el functions.php usando add_image_size. Adems la imagen debe estar entre etiquetas <a></a> y el link debera dirigirnos a la entrada que se est mostrando. El cdigo finalmente quedar de la siguiente manera: <div id=slider> <div class=slider-wrapper theme-default> <div class=ribbon></div> <div id=nivoslider class=nivoSlider> <?php query_posts(category_name=slider&posts_per_page=3 ); while ( have_posts() ) : the_post(); ?> <a href=<?php echo get_permalink(); ?>><?php the_post_thumbnail( homepage-slider ); ?></a>
<?php endwhile; wp_reset_query(); ?> </div> </div> </div><!-- end of nivoslider -->
39 Finalmente podemos observar que el theme por defecto de Nivo Slider nos agrega debajo un control para navegar, lo eliminaremos abriendo su archivo de estilos ubicado dentro de nuestro theme/scripts/theme/default/default.css, buscamos la lnea 30 y le aadimos un display:none para ocultarlo. .theme-default .nivo-controlNav { display:none; position:absolute; left:50%; bottom:-42px; margin-left:-40px; } Esperamos que les haya resultado fcil de entender esta clase y les recomendamos que utilicen el complemento Firebug (para Firefox) para ejercitar con otros scripts similares a Nivo Slider para afianzar conocimientos. Clase 7
40
Los widgets pueden agregarse a cualquier plantilla de nuestra web y combinado con condicionales, los cuales vimos en la Clase 6, nos dan un sinfn de posibilidades para nuestro sitio. Para aadir un widget hace falta primero declararlo en nuestro functions.php, y luego insertarlo en la plantilla deseada. Vamos a generar un rea de widgets bsico para la sidebar. register_sidebar(array( name => Sidebar, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); El primer parmetro, name, asigna un nombre a nuestro widget que figurar luego en nuestro escritorio bajo Widgets para poder identiticarlo. before_widget y after_widget aade etiquetas al inicio y al final del mismo, en nuestro caso abrimos un div con class widget y lo cerramos. Finalmente repetimos la misma operacin pero para el ttulo con before_title y after_title. La funcin register_sidebar tambin admite los parmetros id (para colocar un ID al widget) y description (descripcin). Guardamos el archivo functions.php con estas lneas que acabamos de explicar y vemos si aparece el nuevo rea de widgets en Apariencia > Widgets. Hoy vamos a generar tres reas de widgets para utilizar en tres secciones diferentes: una sidebar en el inicio, otra para la plantilla de categoras y otra para una pgina. Las haremos idnticas entre si pero con diferentes nombres.
register_sidebar(array( name => Sidebar Home, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); register_sidebar(array( name => Sidebar Categoria, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); register_sidebar(array( name => Sidebar Pagina, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Hasta ahora venimos trabajando con una sola sidebar y vamos a explotar su uso todo lo que podamos. Abrimos el archivo y colocamos luego del listado de entradas que colocamos y antes del </div> de cierre del div #sidebar: <?php if ( !function_exists(dynamic_sidebar) || !dynamic_ sidebar(Sidebar Home) ) : endif; ?> Con eso slo estamos insertando los widgets que cargemos dentro de la seccin Sidebar Home, pero faltara indicarle que queremos que se cargue dichos widgets si y slo si estamos visualizando el home. Echamos mano a los Condicional Tags, como ya mencionamos. Entonces reemplazamos el cdigo por este nuevo. <?php if (is_home()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Home) ) : endif; } ?> Probamos aadir un campo de bsqueda o lo que sea para ver si se visualiza en el home y comprobamos que no se visualice en la vista por categoras o en una pgina.
41
Perfecto! Ahora generamos el cdigo con sus respectivos condicionales para el rea de widgets a mostrarse en el caso de estar en una categora (is_category) y en una pgina (is_page). <?php if (is_home()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Home) ) : endif; } elseif (is_category()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Categoria) ) : endif; } elseif (is_page()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Pagina) ) : endif; } ?> Guardamos, activamos diferentes widgets en cada rea y confirmamos que cada sidebar muestre lo que nosotros queremos. De acuerdo a lo que escribimos en nuestro functions.php el cdigo HTML de cada widget qued de la siguiente manera: <div class=widget> <h3>Busqueda</h3> <!-- contenido del widget seleccionado --> </div> Aplicamos un estilo diferente al widget para diferenciarlo de otros contenidos aadiendo un margen inferior, color de fondo, color de borde, borde redondeado y padding. .widget { margin-bottom: 20px; -webkit-border-radius: 5px; border-radius: 5px; background: #f4f4f4; border: 1px solid #ececec; padding: 5px; } 42
Doble sidebar
A nuestro template de pgina le vamos a agregar una segunda sidebar, slo por el gusto de ver como funciona el asunto. Abrimos el archivo page.php y observamos que en la anteltima lnea se utiliza una funcin para incluir la sidebar all. Duplicaremos dicha funcin pero esta vez insertando entre comillas simples el nombre de nuestra nueva sidebar, que en este caso se llamar dos. <?php get_sidebar(); get_sidebar(dos); ?>
Ahora necesitamos crear el archivo de dicha sidebar y para nombrarlo debemos tener en cuenta que primero colocamos sidebar-nombreelegido.php. El nombreelegido es lo que colocamos entre comillas simples cuando invocamos al archivo con get_sidebar. En nuestro caso el archivo deber llamarse sidebar-dos.php. Coloquemos dentro el siguiente contenido. <div id=sidebar> <?php if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar
Dos) ) : endif; ?> </div><!-- end of sidebar --> Generamos esta nueva rea de widgets en el functions.php. register_sidebar(array( name => Sidebar Dos, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Y para que haya un poco de coherencia en el diseo, vamos a modificar los ids de page.php para generar un CSS para este layout. <div id=wrapper-dos> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?> </div><!-- end of wrapper--> Aadimos en el CSS las propiedades para #wrapper-dos y #sidebar-dos. #wrapper-dos { width:392px; float:left; margin-top:20px; margin-left:20px; } #sidebar-dos{ width: 215px; margin-top:20px; margin-right:20px; float:right; } Y vamos a darle un poco de formato a las listas dentro de widget, ya que nuestros widgets las usan mucho. .widget li { list-style-type:none; padding: 0 0 0 10px; } 43
Nuestro ejercicio de hoy no ha quedado muy bonito que digamos, pero espero que la idea haya sido lo mas clara posible. Pueden agregar tantas reas de widgets como quieran y tantas sidebars como sean necesarias.
44
Clase 8
45
En el trabajo que ya tenemos hecho, nuestras dos sidebars tienen ancho fijo y flotan hacia la derecha (float:right). Es importante remarcar que las sidebars se ubican en el primer espacio libre encontrado en la direccin indicada desde float. Nosotros ubicamos el contenido a la izquierda, por eso queda disponible el espacio derecho para nuestros widgets. #sidebar { width: 293px; margin-top:20px; margin-right:20px; float:right; } #sidebar-dos{ width: 215px; margin-top:20px; margin-right:20px; float:right; } Al tener las sidebars los anchos que deseamos, los contenedores con class .widget no lo necesitan, ya que flotarn con el mismo ancho de su contenedor padre en direccin vertical. .widget { margin-bottom: 20px; -webkit-border-radius: 5px; border-radius: 5px; background: #f4f4f4;
border: 1px solid #ececec; padding: 5px; } Ahora lo que tenemos que lograr es insertar una tercera sidebar, debajo de todo el contenido pero arriba del footer, que ocupe todo el ancho de la pgina y que tenga tres widgets adentro.
46
La tercera sidebar se ubicar dentro de un archivo que llamaremos sidebar-horizontal.php y la llamada a la misma dentro de page.php se realiza de la siguiente forma: <?php get_sidebar(); get_sidebar(dos); get_sidebar(horizontal); ?> Dentro de sidebar-horizontal.php colocaremos dos reas con contenido de pruebas y en el tercer espacio repetiremos un rea de widgets (ustedes ya saben como agregar reas nuevas!). <div id=sidebarHorizontal> <div class=widget> <h3>Area uno</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <div class=widget> <h3>Area dos</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <?php
if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Categoria) ) : endif; ?> </div><!-- end of sidebarHorizontal --> Y finalmente el toque mgico para que tome la forma deseada: el cdigo CSS. Primero damos el ancho total que va a tener el rea contenedor de los widgets, los mrgenes (20px de cada lado excepto del izquierdo) y le indicamos que se ubique en el primer espacio libre a la izquierda que encontramos puesto que de lo contrario los elementos dentro de ubicarn fuera del rea deseada. #sidebarHorizontal{ width: 920px; margin:20px; float:left; } Luego procedemos a indicarle al elemento .widget que, slo cuando se encuentra dentro del rea #sidebarHorizontal, debe tener un determinado ancho fijo, ubicarse en el primer espacio libre a la izquierda (float:left;) y tener un margen a la izquierda de 20px. #sidebarHorizontal .widget { width:281px; float:left; margin-left:20px; } Y listo! Pueden experimentar colocar esta nueva sidebar debajo del header, en la plantilla index. php o en donde se les ocurra. Clase 8 Anexo 47
48
Area de widgets
Hasta ahora en el div #footer tenemos lo siguiente: <div id=footer> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer -->
Vamos a modificarlo para que dentro haya tres reas de widgets. En la primera colocaremos cualquier contenido a modo de pruebas, en la segunda colocaremos un rea de widgets que crearemos para esta seccin y en la tercera dejaremos los conos sociales. Primero colocamos el cdigo para crear nuestro rea de widgets en el functions.php. register_sidebar(array( name => Widget Footer, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Y ahora todo el contenido del #footer. <div id=footer> <div class=widget> <h3>Footer</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <?php if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Widget Footer) ) : endif; ?> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer --> Las rutas a los conos sociales deben arreglarse para que funcionen cuando el theme est instalado en cualquier sitio web, por lo que necesitamos usar la funcin bloginfo() para lograr que stas sean dinmicas. <ul class=social> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ skype.png /></a></li> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/facebook.png /></a></li> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ twitter.png /></a></li>
49
<li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ rss.png /></a></li> </ul> El resultado es un rea de widgets que tiene fondo gris, como los que agregamos anteriormente en las sidebars.
Sera bueno que los widgets del footer tengan su propio estilo, por lo que aadimos un nuevo estilo para todo .widget que se encuentre dentro de #footer de la siguiente manera: #footer .widget { width:281px; float:left; margin-left:20px; background:none; border:none; padding:0; } #footer .widget h3{ color: #7b7b7b; border-bottom: 2px solid #fff; padding-bottom: 5px; margin-bottom:5px; width:281px; float:left; margin-left:20px; text-shadow: 0px 0px 2px #bdbdbd; filter: dropshadow(color=#bdbdbd, offx=0, offy=0); } #footer .widget p, #footer .widget a, #footer .widget li{ color: #7b7b7b; text-decoration:none; } #footer .widget a:hover { text-decoration:underline; } Al ttulo h3 del widget notarn que le agregu text-shadow. Pueden agregar toda clase de efectos geniales con CSS3 usando este generador de cdigo css3generator.com. Quienes tengan navegadores actualizados a las ltimas versiones podrn ver los nuevos efectos, y quienes tengan navegadores mas antiguos vern simplemente el texto sin el efecto, completamente funcional. Los conos sociales quedaban en dos lneas porque el contenedor resultaba muy angosto, por lo
50
que aumentamos el width y ya caben perfectamente. ul.social { list-style-type:none; float:right; width:190px; padding:0px; margin:0px; }
51
Men adicional
No resulta mala idea aadir un men al pie de pgina. Ayuda a que el sitio resulte mas fcil de navegar. Por eso vamos a repetir nuestro Men Principal debajo pero definitivamente debemos modificar el estilo del mismo. Vamos a utilizar el id #menuFooter para la etiqueta <ul>, as que modificamos y pegamos el siguiente cdigo antes del cierre del div #footer. <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menuFooter>%3$s</ul>, theme_location=> menu, )); ?> Para este segundo men no vamos a colocar los submens desplegables debido a que para que funcione correctamente necesitamos pasar un valor fijo para un alto que no conocemos, por lo que ahora evitaremos entrar en un script para calcular cuanto debe trasladarse el submen y que se abra como corresponde. Hecha esta aclaracin, le damos estilo a la nueva clase #menuFooter. #menuFooter { -webkit-box-shadow: inset 0px 3px 1px 0px #ccc; box-shadow: inset 0px 3px 1px 0px #ccc; width: 960px; background: #e1e1e1; border:none; margin: 10px 0 0 0; -webkit-border-radius: 0px 0px 10px 10px; border-radius: 0px 0px 10px 10px; list-style-type:none; float:left; height:35px; } #menuFooter a {
float:left; display:block; text-decoration:none; color:#666; font-weight:bold; margin-left:10px; padding: 10px; border-right: none; background: none; } #menuFooter a:hover { color:#666; background: #f4f4f4; } #menuFooter ul { background:none; list-style-type:none; } #menuFooter li ul { display:none; } #menuFooter ul a { float:left; } Y modificamos el padding de #footer. #footer { float:left; background: #e6e6e6; width: 960px; padding: 20px 0 0 0; }
52
Volver arriba
El usuario hizo scroll luego de revisar mucho texto y lleg hasta nuestro footer, si necesita volver al inicio de la pgina para usar el men desplegable completo o el men top, nosotros podemos hacerle la tarea mas fcil si le ofrecemos al pi un link que diga volver arriba o similar. En nuestro caso, deseamos colocar el link en la misma barra en donde est el men del footer, slo que alineado a la derecha para separarlo de los items del men. Para eso lo agregamos como un elemento mas de la lista #menuFooter pero con una clase diferente. Modificamos las lneas en donde insertamos el men de la siguiente manera:
<?php wp_nav_menu( array( container => false, items_wrap => <ul id=menuFooter>%3$s<li class=toTop><a href=#top>Volver arriba</a></li></ul>, theme_location=> menu, )); ?> De este modo al final de la lista que conforma el men, metemos el elemento con clase .toTop y dentro un link con href #top. Aprovechando que estamos en la plantilla footer.php, aadimos las siguientes lneas de jQuery luego de las que ya figuran de nivoslider entre etiquetas <script>. $(document).ready(function() { $(a[href=#top]).click(function(){ $(html, body).animate({scrollTop:0}, slow); return false; }); }); Y finalmente necesitamos indicar en nuestro CSS que el <li> con class .toTop debe flotar a la derecha. .toTop { float:right; }
53
Clase 9
Es la plantilla para la vista individual de una entrada y su estructura bsica es como muestra la siguiente imagen.
54
Pasamos en limpio lo que vamos a hacer: llamamos al header, en el rea de contenidos usamos las funciones the_title (el ttulo) y the_content (el contenido), luego llamamos a la sidebar y finalmente al footer. Para que the_title y the_content puedan traernos contenido desde la base de datos correspondiente al ID de la entrada que estamos consultando, necesitamos colocarlos dentro del bucle. Esto se traduce en el siguiente contenido (que es el que ya tenemos desde la clase 4). <?php get_header(); ?> <div id=wrapper> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=dos-tercios listado> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of dos-tercios -->
<?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); ?> <?php get_footer(); ?>
55
La funcin the_content nos trae todo el contenido publicado en una entrada: su texto, imgenes, galeras, listas, etc. Y para aprovechar la oportunidad aqu es en donde necesitamos definir la alineacin de las imgenes que, tal como el editor de WordPress lo seala al subir una imagen, la posicin de las mismas puede ser centrada respecto del texto, a la izquierda del texto, a la derecha del texto o sin bordear por texto. Esto se traduce en el siguiente CSS. /* alignments */ .center {text-align: center;} img.center, img[align=center] {display: block;margin-left: auto;margin-right: auto;} .alignleft {float: left;} img.alignleft, img[align=left] {float:left;margin: 2px 10px 5px 0px;} .alignright {float: right;} img.alignright, img[align=right] {float:right;margin: 2px 0px 5px 10px;} .clear {clear:both;} hr.clear {clear:both;visibility: hidden;margin: 0px;padding: 0px;height:0px;} Generalmente en la vista de entrada tambin se suele colocar informacin como la fecha de publicacin, en qu categora se encuentra, etiquetas, cantidad de comentarios y el autor. Y para esta seccin nos vamos a ayudar con algunos conos para que la seccin luzca lo mejor posible. En este caso nos decidimos por este set de conos genial llamado gcons. Vamos a construir debajo del cierre del contenedor .dos-tercios, un contenedor con class .metabox en donde colocaremos todas las funciones dentro de etiquetas span para luego insertarles algn cono. Utilizaremos las siguientes funciones: the_category, the_time, the_author_posts_link, comments_popup_link y the_tags (cada funcin tiene su link al codex, aprendan a consultarlo). <div class=metabox> <span class=time meta>Publicado el <?php the_time(j) ?> de <?php the_time(F, Y) ?> | </span><span class=author meta>Por <?php the_author_posts_link(); ?> | </span>
<span class=comments meta><?php comments_popup_link(Sin Comentarios, 1 Comentario, % Comentarios); ?> | </span><span class=category meta>En la categoría <?php the_category( ); ?> | </span> <span class=tags meta>Con las siguientes etiquetas <?php the_tags(); ?></span> </div> El resultado, sin ningn tipo de estilo aplicado:
Los conos gcons tienen un set en color azul. Tomamos algunos para utilizar en nuestros spans y los llevamos a tamao 16px x 16px con Photoshop o algn programa de edicin. Al .metabox le colocamos un color azul oscuro, tipografa de color blanco, bordes redondeados y un padding para que no queden pegados al borde los elementos que ubicamos dentro. .metabox { padding: 10px; background: #2d435a; color:white; -webkit-border-radius: 10px; border-radius: 10px; margin: 10px 0; display:block; float:left; } La clase .meta se repetir luego dentro de cada span, los cuales tienen dos clases (ej. class=category meta suma dos clases, .category y .meta), por eso colocamos las propiedades background-repeat y background-position, que modificarn el cono que insertaremos luego en la otra clase de cada span. Colocamos tambin un padding-left para que el texto deje un espacio para que se vea el cono. .meta { background-repeat: no-repeat; padding-left:20px; margin-bottom: 4px; float:left; height:16px; background-position: center left; } Y colocamos el link a cada cono. .time { background-image: url(images/calendar.png); } .author{
56
57
os comentarios
Ahora podemos insertar el llamado a la plantilla de comentarios. Bastar con colocar la siguiente funcin dentro del bucle (o sea, antes del endwhile). <?php comments_template(); ?> Y automticamente veremos el siguiente contenido.
Si nos fijamos en el cdigo, el HTML generado es el siguiente: <ol class="commentlist"> <li class="comment byuser comment-author-admin bypostauthor even thread-even depth-1" id="comment-31"> <div id="div-comment-31" class="comment-body"> <div class="comment-author vcard"> <img alt='' src='http://0.gravatar.com/avatar/a1b6b0dc561b8146fba62 24e6c71a1be?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad5165 03a11cd5ca435acc9bb6523536%3Fs%3D32&r=G' class='avatar avatar-32 photo' height='32' width='32' /> <cite class="fn">admin</cite> <span class="says">dice:</span> </div> <div class="comment-meta commentmetadata"><a href="http:// localhost/?p=694#comment-31"> 19 mayo, 2012 a las 23:56</a> <a class="comment-edit-link" href="http://localhost/wp-admin/comment.php?action=editcomment&c=31" title="Editar comentario">(Editar)</a> </div> <p>Hola! Este es un comentario <img src='http://localhost/wp-includes/ images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p> <div class="reply"> <a class='comment-reply-link' href='/?p=694&replytocom=31#respond' onclick='return addComment.moveForm("div-comment-31", "31", "respond", "694")'>Responder</a> </div> </div> </li> </ol> Claro que podemos simplificar un poco si sabemos a lo que apuntamos y podemos ignorar algunas clases muy especficas como .bypostauthor en nuestra etiqueta <li>. La estructura bsica que vamos a tomar es la siguiente: <ol class="commentlist"> <li> <div class="comment-author"> <img alt='' src='/link/a/gravatar/' height='32' width='32' /> <cite class="fn">admin</cite> <span class="says">dice:</span> </div> <div class="comment-meta"><a href="http://localhost/?p=694#comment-31"> 19 mayo, 2012 a las 23:56</a> <a href="link/a/editar" title="Editar comentario">(Editar)</a> </div> <p>Hola! Este es un comentario</p> <div class="reply"> <a class='comment-reply-link' href='/link/para/responder'>Responder</a> </div> </li> </ol> Qu sucedi? Simplificamos. Eliminamos clases que no necesitabamos declarar as como una etiqueta div que contenia a todo el comentario y que resultaba innecesario para un estilo bsico.
58
Ahora colocamos las clases y etiquetas correspondientes en el CSS. Al inicio de mi nueva seccin coloco entre /* y */ un comentario para utilizar de referencia a futuro. Lo nico que agregu que no estaba en el HTML es la clase .comment-awaiting-moderation, que aparece cuando un mensaje est pendiente de moderacin, tal como lo dice su nombre. /* Comments! */ ol.commentlist {} ol.commentlist li {} .comment-author {} .comment-author img {} .fn {} .says {} .comment-meta {} .comment-awaiting-moderation {} .comment-meta a {} ol.commentlist li p {} .reply a {} Es importante destacar que vamos a trabajar con comentarios anidados (o sea que puedo responder al comentario de alguien y mi comentario aparecer debajo del mismo) y del modo en que lo estamos maquetando aparecer un comentario dentro del otro. As que lo mejor es utilizar anchos que no sean fijos, sino relativos (o sea que cubran determinado porcentaje del contenedor padre). /* Comments! */ ol.commentlist { list-style-type: none; width:600px; } ol.commentlist li { width:95%; position:relative; overflow:hidden; background: #e1e1e1; -webkit-border-radius: 10px; border-radius: 10px; border: 1px solid #ccc; padding:10px; margin: 10px 0; } .comment-author { width: 60%; float:left; height:40px; } .comment-author img { float:left; border: 1px solid #ccc; margin: 2px; } .fn { color: #2d435a; font-weight:bold;
59
font-size:14px; } .says {} .comment-meta { width: 40%; float:left; height:40px; text-align:right; overflow:hidden; } .comment-awaiting-moderation { position:absolute; left:0px; top:10px; width:100%; margin-right:10px; text-align:right; } .comment-meta a {} ol.commentlist li p {} .reply a { padding: 5px 10px; background: #2d435a; -webkit-border-radius: 10px; border-radius: 10px; border: 1px solid #ccc; color:white; text-decoration:none; margin: 5px 0; } El resultado ser:
60
Claro que no se diferencian bien las respuestas del original. Pero como vimos antes el comentario tiene una clase de acuerdo a su nivel dentro de los comentarios anidados, basta con leer el cdigo HTML generado por esta pgina: <li class="comment byuser comment-author-admin bypostauthor odd alt depth-2 parent" id="comment-34"> Existen, entonces, varios niveles de profundidad (depth) en nuestros comentarios. Eliminemos el background de ol.comments li y colocamos las siguientes clases con diferentes tonos de gris por fondo: .depth-1 {background: #e1e1e1;} .depth-2 {background: #f1f1f1;} .depth-3 {background: #f9f9f9;} Y obtendremos: 61
Todo esto sin necesidad de generar en ningn momento la plantilla comentarios, utilizando slo el cdigo por defecto que WordPress genera. Para el caso de que queramos modificar drsticamente nuestra seccin de comentarios podemos generar un archivo comments.php o bien podemos hacerlo va hooks desde el functions.php. En este taller no vamos a ir mas all, ya que en SummArg constantemente sacamos notas con trucos para personalizar algunas plantillas de modo original. Pero a cambio les vamos a dejar de ejemplo el cdigo que estamos usando en nuestra plantilla para mostrar los comentarios por si les sirve de referencia. En nuestro functions.php colocamos la siguiente funcin para mostrar los comentarios con cdigo personalizado. <?php function mytheme_comment($comment, $args, $depth) { $GLOBALS['comment'] = $comment; ?> <li class="comment"> <div class="comment-top"> <?php echo get_avatar($comment,$size='36',$default='<path_to_url>' ); ?> <?php printf(__('<div class="fn">%s</div>'), get_comment_author_link()) ?> <?php if ($comment->comment_approved == '0') : ?> <em><?php _e('Tu comentario espera moderación.') ?></em> <br /> <?php endif; ?>
<div class="comment-meta commentmetadata"> <br /> <a href="<?php echo htmlspecialchars( get_comment_link( $comment>comment_ID ) ) ?>"> <?php comment_date('j-n-y'); ?> </a><?php edit_comment_link(__('(Edit)'),' ','') ?></div> </div><!-- end of comment-top--> <div class="comment-text"> <?php comment_text() ?> <div class="reply"> <?php comment_reply_link(array_merge( $args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?> </div> </div><!-- end of comment-text --> </li> <?php } Y el CSS .commentlist li.comment { width: 600px; display:block; margin: 5px auto; float:left; } .infos { width:565px; float:left; display:block; border-top: 1px double #ccc; padding: 5px; margin: 5px 0; font:normal 12px "tahoma", "arial", Sans-serif; color: #999; } .comment-top { background-color: #405e76; color: #fff; width:150px; float:left; border: 2px solid #405e76; padding: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 0px; -moz-border-radius-bottomright: 0px; -moz-border-radius-bottomleft: 5px; -webkit-border-radius: 5px 0px 0px 5px; border-radius: 5px 0px 0px 5px; } .comment-top a { color: #fff; }
62
.fn a, .fn{ font-size:12px; font-weight:bold; color: #fff; float:right; text-decoration: none; } .comment-text { background: url(images/comments-arrow.png) no-repeat; background-position: left top; border: 2px solid #405e76; background-color: #f1f1f1; width:407px; float:right; padding: 5px 5px 5px 20px; -moz-border-radius-topleft: 0px; -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 0px; -webkit-border-radius: 0px 5px 5px 0px; border-radius: 0px 5px 5px 0px; } La nica imagen que agregamos es comments-arrow.png, que no es mas que el tringulo que est al lado del cuadro azul con el avatar y el nombre del comentador. El resultado es el siguiente:
63
Esperamos que la clase de hoy les haya resultado esclarecedora. Como siempre, les dejamos el demo funcionando y los archivos de la clase para descargar. Clase 10
64
Esa pgina es nuestra plantilla por defecto segn la ltima actualizacin al theme. Por eso vamos a aprender a agregar pginas personalizadas y veamos que opciones tenemos para ello. Por ltimo, vale la pena destacar que las plantillas de pginas soportan comentarios y si bien en esta clase no vamos a colocarlos, pueden seguir los mismos pasos que realizamos en la clase 10 para agregarlos.
Pginas personalizadas
Por un lado podemos optar por colocar desde el nombre del archivo la directiva para que se aplique la plantilla a una determinada pgina ya sea por su ID o por su slug.
page-{id}.php page-{slug}.php
De este modo, por ejemplo, si colocamos una plantilla con nombre page-10.php, WordPress intentar aplicar dicha plantilla automticamente a la pgina con ID 10. Lo negativo de este mtodo es que no permite aplicar una plantilla en particular a varias pginas de forma prctica, pero suele resultar bastante prctico para aplicar un estilo determinado a una nica pgina. Para crear una plantilla que luego se pueda aplicar a diferentes pginas segn le indiquemos desde el editor, primero debemos dar al archivo un nombre descriptivo. Nosotros vamos a crear una plantilla de pgina en donde el contenido abarcar 3/4 del layout y el restante lo usaremos para una sidebar. Tambin removeremos la sidebar horizontal, siendo nuestro objetivo lograr la siguiente estructura.
65
Creamos un archivo llamado page-unasidebar.php. No es obligatorio colocar el prefijo page- en el nombre del archivo, simplemente lo hacemos para ser lo mas descriptivos posibles. Para evitar conflictos con el nombre, recuerden revisar el cuadro de Template Hierarchy y vern cuales son los nombres que WordPress se reserva para plantillas en particular. Colocamos en su encabezado el siguiente cdigo comentado dentro de llaves de php. <?php /* Template Name: Una Sidebar */ ?>
La mayora del cdigo ya lo tenemos, podemos copiar el contenido anterior de page.php, eliminar las dos sidebars extras y modificar el ID del contenedor del texto de #wrapper-dos a #wrapper que ya tiene las medidas necesarias. <?php get_header(); ?> <div id=wrapper> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?>
66
Generar una plantilla por si misma no se refleja en ningn cambio en nuestro WordPress hasta que no asignamos la plantilla a una pgina existente. Para esto, nos dirigimos a nuestro panel de control y a una pgina existente le aadimos la plantilla. Guardamos la pgina al finalizar el cambio.
Pginas y subpginas
Como mencionamos al principio, las pginas pueden tener subpginas para ayudarnos a organizar mejor nuestra informacin. Para generar una subpgina, desde nuestro editor asignamos una pgina superior a nuestra pgina actual.
Guardamos y vamos a la seccin de Pginas en el escritorio. All observaremos como se refleja el sistema de jerarquas de pgina segn la pgina superior asignada en cada caso.
Por ltimo, en la seccin de Atributos de Pgina, cuando estamos en el editor de la pgina, podemos ver un casillero llamado Orden. El mismo soporta valores numricos para asignar un orden a las pginas que tengan la misma jerarqua. Ya que las pginas no se destacan por su orden cronolgico, como las entradas, es muy til poder asignar mediante este mtodo el orden en el que deseamos que se muestren nuestras pginas. 67
La ubicacin mas utilizada para mostrar subpginas generalmente es en algn sitio de la sidebar, por lo que vamos a colocar un condicional para nuestra sidebar.php. En el mismo necesitamos comprobar si existen hijos de la pgina actual, caso contrario no debe mostrarse nada. Si el condicional resulta afirmativo (es una pgina y no una entrada o una categora, y adems resulta tener hijos), entonces se mostrar el ttulo Subpginas y desplegamos debajo el resultado de $children, en donde usamos la funcin wp_list_pages. El cdigo debe ir luego de abrir el div #sidebar. <?php $children = wp_list_pages('title_li=&child_of='.$post->ID.'&echo=0'); if ($children) { ?> <div class="widget"> <h3>Subpáginas</h3> <ul class="subpages"> <?php echo $children; ?> </ul> </div> <?php } ?> Agregaremos un poco de estilo para que se muestre un poco mas prolijo. ul.subpages { margin:0; margin-left:10px; } .subpages li { list-style-type: circle; margin: 4px 0 4px 10px; text-indent:-5px; border-top: 1px solid #f9f9f9; padding: 2px 0 0 5px;; } ul.subpages li ul {
margin:0; } .subpages li a { text-decoration:none; } Realizamos un cambio en la plantilla de estilos en donde eliminamos los elementos #sidebar ul y #sidebar li, y creamos la clase .sidebarNews en nuestra lista de noticias en la Sidebar. <h3>Ultimas noticias</h3> <ul class="sidebarNews"> <?php query_posts('category_name=Blog&posts_per_page=4' ); while ( have_posts() ) : the_post(); ?> <li><a href="<?php echo get_permalink(); ?>"><?php the_title(); ?></a> <br /> Por <?php the_author(); ?></li> <?php endwhile; wp_reset_query(); ?> </ul> La nueva clase en el CSS. ul.sidebarNews { list-style-type:none; margin-bottom:20px; } ul.sidebarNews li { padding: 5px 10px; border-bottom: 1px solid #7b7b7b; color: #7b7b7b; } ul.sidebarNews li a{ text-decoration:none; color: #7b7b7b; } De ese modo podemos dar estilos diferentes a los listados que aparezcan dentro de la sidebar. Aadimos varios elementos hijos y nietos a la pgina con la que iniciamos las pruebas de esta clase y obtuvimos el siguiente resultado.
68
Nada nos impide que usemos las plantillas de pgina para colocar consultas con query_posts, tal como vimos en la clase 5, y en esta oportunidad vamos a ver como crear una pgina en donde mostrar una categora de productos de un modo diferente al que usaremos luego en las plantillas
de categora. Primero generamos una categora llamada Productos. Antes de subir contenidos a dicha categora, vamos a establecer en el functions.php el tamao de la miniatura, para no tener que regenerarlas luego. add_image_size( producto, 195,195,true ); Subimos los artculos que necesitemos para ir probando nuestro theme y recordamos marcar como destacadas las imgenes que asignemos. Creamos un archivo llamado page-misproductos. php y en su interior colocaremos el cdigo que explicaremos por partes. Primero el encabezado del template. <?php /* Template Name: Mis productos */ get_header(); ?> Abrimos un contenedor con id #wrapper-full y colocamos el primer bucle, destinado a buscar el contenido de la pgina y tomar de l el ttulo y el contenido. Cerramos el bucle. <div id=wrapper-full> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h1><?php the_title(); ?></h1> <div class=descripcion><?php the_content(); ?></div> <?php endwhile; endif; Luego arrancamos con el bucle para mostrar los productos, en donde indicamos que queremos mostrar de a 8 productos y aadimos la variable de paginacin (leer ms sobre paginacin y query_posts aqu). El producto estar en un contenedor con la clase .producto y mostramos primero la imagen y luego el nombre del producto con su link. query_posts( array ( category_name => productos, showposts => 8, paged => get_query_var(paged) ) ); if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=producto> <?php the_post_thumbnail(producto); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> </div> <?php endwhile; endif; ?> Finalmente colocamos los links de navegacin, cerramos el contenedor y llamamos al footer. <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div>
69
</div><!-- end of wrapper-full --> <?php get_footer(); ?> Ahora vamos a darle un poco de estilo a la pgina. Primero definimos las propiedades que va a tener el contenedor de la pgina, que ocupa todo el ancho, el ttulo y la descripcin. #wrapper-full { width:920px; float:left; margin: 20px; } #wrapper-full h1 { text-align:center; padding: 20px 0 5px 0; border-bottom: 3px solid #7ec5ff; font-size:32px; } .descripcion p{ text-align:center; font-size:13px; line-height:18px; color: #7ec5ff; font-weight:bold; } .descripcion { margin: 0 0 10px 0; } Ahora daremos forma a los contenedores de producto aadiendo color de fondo, de bordes, sombras y un tamao especfico para el ttulo. .producto { float:left; width: 205px; height:225px; padding: 5px; margin: 6px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid /*#2d435a; #7ec5ff;*/ #e9e9e9; background-color: #f4f4f4; -webkit-box-shadow: 0px 0px 1px 1px #999; box-shadow: 0px 0px 1px 1px #999; } .producto img { border: 1px solid #b4b4b4; -webkit-border-radius: 5px; border-radius: 5px; } .producto h2 { font-size:14px; text-align:center; line-height:22px;
70
font-weight:bold; } .producto h2 a { color: #999; } Finalmente damos estilo a la paginacin para que aparezca siempre abajo. .navigation { width: 920px; margin:20px 0; height:20px; display:block; float:left; } El resultado ser el siguiente. 71
Encontrarn el ejercicio en nuestro demo online. Pueden descargar el theme completo desde aqu: themeTaller11
Clase 12: archive.php y plantillas por categora, fecha, autor, taxonoma, etiqueta.
Antes de arrancar con las plantillas de archivo en general, vamos a actualizar un poco el header. php de nuestro theme en funcin de adaptarlo a los requerimientos actuales con Facebook. Antes que nada, incluyamos un favicon, porque sino el theme se ve aburrido en nuestros navegadores. <link rel="shortcut icon" type="image/x-icon" href="<?php bloginfo('template_directory'); ?>/images/favicon.ico">
72
Acto seguido, vayamos colocando algunas etiquetas para que Facebook tome la informacin como nosotros queremos en cuanto al home, los interiores los dejaremos para que naturalmente tome los datos del cuerpo del contenido. <?php if (is_home() || is_front_page()) { ?> <meta property='og:locale' content='es_ES'/> <meta property='og:type' content='website'/> <meta property='og:title' content='themeTaller'/> <meta property='og:description' content='Un theme WordPress para aprender'/> <meta property='og:url' content='http://www.summarg.com/demos/themetaller/'/> <meta property='og:site_name' content='themeTaller'/> <meta property="og:image" content="<?php bloginfo('template_directory'); ?>/images/avatar.png"> <?php } ?> Por avatar.png debemos subir una imagen de mas de 350px x 350px. Para ver la informacin que Facebook toma de nuestras urls podemos usar la herramienta llamada Depurador.
73
Listo! Ahora si, vamos a lo nuestro. Como ya vimos en la clase 4, la plantilla archive.php agrupa todos los listados de posts por: categoras, autor, fechas, etiquetas, custom post types archive y custom taxonomies. Esto significa que si solicitamos un listado de entradas de la categora con id 4 (miblog.com/?cat=4), WordPress primero buscar la plantilla para esa categora especfica, que sera category-4.php. Al no encontrarla, busca la plantillas de categoras en general, category.php. Si no existe, utiliza archive.php, si a su vez tampoco existe entonces buscar index.php. Lo mismo sucede para etiquetas, autor, fecha, y las dems. Existe una jerarqua que WordPress recorre en un orden especfico. Tomemos el caso de dos categoras de nuestra instalacin de prueba, la categora productos (id 111) y la categora blog (id 45). Podramos crearles una plantilla para cada uno generando el archivo category-productos.php y category-blog.php, respetando la primera forma que busca WordPress que es category-$slug.php. O bien podramos llamarlos caregory-111.php y el category-45. php, con el formato category-$id.php. Pero vamos a usar archive.php con Conditional Tags, slo por el placer de usar tantos condicionales. En un sitio normal con muchas visitas no nos conviene tener un archivo con tantos condicionales como lo vamos a crear ahora, y resulta mas efectivo crear tantos archivos como sea necesario. Pero estamos aprendiendo y esto es un gran experimento. Esto es lo que tenemos hasta ahora en nuestro archive.php: <?php get_header(); ?> <div id="wrapper"> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time('F jS, Y') ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?>
</div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> Vamos a tener dos objetivos simples. El primero es que cuando se muestre la categora de productos se vea tal como est en la pgina de productos, as que tomaremos gran parte del cdigo que est en la pgina personalizada que construimos la clase anterior. El header y el footer se mantienen, en todas las plantillas necesitamos de estos dos, as que vamos a manejarnos en el medio de ese espacio. Colocamos debajo de la llamada al header nuestro condicional con el correspondiente else. Cabe mencionar que necesitamos colocar un exit a cada if, ya que cuando se cumpla la condicin dada (ej. estamos en la categora 111) se va a mostrar ese cdigo y adicionalmente tambin se va a mostrar el que coloquemos dentro del else, ya que ambas condiciones se cumplen de algn modo. El exit corta o escapa a todo el conjunto una vez que una se cumple. <?php if (is_category(111)) { ?> <div id="wrapper-full"> <h1>Productos</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="producto"> <?php the_post_thumbnail('producto'); ?> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> </div> <?php endwhile; endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper-full --> <?php exit; } else { ?> Antes de la llamada al footer hay que colocar otra llave cerrando todo. <?php get_sidebar(); ?> <?php } ?> <?php get_footer(); ?> Cabe destacar que lo que tendramos que lograr es que no haya tantas aperturas y cierres de php, por lo que la lnea anterior bien la podramos convertir en esto: <?php get_sidebar(); } get_footer(); ?> Pero como dijimos antes, estamos aprendiendo y la intencin es que les resulte bien claro lo que vamos haciendo. Lo importante es que tengan presente que lo que ven ac es un pantallazo para entender como funciona el tema y de ah progresar. Ahora si vamos a nuestra categora de productos, podemos ver el listado de productos de la categora productos y de sus subcategoras, en el formato que escogimos. Podemos ver el resultado en el demo online. Pasemos a darle un formato diferente a las entradas en la categora blog para que quede del siguiente modo, sin barra lateral:
74
En la lnea superior a la del else, colocamos la nueva condicin y le daremos un formato distinto a nuestros contenedores. <?php } if (is_category(45)) { ?> <div id=wrapper-full> <h1>Blog</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=blog> <a href=<?php the_permalink() ?> title=<?php the_title(); ?>> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail(thumb); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div> </div><!-- end of wrapper-full --> <?php exit; } else { ?> Y en el CSS definimos este nuevo contenedor para que tenga su propio estilo. .blog { width: 435px; height: 210px; float:left; margin: 5px; padding:5px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .blog a { text-decoration:none;
75
color: #333; } .blog img { float:left; margin: 5px 10px 0 0; border: 2px solid #e9e9e9; } .blog h2 { margin-top:5px; font-size:20px; line-height:24px; } .blog a h2 { text-decoration:none; color: #333; } .blog:hover { background-color: #ccc; } Podemos ver el resultado del ejercicio en esta ubicacin. Ahora hagamos una plantilla para mostrarse cuando el usuario solicite las entradas de un autor. Al igual que en el caso de las categoras, cuando se solicite el listado por autor, WordPress dar prioridad a la bsqueda de plantillas de la siguiente manera: 1. author-$nicename.php: En donde $nicename es el nombre de usuario del autor solicitado. 2. author-$id.php: En donde $id es el id de usuario del autor. 3. author.php: Plantilla genrica para todos los autores 4. archive.php: El nuestro! 5. index.php Vamos a usar nuevamente un condicional tag y a pensar en cmo queremos mostrar la pgina. Nuestro objetivo ser colocar arriba del listado (fuera del loop) la informacin que podamos sobre el autor solicitado. Y aqu tenemos un problema puesto que todas las funciones con get_the_author() y similares funcionan dentro del loop. Pero una de las maravillas de WordPress es su documentacin y la enorme comunidad que escribe sobre estos temas, as que le echamos una leda al snippet que public Kevin Muldon en WPHub y tomamos lo que necesitamos para construir nuestro recuadro de autor.
76
Luego del recuadro de autor (identificado con la class authorInfo) procedemos a colocar el bucle como siempre, con unos contenedores que esta vez contemplarn el espacio que necesita la sidebar para mostrarse. El cdigo PHP quedar de la siguiente manera: <?php } if (is_author()) { ?> <div id=wrapperUnTercio> <?php if(isset($_GET[author_name])) : $curauth = get_userdatabylogin($author_name); else : $curauth = get_userdata(intval($author)); endif; ?> <h1>Artículos escritos por <?php echo $curauth->nickname; ?></ h1> <div class=authorInfo> <h2><?php echo $curauth->nickname; ?></h2> <p><strong>Sitio web</strong>: <a href=<?php echo $curauth->user_url; ?>><?php echo $curauth->user_url; ?></a></p> <p><strong>Sobre <?php echo $curauth->nickname; ?></strong>: <?php echo $curauth->user_description; ?></p> </div> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=unTercio> <a href=<?php the_permalink() ?> title=<?php the_title(); ?>> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail(thumb); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div> </div><!-- end of wrapper --> <?php get_sidebar(); ?> <?php exit; } else { ?> El CSS para esta nueva seccin quedara de la siguiente manera: .authorInfo { width: 586px; padding: 10px; float:left; margin: 0 0 20px 20px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .authorInfo h2 { color: #7ec5ff; } .unTercio { width: 285px;
77
float:left; margin: 0 0 20px 20px; border-bottom:1px solid #e9e9e9; } .unTercio a { text-decoration:none; color: #333; } .unTercio img { float:left; margin: 5px 10px 0 0; border: 2px solid #e9e9e9; } .unTercio h2 { margin-top:5px; font-size:20px; line-height:24px; } .unTercio a h2 { text-decoration:none; color: #333; } .unTercio:hover { background-color: #f4f4f4; } Y el resultado puede verse en el siguiente ejemplo con un autor de nuestro demo. Finalmente vamos a construir una plantilla para tags (etiquetas) que sea prcticamente igual a la de autor con la diferencia de que queremos que se muestre la nube de etiquetas arriba de todo en un estilo que se adapte a nuestro trabajo.
78
El cdigo PHP deber utilizar el tag single_tag_title() para llamar al nombre del tag y utilizarlo en nuestro ttulo, luego colocamos la funcin wp_tag_cloud() sin parmetros para mostrar la nube de tags y el bucle sigue igual que en el de autor.
<?php } if (is_tag()) { ?> <div id="wrapperUnTercio"> <h1>Listado de artículos con la etiqueta <?php single_tag_title(); ?></h1> <div class="tagCloud"> <?php wp_tag_cloud(); ?> </div> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="unTercio"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail('thumb'); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper --> <?php get_sidebar(); ?> <?php exit; } else { ?> Para el CSS unicamente aadimos lo siguiente: .authorInfo, .tagCloud { width: 586px; padding: 10px; float:left; margin: 0 0 20px 20px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .tagCloud a{ text-decoration:none; } Comprobamos que la nube y el listado se muestren correctamente en este link. Pueden descargar el theme desde aqu: themeTaller 12
79
Clase 13: Pgina de bsquedas e integracin con Google Custom Search Engine
Por defecto WordPress utiliza el template search.php para mostrar sus resultados de bsquedas, si no encuentra dicha plantilla entonces utiliza index.php. Vamos a colocar un pequeo formulario de bsqueda en el encabezado del sitio. Buscaremos lograr lo que se muestra en la siguiente imagen:
Para ello utilizaremos el siguiente cdigo que podremos despus del primer men: <div id="search"> <form method="get" id="searchform" action="<?php bloginfo('home'); ?>/"> <input type="text" value="Buscar..." onclick="this.value='';" name="s" id="s" class="searchtxt"/> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div> Para el estilo, primero aadiremos a #header un nuevo selector position:relative; #header { padding: 5px 20px; width:920px; height:110px; position:relative; } De este modo ahora todos los elementos que estn dentro de las etiquetas de #header pueden utilizar posicionamiento en relacin al padre. Procedemos a darle estilo a nuestro formulario. #search { width: 185px; border:1px solid #7ec5ff; position:absolute; right:20px; bottom:20px; -webkit-border-radius: 3px; border-radius: 3px; } #search form input#s { width:180px; height:20px; font-size:11px;
80
font-style:italic; padding: 0 0 0 5px; background-image:url(images/lupa.png); background-position:right center; background-repeat:no-repeat; border:none; } #search form input[type=button] { display:none; } Vern que nuestro #search utiliza el selector position y con el valor absolute nos permite definir un top y un right. Les recomiendo que lean la documentacin sobre positioning aqu y aqu. El archivo de lupa.png se encuentra dentro del nuevo paquete para descargar con la presente clase al pie de pgina. El botn necesitamos que exista, pero no necesitamos que se vea, por lo que le damos la indicacin para que no se muestre. Cuando el usuario ingrese su bsqueda y presione enter, la bsqueda se iniciar sin necesidad alguna de clickear un botn. WordPress buscar la plantilla search.php a la cual le colocaremos un layout estandar. <?php get_header(); ?> <div id="wrapper"> <h1>Resultados para <?php the_search_query(); ?></h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time('F jS, Y') ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <div><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></div> <?php get_sidebar(); get_footer(); ?> Utilizamos la funcin the_search_query para mostrar en el ttulo el trmino de bsqueda que introdujo el usuario. Con esto ya nos queda la funcin de bsquedas de WordPress bastante completa.
81
Introduzcamos un formulario de bsquedas personalizadas de Google en nuestro theme. Las razones son varias: Posibilidad de monetizar nuestras bsquedas: Google CSE permite el uso de Google Adsense. Mejoras en el rendimiento del servidor al ahorrarnos las consultas a la base de datos. Permite buscar en varios sitios a definir por nosotros. Es de Google, necesitamos decir mas?
Para crear una cuenta para nuestro sitio nos dirigimos a www.google.com/cse, le damos nombre a nuestro buscador, definimos el idioma, los sitios en los que habr de buscar y activamos Adsense si lo deseamos. Lo que necesitamos de todo este proceso es la ID del motor de bsqueda generado.
82
Ahora bien, no queremos destruir el formulario de bsqueda que hemos agregado recientemente, as que aadiremos nuestro nuevo formulario en una de las sidebars. <div class="widget"> <form class="search" name="search" action="http://www.summarg.com/demos/themetaller/resultados.php" id="cse-search-box"> <input type="hidden" name="cx" value="010330468867836346028:q6pfqadll de" /> <input type="hidden" name="cof" value="FORID:11" /> <input type="hidden" name="ie" value="UTF-8" /> <input id="s" class="searchtxt" type="text" name="q" size="31" /> <input type="submit" name="sa" class="btn" /> </form> <script type="text/javascript" src="http://www.google.com/coop/cse/ brand?form=cse-search-box&lang=es"></script> </div> En el value del primer input debemos colocar el ID del motor de bsqueda que acabamos de generar. Emprolijamos un poco desde el style.css form#cse-search-box input#s { width: 220px; float:left; } form#cse-search-box input[type=submit] { float:left; border: 1px solid #7ec5ff; background-color: #7ec5ff; color: white;
height:22px; font-weight:bold; font-size:11px; margin: 0 0 0 5px; width:45px; overflow:hidden; } Comprobamos que se muestre correctamente en nuestro theme.
Ahora debemos colocar nuestra plantilla de resultados, que se llamar resultados.php. La misma contiene la estructura bsica de cualquier plantilla con la salvedad de que en vez de colocar un bucle slo colocaremos el script de Google CSE. Adems vamos a colocar este archivo fuera del directorio de nuestro theme, directamente en el raz del sitio, por lo que en la primer lnea utilizaremos una llamada para poder utilizar nuestro theme normalmente. resultados.php <?php require('./wp-blog-header.php'); ?> <?php get_header(); ?> <div id="wrapper"> <div id="cse-search-results"> <script type="text/javascript"> var googleSearchIframeName = "cse-search-results"; var googleSearchFormName = "cse-search-box"; var googleSearchFrameWidth = 600; var googleSearchDomain = "www.google.com"; var googleSearchPath = "/cse"; </script> <script type="text/javascript" src="http://www.google.com/afsonline/ show_afs_search.js"></script> </div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> Y efectuamos una bsqueda a modo de prueba.
83
Nuestro theme ya tiene dos formularios de bsqueda totalmente funcionales. Pods verlo en nuestro demo online. Descarg la clase: themeTaller 13
84
Actualmente el plugin mas utilizado para lograr esto es wp-pagenavi, pero en esta oportunidad insertaremos una paginacin sin utilizar ningn plugin. Meramente creamos la funcin y la insertamos en nuestro functions.php function wp_pagenavi() { global $wp_query, $wp_rewrite; $pages = ''; $max = $wp_query->max_num_pages; if (!$current = get_query_var('paged')) $current = 1; $args['base'] = str_replace(999999999, '%#%', get_pagenum_ link(999999999)); $args['total'] = $max; $args['current'] = $current; $total = 1; $args['mid_size'] = 3; $args['end_size'] = 1; $args['prev_text'] = '<img src="'.get_bloginfo('template_url').'/images/arrow-left.png" />'; $args['next_text'] = '<img src="'.get_bloginfo('template_url').'/images/arrow-right.png" />'; if ($max > 1) echo '<div class="wp-pagenavi">'; if ($total == 1 && $max > 1) $pages = '<span class="pages">Página ' . $current . ' de ' . $max . '</span>'; echo $pages . paginate_links($args); if ($max > 1) echo '</div>'; } Las dos imgenes que mencionamos en los argumentos se entregan en el RAR que pueden descargar al pi del tutorial. La funcin lo que hace es obtener las cantidades mximas de pginas existentes en la query y darle un formato que contenga mas informacin y nos permita navegar salteando pginas si lo deseamos. Ahora abrimos nuestro archive.php y reemplazamos estas lneas: <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div>
85
Por esta: <div class="navigation"><?php wp_pagenavi(); ?></div> Este reemplazo lo debemos ejecutar 5 veces en total. Luego continuamos con el estilo, en nuestro CSS colocamos: .wp-pagenavi span.pages, .wp-pagenavi a.page, .wp-pagenavi .page-numbers, .wp-pagenavi span.extend, .wp-pagenavi a.first, .wp-pagenavi a.nextpostslink, .wp-pagenavi a.previouspostslink, .wp-pagenavi a.last { padding:5px; height:20px; margin-right:5px; background: #7ec5ff; color:white; border:1px solid #5995c6; text-decoration:none; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi span.current, .wp-pagenavi a:hover { padding:5px; height:20px; margin-right:5px; background:#fff; color:#7ec5ff; border:1px solid #5995c6; text-decoration:none; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi a.next, .wp-pagenavi a.prev { padding-top:1px 0; height:20px; margin-right:5px; background: #7ec5ff; color:white; border:1px solid #5995c6; text-decoration:none; border-radius: 3px;
86
-moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi img { height:20px; width:25px; margin-top:0px; } Y con ello bastar.
'</p>'; } /*End of Breadcrumbs*/ Aadimos un estilo muy bsico. .breadcrumb { width: 100%; float:left; display:block; } .breadcrumb p a { text-decoration:none; } .breadcrumb p { font-size:12px; } E insertamos la funcin en archive.php debajo del div id#wrapper y debajo de cada apertura de un div contenedor de modo de atender todos los condicionales: <div class="breadcrumb"><?php the_breadcrumbs(); ?></div> Es un cdigo muy sencillo y no es del todo completo, pero sirve a nuestros propsitos. La funcin puede insertarse en la plantilla single.php, page.php, search.php, incluso en el home aunque no parece necesario. Es a criterio del desarrollador. Finalmente necesitamos elaborar una pgina de error 404. Esta pgina se visualiza cuando el usuario solicita una URL inexistente, ya sea porque se cambi la URL adrede, o bien se borr dicha entrada, o cualquier otro motivo. La plantilla que debemos crear es: 404.php <?php get_header(); ?> <div id="wrapper"> <h2>Error 404</h2> <p>Lo sentimos, el contenido que está intentando visualizar no se encuentra o fue movido a otra parte. Por favor utilice nuestro formulario de búsquedas</p> <div id="searchInner"> <form method="get" id="searchform" action="<?php bloginfo('home'); ?>/"> <input type="text" value="Buscar..." onclick="this.value='';" name="s" id="q" class="searchtxt"/> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?>
88
El formulario es el mismo que el del header, pero debemos cambiar leves detalles (por ejemplo, cambiar el posicionamiento absoluto a un float) y adems no podemos usar un id dos veces, as que lo reemplazamos. #searchInner { width: 185px; border:1px solid #7ec5ff; float:left; -webkit-border-radius: 3px; border-radius: 3px; } #searchInner form input#q { width:180px; height:20px; font-size:11px; font-style:italic; padding: 0 0 0 5px; background-image:url(images/lupa.png); background-position:right center; background-repeat:no-repeat; border:none; } #searchInner form input[type=button] { display:none; } Si ingresamos una url cualquiera (ej. http://www.summarg.com/demos/themetaller/asdasdasd) Obtendremos el siguiente resultado:
89
Si googlean imgenes de error 404 van a encontrar ideas muy divertidas y originales para utilizar en este tipo de pginas. Pueden descargar la clase de hoy desde aqu: themeTaller 14
Nuestro theme ya est listo, pero cmo podemos hacernos la vida mas simple a la hora de gestionar los anuncios de un sitio? Sabemos que colocar anuncios Adsense ac y all es cosa de una vez, pero el asunto se vuelve mas complejo si adems vendemos espacios de forma mensual y nuestros anunciantes cambian con frecuencia. Vamos a retomar una herramienta que les presentamos hace tiempo, que es gratuita y se integra a nuestro theme muy bien: Options Framework Theme de WP Theming (tiene una versin paga con varias herramientas muy interesantes). Esta herramienta, que podemos descargar desde github, nos permite usar variables personalizadas en situaciones diferentes de las que vamos a plantear en esta clase. Pensemos que nos puede permitir ingresar el cdigo hexadecimal de un nuevo color de fondo, o texto para incluir en un rea en donde no queremos usar widgets, trozos de cdigo completos, mensajes globales a usuarios, etc. Lo primero que necesitamos hacer es descomprimir el paquete y colocar el siguiente cdigo al inicio de nuestro functions.php, despus de la etiqueta <?php. if ( ! function_exists( optionsframework_init ) ) { define( OPTIONS_FRAMEWORK_DIRECTORY, get_template_directory_uri() . / inc/ ); require_once dirname( __FILE__ ) . /inc/options-framework.php; } Luego copiamos el archivo options.php y la carpeta /inc/ y las colocamos en el raz de nuestro theme. 90
Ahora editemos el archivo options.php, que es en donde podremos gestionar las pestaas y sus contenidos dentro de Theme Options.
Para eliminar el contenido de pruebas debemos borrar desde la lnea 105 del options.php hasta la 288. Vamos a buscar aadir dos sectores de publicidad a los que le aadiremos una imagen y su respectivo link, y aprovechamos a completar los tres cuadros de texto que figuran debajo del slider desde las opciones de nuestro theme. 91
Vamos a trabajar insertando las opciones a partir de la lnea 105. Primero generamos el encabezado de nuestra seccin Publicidad. $options[] = array( 'name' => __('Publicidad', 'options_framework_theme'), 'type' => 'heading'); Luego aadimos dos campos de texto que vamos a usar para colocar los links, y dos campos de upload para las imgenes. $options[] = array( 'name' => __('Link Ad Header', 'options_framework_theme'), 'desc' => __('Link conteniendo http://...', 'options_framework_theme'), 'id' => 'link_ad_header', 'type' => 'text'); $options[] = array( 'name' => __('Imagen Ad Header', 'options_framework_theme'), 'desc' => __('400x60px', 'options_framework_theme'), 'id' => 'image_ad_header', 'type' => 'upload'); $options[] = array( 'name' => __('Link Ad Footer', 'options_framework_theme'), 'desc' => __('Link conteniendo http://...', 'options_framework_theme'), 'id' => 'link_ad_footer', 'std' => 'Default', 'type' => 'text'); $options[] = array( 'name' => __('Imagen Ad Footer', 'options_framework_theme'), 'desc' => __('281x100px', 'options_framework_theme'), 'id' => 'image_ad_footer', 'type' => 'upload'); El parmetro name especifica el ttulo de nuestro campo, desc sirve para colocar una descripcin que se ver debajo del ttulo, id se utiliza luego para invocar al contenido del elemento, type define el tipo de campo que ser. Tambin tenemos adicionalmente class (para elegir algunas variantes de type) y std que sirve para colocar contenido por defecto.
92
Abrimos nuestro header.php y colocamos el siguiente cdigo luego del div#logo: <?php if ( of_get_option( 'image_ad_header' ) ) { ?> <div class="adHeader"> <a href="<?php echo of_get_option( 'link_ad_header', 'no entry' ); ?>"> <img src="<?php echo of_get_option( 'image_ad_header' ); ?>" /> </a> </div> <?php } ?> Con ello establecemos un condicional en el que si encuentra que #image_ad_header (nuestro id de la imagen para el header) tiene contenido, entonces coloca un div.adHeader y en su interior el link con el contenido de #link_ad_header y la imagen del id ya mencionado. Le damos un poco de estilo a la clase que acabamos de crear. .adHeader { width: 400px; height:60px; float:left; margin: 35px 0 0 10px; } Subimos contenido para estos dos campos.
93
Excelente! Ahora procedemos a repetir la operacin pero esta vez en el footer. Aprovechamos a comentar que la clase .widget en el footer debera tener 293px de ancho, as que lo corregimos, del mismo modo la imagen del aviso deber tener ese valor para su ancho. Podemos usar dicha clase para colocar dentro nuestra imagen en caso de que exista.
<?php if ( of_get_option( 'image_ad_footer' ) ) { ?> <div class="widget"> <a href="<?php echo of_get_option( 'link_ad_footer', 'no entry' ); ?>"> <img src="<?php echo of_get_option( 'image_ad_footer' ); ?>" /> </a> </div> <?php } ?> Finalmente vamos a nuestra seccin de destacados. Hasta ahora lo venamos manejando con publicaciones en la categora Productos Destacados, pero dado el formato que necesitamos queda algo desprolijo y se nos ocurre que podramos mejorarlo de este modo. Adems suponemos que puede haber muchsimas entradas y que cuando el dueo del sitio decida modificar los destacados puede cometer varios errores, como excederse en la cantidad de texto o colocar una imagen dentro, y eso rompera nuestro home. Este es el cdigo que tenemos ahora. <div id="featured"> <?php query_posts('category_name=Producto Destacado&posts_per_page=3' ); while ( have_posts() ) : the_post(); ?> <div class="item"> <h3><?php the_title(); ?></h3> <?php the_content(); ?> </div><!-- end of item" --> <?php endwhile; wp_reset_query(); ?> </div><!-- end of featured --> Vamos a crear en options.php tres campos para cada uno de los destacados, uno para el ttulo, otro para el texto y uno mas para el link. Nos quedarn un total de nueve campos. Les mostramos los primeros tres junto con el separador para que todo esto est en una pestaa a la que llamaremos Destacados. $options[] = array( 'name' => __('Destacados', 'options_framework_theme'), 'type' => 'heading'); $options[] = array( 'name' => __('Titulo destacado 1', 'options_framework_theme'), 'id' => 'titulo_destacado_1', 'std' => 'Default Value', 'type' => 'text'); $options[] = array( 'name' => __('Link destacado 1', 'options_framework_theme'), 'id' => 'link_destacado_1', 'type' => 'text'); $options[] = array( 'name' => __('Texto destacado 1', 'options_framework_theme'), 'id' => 'textarea_destacado_1', 'type' => 'textarea'); Y en el index.php reemplazamos el bucle que llama a los tres elementos por: <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_1' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_1' ); ?>"> 94
<p><?php echo of_get_option( 'textarea_destacado_1' ); ?></p> </a> </div><!-- end of item --> <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_2' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_2' ); ?>"> <p><?php echo of_get_option( 'textarea_destacado_2' ); ?></p> </a> </div><!-- end of item --> <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_3' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_3' ); ?>"> <p><?php echo of_get_option( 'textarea_destacado_3' ); ?></p> </a> </div><!-- end of item --> Los links que aadimos van a generar un subrayado que no vamos a querer, as que lo eliminamos va CSS y de paso le cambiamos el color de fondo a cada elemento cuando se le hace un hover. .item a { text-decoration:none; } .item:hover { background-color:#f4f4f4; } 95
Podemos ver el resutado en nuestro demo, y descargar la clase de hoy themeTaller 15. Antes de finalizar queremos destacar que el framework que elegimos contiene las siguientes opciones de campos para incluir: Campos de texto (pequeos, medianos, largos) Textarea con el editor Upload de archivos Radio buttons Checkboxes Selects Select con las pginas de WordPress Select con las categoras de WordPress Select con las etiquetas de WordPress Color picker Selector de imgenes precargadas Todas estas opciones nos dan mucho margen de trabajo para hacer un theme amigable y completo. Adems de ser fcil de entender, es muy liviano y cuenta con la posibilidad de comprar la licencia para extender sus funciones.
96
97
Mediante este cdigo registramos el post type asignndole todos los valores necesarios para que se conviertan en un tipo de entradas que acepta archivo, que se muestra en los menes, que se puede exportar, que soporta los campos de ttulo, el editor, miniaturas y custom fields, etc. Existe un generador de cdigo muy bueno que elabor la gente de themergency.com en este link. Al completar el formulario en varios pasos obtenemos el cdigo resultante de nuestras especificaciones. Vamos a querer asignarle categoras a nuestras entradas, y queremos definir las mismas de modo independiente al resto de las entradas comunes, as que para ello seguimos colocando cdigo en nuestro functions.php: function register_portfoliotaxonomies() { $labels = array( 'name' => _x( 'tipos', 'taxonomy general name' ), 'singular_name' => _x( 'tipo', 'taxonomy singular name' ), 'add_new' => _x( 'Agregar tipo', 'tipo'), 'add_new_item' => __( 'Agregar tipo' ), 'edit_item' => __( 'Editar tipo' ), 'new_item' => __( 'Nuevo tipo' ), 'view_item' => __( 'Ver tipo' ), 'search_items' => __( 'Buscar tipos' ), 'not_found' => __( 'No encontrado' ), 'not_found_in_trash' => __( 'No encotrado' ), ); $pages = array('portfolio'); $args = array( 'labels' => $labels, 'singular_label' => __('tipo'), 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'show_tagcloud' => false, 'show_in_nav_menus' => true, '_builtin' => false, 'rewrite' => array('slug' => 'porfoliotax','with_ front' => FALSE ), ); register_taxonomy('portfoliotaxonomies', $pages, $args); } add_action('init', 'register_portfoliotaxonomies'); De este modo generamos las categoras para Portfolio. Pueden revisar una descripcin de los parmetros de register_taxonomy en el codex. Procedemos a completar con algunas categoras antes de subir material. Necesitamos tener algunas entradas ingresadas para poder trabajar, as que vamos a crear un portfolio de una empresa de marketing y diseo.
98
Ahora si podemos proceder a agregar algunas entradas en diferentes categoras. A medida que lo hagamos veremos que tenemos problemas para visualizar los contenidos (salvo que no estn usando URLs amigables), por lo que debemos recrear los permalinks. El modo mas sencillo es cambiando la configuracin un momento a predeterminado y volvindola a cambiar a la que hayamos elegido.
99
Vamos a echar mano a un recurso muy til en esa nueva seccin: los metaboxes. Estas cajas son una versin sofisticada para manejar los valores de custom fields, dejando al usuario un entorno mas amigable para completar los campos. Vamos a crear tres campos de texto y un campo con dos radio buttons. Los datos que recabemos con los tres primeros elementos sern usados en clases por venir, pero los radio los vamos a usar hoy mismo.
Functions.php /* Metabox */ $meta_box = array( 'id' => 'metabox-portfolio', 'title' => 'Elementos del Portfolio', 'page' => 'portfolio',
'context' => 'normal', 'priority' => 'high', 'fields' => array( array( 'name' => 'Cliente', 'desc' => 'Nombre del cliente', 'id' => 'cliente', 'type' => 'text', 'std' => 'Un Cliente' ), array( 'name' => 'Socios', 'desc' => 'Nombre del/los socios', 'id' => 'socios', 'type' => 'text', 'std' => '' ), array( 'name' => 'Descripcion', 'desc' => 'Descripcion corta para la portada', 'id' => 'descripcion', 'type' => 'text', 'std' => '' ), array( 'name' => 'Layout', 'id' => 'layout', 'type' => 'radio', 'options' => array( array('name' => 'Layout1', 'value' => 'Layout1'), array('name' => 'Layout2', 'value' => 'Layout2') ) ) ) ); add_action('admin_menu', 'mytheme_add_box'); // Add meta box function mytheme_add_box() { global $meta_box; add_meta_box($meta_box['id'], $meta_box['title'], 'mytheme_show_box', $meta_box['page'], $meta_box['context'], $meta_box['priority']); } // Callback function to show fields in meta box function mytheme_show_box() { global $meta_box, $post; // Use nonce for verification echo '<input type="hidden" name="mytheme_meta_box_nonce" value="', wp_ create_nonce(basename(__FILE__)), '" />'; echo '<table class="form-table">'; foreach ($meta_box['fields'] as $field) {
100
// get current post meta data $meta = get_post_meta($post->ID, $field['id'], true); echo '<tr>', '<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>', '<td>'; switch ($field['type']) { case 'text': echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />', '<br />', $field['desc']; break; case 'textarea': echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4" style="width:97%">', $meta ? $meta : $field['std'], '</textarea>', '<br />', $field['desc']; break; case 'select': echo '<select name="', $field['id'], '" id="', $field['id'], '">'; foreach ($field['options'] as $option) { echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>'; } echo '</select>'; break; case 'radio': foreach ($field['options'] as $option) { echo '<input type="radio" name="', $field['id'], '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' />', $option['name']; } break; case 'checkbox': echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' />'; break; } echo '<td>', '</tr>'; } } add_action('save_post', 'mytheme_save_data'); // Save data from meta box function mytheme_save_data($post_id) { global $meta_box; // verify nonce if (!wp_verify_nonce($_POST['mytheme_meta_box_nonce'], basename(__ echo '</table>';
101
FILE__))) { return $post_id; } // check autosave if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; } // check permissions if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) { return $post_id; } } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } foreach ($meta_box['fields'] as $field) { $old = get_post_meta($post_id, $field['id'], true); $new = $_POST[$field['id']]; if ($new && $new != $old) { update_post_meta($post_id, $field['id'], $new); } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); } } 102
Esos radio buttons los vamos a usar para crear dos estilos diferentes de archivo single para nuestro custom post type.
La plantilla single-cpt.php
Arranquemos a generar la plantilla para visualizar un elemento. Recordemos lo referente a jerarquas de plantillas (template hierarchy) y segn el mapa de plantillas necesitamos crear un archivo single-portfolio.php. Vamos a crear tres plantillas en una usando condicionales en base a ese campo Layout. La primera de ellas contendr un cuadro con los datos del metabox arriba de todo, y en la barra lateral lista entradas de la misma categora.
Veamos la primera parte de nuestro cdigo en single-portfolio.php. La estructura de colocar al inicio un get_header() seguido de un div que haga de contenedor es igual en todas. Lo que nosotros necesitamos es inmediatamente obtener el valor del custom field layout por lo que primero llamamos a la variable global $post y luego procedemos a usar get_post_meta. Construimos un contenedor con los valores de cliente, socios y descripcin, a la que le colocamos una miniatura a la izquierda (para obtener la miniatura pequea por defecto de WordPress usamos thumb). Seguidamente, y siempre dentro del bucle, colocamos las funciones para llamar al ttulo y al contenido. <?php get_header(); ?> <div class="wrapperPortfolio"> <?php global $post; $layout = get_post_meta(get_the_id(), 'layout', TRUE); if ($layout == 'Layout1') { if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $socios = get_post_meta(get_the_id(), 'socios', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioUno"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <div class="portfolioDetalle"> <?php the_post_thumbnail('thumb'); ?> <?php echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; echo '<br /><div class="detalleTitulo">Socios</div> '.$socios; echo '<br /><div class="detalleTitulo">Decripcion</div> '.$descripcion.'</p>'?> </div> <?php the_content(); ?> </div><!-- end of portfolioUno --> <?php endwhile; endif; ?> En la segunda parte de nuestro Layout1 queremos encargarnos de colocar en la barra lateral otras entradas de la misma categora. Esto ya resulta fcil para nosotros, no es cierto? De paso dejo establecidos los condicionales para los otros Layouts, por el momento no se ver nada mas que un texto. <div class="sidebarPortfolio"> <div class="itemPortfolio"> <h3>Otros trabajos relacionados</h3> </div> <?php $categories = get_the_category($post->ID); $args= array( 'cat' => $categories, 'posts_per_page' => 4, 'post_type' => 'Portfolio' ); query_posts($args); if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
103
<div class="itemPortfolio"> <?php the_post_thumbnail('portfolio'); ?> <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3> </div> <?php endwhile; endif; ?> </div> <?php } else if ($layout == 'Layout2') { ?> Otro Layout <?php } else { ?> Y otro layout mas.... <?php } ?> </div><!-- end of wrapper--> <?php get_footer(); ?> Necesitamos definir el tamao de la imagen destacada, colocamos el siguiente valor en nuestro functions.php: add_image_size( 'portfolio', 230,130, true ); Y hasta aqu nuestro CSS. .wrapperPortfolio { width: 940px; float:left; margin: 20px 0 20px 20px; } .portfolioUno { width: 670px; float:left; } .sidebarPortfolio { width: 230px; margin: 20px 0 0 20px; float:left; } .itemPortfolio { width: 230px; border:1px solid #7ec5ff; float:left; display:block; margin: 0 0 20px 0; background-color:#7ec5ff; } .itemPortfolio img { margin:0; padding:0; } .itemPortfolio h3 { font-size:16px; line-height:22px; font-weight:bold; text-align:center; 104
margin: 5px 0 0 0; color:white; } .itemPortfolio h3 a { color:white; text-decoration:none; } .portfolioDetalle { width: 650px; padding:10px; margin: 0 0 20px 0; background-color: #f4f4f4; -webkit-border-radius: 5px; border-radius: 5px; display:block; float:left; } .portfolioDetalle img { float:left; margin: 0 10px 0 0; } .detalleTitulo { width: 85px; color: #7ec5ff; font-weight:bold; float:left; text-align:right; margin: 0 5px 0 0; } En Layout 2 vamos a disponer de los elementos de un modo ligeramente diferente, construyendo en nuestra barra lateral el rea en donde mostraremos los datos del metabox y debajo nuestra imagen destacada. Aadimos al functions.php el nuevo tamao que usaremos para the_post_ thumbnail();. Insertamos el siguiente valor debajo del ltimo add_image_size(); add_image_size( 'layout2', 340, 300, true); As quedar nuestro Layout 2:
105
Ahora procedemos a completar el single-php.php reemplazando ese texto que colocamos previamente Otro Layout. if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $socios = get_post_meta(get_the_id(), 'socios', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioDos"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of portfolioDos --> <div class="sidebarPortfolioDos"> <div class="portfolioDosDetalle"> <?php echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; echo '<br /><div class="detalleTitulo">Socios</div> '.$socios; echo '<br /><div class="detalleTitulo">Decripcion</div> '.$descripcion.'</p>'?> </div> <?php the_post_thumbnail('layout2'); ?> </div> <?php endwhile; endif; ?> Este segundo layout es mas sencillo pues tiene un solo bucle. Veamos el CSS: .portfolioDos { width: 560px; float:left; } .portfolioDosDetalle { width:320px; padding:10px; margin: 0 0 20px 0px; background-color: #f4f4f4; -webkit-border-radius: 5px; border-radius: 5px; display:block; float:right; } .sidebarPortfolioDos { width: 340px; margin: 20px 0 0 10px; padding: 0 0 0 10px; border-left: 1px solid #f4f4f4; float:left; } Para el tercer Layout, puesto que ya comprendimos la idea, vamos a insertar parte de la plantilla single.php con la salvedad de que tenemos que eliminar un contenedor y vamos a eliminar el area de informacin de la entrada.
106
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of dos-tercios --> <?php endwhile; endif; get_sidebar(); Con esto terminamos por hoy, esperamos que hayan comprendido la idea de la plantilla singlecpt.php y que puedan explotarla al mximo a la hora de disear sus sitios. Demo online Layout 1 | Demo online Layout 2 | Demo online Layout 3 Descargar la clase de hoy: themeTaller 16 Nota importante: Para generar los metabox nosotros utilizamos un framework que encontramos hace un tiempo en la web y no recordamos quin es su autor, por eso se los dejamos para que lo utilicen aqu: meta-box Si alguno reconoce el cdigo y al autor, por favor envenos un mensaje para mencionarlo como corresponde.
107
108
type=attachment&post_mime_type=image&numberposts=1" ); if ($attached_image) { foreach ($attached_image as $attachment_id => $attachment) { set_post_thumbnail($post->ID, $attachment_id); } } } } //end function add_action('the_post', 'autoset_featured'); add_action('save_post', 'autoset_featured'); add_action('draft_to_publish', 'autoset_featured'); add_action('new_to_publish', 'autoset_featured'); add_action('pending_to_publish', 'autoset_featured'); add_action('future_to_publish', 'autoset_featured'); Buscaremos que nuestra plantilla tenga el siguiente formato: 109
Llegado este punto, y si ya tienen varios elementos cargados, necesitan regenerar las miniaturas para que muestre el nuevo formato. Pueden usar el plugin Regenerate Thumbnails que les va a ahorrar mucho tiempo y esfuerzo. Vamos con el CSS. /* plantilla taxonomia */ .portfolioItem { width: 230px; height:230px; float:left; position:relative; margin:0; padding:0; } .portfolioItem a { color:white; text-decoration:none; } .portfolioItem a img { border:none;
margin:0; } Necesitamos que .portfolioItem tenga position:relative ya que el contenedor que le sigue tendr que superponerse a nuestra imagen para lograr el efecto deseado, para lo cual usar position:absolute y le indicaremos que se posicione en top:0 y left:0. .portfolioItemDetalle { display:none; position:absolute; top:0; left:0; background-image:url(images/darky.png); background-repeat:repeat; padding: 10px; width: 210px; height:210px; color:white; margin:0; } .portfolioItemDetalle h2 { text-align:center; margin-top:20px; color:white; } Al contenedor con el ttulo y los detalles del trabajo le damos un display:none para ocultarlo, ya que queremos que se muestre nicamente cuando el usuario pase el mouse por arriba del elemento y luego se oculte. Con la siguiente lnea completamos el truco: .portfolioItem:hover .portfolioItemDetalle { display:block; } Listo! El truco funciona. Aunque Qu tal si ponemos un poquito de jQuery para animar esas ventanitas un poco? De ese modo podemos suavizar el efecto al pasar el mouse por arriba. Comentemos o eliminemos el ltimo trozo de CSS y coloquemos el siguiente cdigo en la plantilla de taxonoma luego del endif; <script type="text/javascript"> $(function() { $(".portfolioItem").hover(function() { $(this).children(".portfolioItemDetalle").show("fast"); },function(){ $(this).children(".portfolioItemDetalle").hide("fast"); }); }); </script> Con esto ya tenemos un bonito modo de mostrar nuestros items y dejamos las bases bien plantadas para que los lectores puedan tomar su propio rumbo a la hora de usar Custom Post Types. Pueden ver el producto terminado en el demo online.
110
Todava podemos hacer algo mas, un poco mas complicado y personalizado pero que va a quedar muy bien para lucir nuestro porfolio. Fuera de programa les vamos a regalar una integracin entre el plugin jQuery Isotope y nuestro portfolio. Creamos una pgina personalizada de nombre page-portfolio.php y colocamos en su interior exactamente lo que ya tenemos para taxonoma con pequeas diferencias: Agregamos el encabezado con el template name. Modificamos los argumentos de la query para que muestre cantidad ilimitada de elementos dentro del post_type que nos interesa. Eliminamos la lnea de paginacin ya que no vamos a usar ninguna. <?php /* template name: Portfolio + Isotope */ get_header(); ?> <div class="wrapperPortfolio"> <?php $args= array( 'posts_per_page' => 9999, 'post_type' => 'Portfolio' ); query_posts($args); if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioItem"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <?php the_post_thumbnail('portfolioitem'); ?> <div class="portfolioItemDetalle"> <h2><?php the_title(); ?></h2> <?php if ($cliente) { echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; } if ($descripcion) { echo '<br /><div class="detalleTitulo">Decripcion</ div> '.$descripcion.'</p>'; } ?> </div> </a> </div><!-- end of portfolioItem --> <?php endwhile; endif; ?> <script type="text/javascript"> $(function() { $(".portfolioItem a").hover(function() { $(this).children(".portfolioItemDetalle").show("fast"); },function(){ $(this).children(".portfolioItemDetalle").hide("fast"); }); }); </script> </div> <?php get_footer(); ?> Creamos una pgina y le asignamos la plantilla que estamos construyendo. Descargamos desde
111
Isotope el plugin y lo anexamos a nuestro header. <script type="text/javascript" language="javascript" src="<?php bloginfo('template_directory'); ?>/scripts/jquery.isotope.min.js"></ script> Ahora bien, el plugin nos pide que respetemos una estructura de marcado determinada el men y para los elementos. Pueden ver aqu la documentacin (especficamente en lo que respecta a sorting) y les transcribimos el cdigo del demo de Isotope para que se den una buena idea. <ul id="sort-by"> <li><a href="#name">name</a></li> <li><a href="#symbol">symbol</a></li> <li><a href="#number">number</a></li> <li><a href="#weight">weight</a></li> <li><a href="#category">category</a></li> </ul> <div id="container"> <div class="element transition metal" data-category="transition"> <p class="number">79</p> <h3 class="symbol">Au</h3> <h2 class="name">Gold</h2> <p class="weight">196.966569</p> </div> <div class="element metalloid" data-category="metalloid"> <p class="number">51</p> <h3 class="symbol">Sb</h3> <h2 class="name">Antimony</h2> <p class="weight">121.76</p> </div> </div> Entonces nosotros intentaremos adaptar esa estructura a nuestro trabajo para que funcione el plugin. Debajo de la llamada de get_header() insertamos el men desde el que llamaremos a cada una de las taxonomas para que se muestren. <div id="options"> <ul id="filters" data-option-key="filter"> <li><a href="#filter" data-option-value="*">Todos</a></li> <li><a href="#filter" data-option-value=".Logos">Logos</a></li> <li><a href="#filter" data-option-value=".Packaging">Packaging</a></li> <li><a href="#filter" data-option-value=".Websites">Sitios Web</a></li> <li><a href="#filter" data-option-value=".Tarjetas">Tarjetas</a></li> </ul> </div> Inmediatamente despus de que se inicia el bucle necesitamos obtener el nombre de la taxonoma para colocarla en la clase de cada elemento, de ese modo el plugin puede traer a cada elemento cuando el usuario clickee en el men. $terms = get_the_terms( $post->ID , 'portfoliotaxonomies' ); foreach ( $terms as $term ) { $isotopeClass = $term->name; }
112
El nombre de la taxonoma se almacena en $isotopeClass, y ahora debemos imprimirla en nuestros elementos. <div class="portfolioItem isotopeElement <?php echo $isotopeClass; ?>"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <?php the_post_thumbnail('portfolioitem'); ?> <div class="portfolioItemDetalle"> <h2><?php the_title(); ?></h2> <?php if ($cliente) { echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; } if ($descripcion) { echo '<br /><div class="detalleTitulo">Descripci on</div> '.$descripcion.'</p>'; } ?> </div> </a> </div><!-- end of portfolioItem --> Con esto ya tenemos el marcado necesario y podemos proceder a aadir el cdigo javascript para que se ejecute el plugin. El siguiente cdigo debe anexarse al que ya habamos colocado para animar la aparicin de los detalles del item. <script type="text/javascript"> $(function(){ var $container = $('#isotopeArea'); $container.isotope({ itemSelector : '.isotopeElement', animationEngine : 'best-available' }); var $optionSets = $('#options .option-set'), $optionLinks = $optionSets.find('a'); $optionLinks.click(function(){ var $this = $(this); // don't proceed if already selected if ( $this.hasClass('selected') ) { return false; } var $optionSet = $this.parents('.option-set'); $optionSet.find('.selected').removeClass('selected'); $this.addClass('selected'); // make option object dynamically, i.e. { filter: '.my-filter-class' } var options = {}, key = $optionSet.attr('data-option-key'), value = $this.attr('data-option-value'); // parse 'false' as false boolean value = value === 'false' ? false : value; options[ key ] = value; if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) { // changes in layout modes need extra logic changeLayoutMode( $this, options ) } else { // otherwise, apply new options $container.isotope( options ); 113
} return false; }); }); </script> Con el parmetro animationEngine : best-available estamos indicando al plugin que utilice animaciones CSS3 cuando el navegador lo permita, y animaciones javascript en caso contrario. As que en nuestro CSS lo que tenemos que incluir son dichas transiciones. /** Isotope **/ .isotope, .isotope .isotope-item { /* change duration value to whatever you like */ -webkit-transition-duration: 0.8s; -moz-transition-duration: 0.8s; -ms-transition-duration: 0.8s; -o-transition-duration: 0.8s; transition-duration: 0.8s; } .isotope { -webkit-transition-property: height, width; -moz-transition-property: height, width; -ms-transition-property: height, width; -o-transition-property: height, width; transition-property: height, width; } .isotope .isotope-item { -webkit-transition-property: -webkit-transform, opacity; -moz-transition-property: -moz-transform, opacity; -ms-transition-property: -ms-transform, opacity; -o-transition-property: -o-transform, opacity; transition-property: transform, opacity; } /**** disabling Isotope CSS3 transitions ****/ .isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition { -webkit-transition-duration: 0s; -moz-transition-duration: 0s; -ms-transition-duration: 0s; -o-transition-duration: 0s; transition-duration: 0s; } Y para concluir damos estilo al men que acabamos de agregar, que dicho sea de paso ser igual al #menu-top que construimos al principio del taller. /** Menu isotope **/ ul#filters { margin:20px 20px 0 0; float:right; list-style-type:none;
114
height:30px; width: 920px; } ul#filters li a{ list-style-type:none; text-decoration:none; float:right; color: #7ec5ff; font-weight:bold; padding: 7px 10px; font-size:12px; } ul#filters li a:hover { text-decoration:none; background-color: #7ec5ff; color:#fff; font-weight:bold; padding: 7px 10px; } Nota: para que este cdigo les funcione tal cual est aqu, deben crear exactamente las mismas taxonomas en Portfolio que nosotros publicamos. Sino simplemente efecten las modificaciones en donde corresponda en el men. Demo online Descargar clase themeTaller 17
115
116
Vamos a crear una pgina personalizada para esta bsqueda y llamaremos al archivo pagesearch.php. <?php /* template name: search */ get_header(); ?> <div id="wrapper-dos"> <form name="searchcpt" class="searchcpt" action="<?php bloginfo('wpurl'); ?>/" method="get"> <p><strong>Buscador Portfolio</strong></p> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div><!-- end of wrapper--> <?php get_sidebar(); get_sidebar('dos'); get_footer(); ?> Ya colocamos las etiquetas de formulario y elegimos usar el layout que contiene dos barras laterales que construimos clases atrs. Lo primero que necesitamos hacer es establecer una diferencia entre este tipo de bsqueda y otros. Podramos tener varios CPT o mezclar este formulario con la bsqueda general del sitio, as que sera bueno definir que la bsqueda la realizaremos en el Portfolio, as que le vamos a pasar el parmetro con un input hidden (oculto). <input type="text" value="portfolio" hidden name="s" id="s" /> El primer custom field que utilizamos fue el que defina el layout as que generamos los radio buttons para que el usuario pueda elegir. <div class="seccionForm"> <div class="radiobuscar"> <input type="radio" name="layout" value="layout1"><div>Layout1</div> </div> <div class="radiobuscar"> <input type="radio" name="layout" value="layout2" checked><div>Layout2</
div> </div> </div> Ahora sera bueno colocar un select que permita seleccionar fcilmente una taxonoma, para lo que generaremos la funcin colocando el siguiente cdigo al final de nuestro functions.php function taxonomy_dropdown($taxonomy) { ?> <select name="cat" id="cat" class="postform"> <option value="">Elija sección</option> <?php $terms = get_terms($taxonomy); foreach ($terms as $term) { printf( '<option class="level-0" value="%s">%s</option>', $term->slug, $term->name ); } echo '</select>'; ?> <?php } ?> Dicha funcin recorre y lista los trminos dentro de la taxonoma que le indiquemos. En nuestra page-search.php colocamos la llamada a la funcin de la siguiente manera: <div class="selectArea"> <?php taxonomy_dropdown( 'portfoliotaxonomies' ); ?> </div> Finalmente nos sera de utilidad listar los socios de cada proyecto, pues cabe esperar que sea un dato que en mas de una oportunidad se repita. Para ello debemos realizar una consulta a la DB mediante $wpdb <div class="selectArea"> <select name="socio"> <option value="">Cualquiera</option> <?php $metakey = 'socios'; $socios = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = %s ORDER BY meta_value ASC", $metakey) ); if ($socios) { foreach ($socios as $socio) { echo "<option value=\"" . $socio . "\">" . $socio . "</option>"; } } ?> </select> </div> El CSS para esta seccin es el siguiente: .radiobuscar { width: 100px; float:left; margin: 0 0 5px 0; }
117
.radiobuscar div{ float:left; } .seccionForm { width: 380px; margin: 0 0 5px 0; float:left; } .selectArea { float:left; margin: 0 0 10px 0; } .searchcpt input[type=button] { float:left; border: 1px solid #7ec5ff; background-color: #7ec5ff; color: white; height:22px; font-weight:bold; font-size:11px; margin: 0 0 0 5px; padding: 5px 10px; overflow:hidden; } Hasta aqu pudimos construir el formulario, pero ahora debemos resolver la bsqueda. De paso podemos aprovechar a partir el formulario de bsquedas en dos archivos. Vamos a nuestro search.php y colocamos las siguientes lneas en la parte superior. Recuerden que deben cerrar la llave que se abre luego del else. $search_refer = $_GET["s"]; if ($search_refer == 'portfolio') { load_template(TEMPLATEPATH . '/ search-custom.php'); } else { En esta seccin utilizamos el primer input que colocamos en el formulario, que utilizamos nicamente para indicar que la variable s tiene por valor portfolio, y para tal caso escapa del template search.php y carga el template search-custom.php. Generamos el archivo search-custom.php y comenzamos a procesar los datos. Como primera medida usamos get_header() para cargar el encabezado y usamos GET para obtener las variables que pasamos por URL desde el formulario. <?php get_header(); $layout = $_GET["layout"]; $cat = $_GET["cat"]; $socio = $_GET["socio"]; Armamos la consulta con query_posts y pasamos todos los argumentos. En primer lugar indicamos el post_type, luego los trminos de portfoliotaxonomies. Para los valores de los custom fields utilizamos meta_query, y como usamos dos diferentes necesitamos introducir el parmetro relation para definir si se deben cumplir ambas condiciones o una u otra. Antes de los argumentos colocamos dos condicionales para cubrir las diferentes situaciones. Si $socio y $layout contienen valores, es decir que el usuario seleccion algo en ambos campos,
118
entonces la relacin que establecemos es AND y significa que se listarn las entradas que contengan los dos valores que pasamos (ej. que pertenezca a Socio X y que su Layout sea Layout1). Si $socio no contiene nada dentro y $layout si, entonces la relacin ser OR, lo que permite listar las entradas que cumplan una u otra condicin. if ($socio && $layout) { $relation = 'AND';} if (!$socio && $layout) { $relation = 'OR';} $args = array( 'post_type' => 'portfolio', 'portfoliotaxonomies' => $cat, 'meta_query' => array( 'relation' => $relation, array( 'key' => 'layout', 'value' => $layout, 'compare' => '=' ), array( 'key' => 'socios', 'value' => $socio, 'compare' => '=' ) ) ); query_posts( $args ); Llegado este punto ya podemos listar el resto de la plantilla con el bucle y los resultados. Para poder comprobar mejor el funcionamiento del formulario vamos a imprimir al pi de cada elemento el valor socio, layout y la taxonoma.
119
<div id="wrapper"> <h1>Resultados en el Portfolio</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); $sociokey = get_post_meta(get_the_id(), 'socios', TRUE); $layoutkey = get_post_meta(get_the_id(), 'layout', TRUE);
$terms = get_the_terms( $post->ID , 'portfoliotaxonomies' ); foreach ( $terms as $term ) { $taxonomy = $term->name; } ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_post_thumbnail('thumb'); the_excerpt(); ?> <?php echo $sociokey.' | '.$layoutkey.' | '.$taxonomy; ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de búsquedas.</p> <?php endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> La intencin de este trabajo es darles una idea de cmo se pueden explotar los Custom Post Types. Este formulario puede ampliarse introduciendo la posibilidad de ingresar trminos o ms custom fields. Tambin llegado este punto podramos elegir cargar los socios como etiquetas y no como custom fields, ya que tambin pueden introducirse en la query y son mas fciles de gestionar. Ver el formulario online Descargar clase: themeTaller 18
120
Plugins
Askimet: Incluido enWordPress, su misin es combatir elspamen todo el mundo, totalmente gratuito. Google XML Sitemap: Generador automtico desitemaps. All in One WP Security: Medidas bsicas de seguridad para tu WP. Contact Form 7: El mejorpluginpara formularios, permite el envo de archivos y mucho mas. Efficient Related Posts: Entradas relacionadas, optimizado en vistas de cuidar el consumo de recursos. Regenerate Thumbnails:Pluginobligatorio para los desarrolladores dethemes, regenera las miniaturas en base a los tamaos que encuentra en el functions.php. Resize at upload plus: Permite establecer el tamao mximo de las imgenes (en ancho y alto), y cuando el mismo es superior redimensiona la imagen. WP-Pagenavi: Inserta paginacin con nmeros. WP SyntaxHighlighter: Permite insertar cdigo en las entradas y mostrarlo con colores segn el lenguaje. WP to Twitter: Enva aTwittercada artculo al ser publicado. Lightbox Gallery: Aade el efectolightboxa tus galeras nativas deWordPress. Simple Lightbox: Efectolightboxa tus imgenes, permite configurar animaciones e incluso un modoslideshow. WP Lightbox 2: Inserta el efectolightboxa imgenes individuales o a galeras. AWPCP:Another WordPress Classifieds Plugin, completsimopluginpara insertar clasificados en nuestro sitio. Dispone de variosaddons premium. Cart66 Lite:Plugindee-commerce, permite vender productos digitales, genera programas de afiliado, ultra liviano. E-Shop: Potenteplugindee-commercecon varias opciones de listado de producto, cargos por flete, varias pasarelas de pago. Jigoshop: Este es unpluginmuy extendido, que cuenta con variosaddons premium(ver categora Jigoshop en Codecanyon), cuenta con la posibilidad deseteardiferentes parmetros por producto (ej. talles de ropa, colores, etc). Muy completo. Woocommerce: Uno de lospluginsmas poderosos, ya que cuenta con una amplia variedad deaddonstanto en elsitio de sus desarrolladorescomo enCodecanyon. WP-e-commerce: Este es uno de lospluginsmas antiguos que todava sobrevive y se adapta muy bien. Tiene una alta compatibilidad con casi cualquiertheme y adems cuenta con sus pro121
piosaddons premium.
Simple Advert: Completo gestor debannersque se integra conWordPress pero tambin funciona en cualquier plataforma. Funciones de publicacin por tiempo,clicks o impresiones. Sistema de estadsticas. Soporta enlaces, imgenes oflash. W3 Total Cache: Uno de lospluginsde cache mas completos, acelera la carga de pgina y economiza recursos del servidor. WP Mobile Edition: Detecta automticamente a los usuarios que ingresan desde un dispositivo mvil y carga unthemeoptimizado para dicha resolucin. Any Mobile Theme Switcher: Igual al anterior pero dispone de mayor control permitiendo cargar unthemepor cada tipo de dispositivo mvil encontrado. WPTouch Mobile Plugin: Elpluginpara visualizar desde dispositivos mviles mas popular del mercado. WordPress Mobile Pack:El mas completoplugin para desarrolladores, incluye varias adaptaciones para determinados dispositivos, untheme default, unthemepara el escritorio deWordPressy mas. 122
Snippets
Aadir custom post types a los feeds. function myfeed_request($qv) { if (isset($qv[feed])) $qv[post_type] = get_post_types(); return $qv; } Cambiar la longitud de the_excerpt function my_excerpt($length) { return 150; } add_filter(excerpt_length, my_excerpt); Cambiar el texto de leer mas del excerpt <?php function new_excerpt_more($more) { return [much more to go]; } add_filter(excerpt_more, new_excerpt_more); ?> Colocar imagen destacada automticamente function autoset_featured() { global $post; $already_has_thumb = has_post_thumbnail($post->ID); if (!$already_has_thumb) { $attached_image = get_children( post_parent=$post-
>ID&post_type=attachment&post_mime_type=image&numberposts=1 ); if ($attached_image) { foreach ($attached_image as $attachment_ id => $attachment) { set_post_thumbnail($post->ID, $attachment_id); } } } } //end function add_action(the_post, autoset_featured); add_action(save_post, autoset_featured); add_action(draft_to_publish, autoset_featured); add_action(new_to_publish, autoset_featured); add_action(pending_to_publish, autoset_featured); add_action(future_to_publish, autoset_featured); Funcin para colocar una cantidad personalizada de texto /* Original Plugin URI: http://labitacora.net/comunBlog/limit-post.phps Usage: the_content_limit($max_charaters, $more_link) */ function the_content_limit($max_char, $more_link_text = (more...), $stripteaser = 0, $more_file = ) { $content = get_the_content($more_link_text, $stripteaser, $more_ file); $content = apply_filters(the_content, $content); $content = str_replace(]]>, ]]>, $content); $content = strip_tags($content); if (strlen($_GET[p]) > 0) { echo <p>; echo $content; echo [...]</p>; } else if ((strlen($content)>$max_char) && ($espacio = strpos($content, , $max_char ))) { $content = substr($content, 0, $espacio); $content = $content; echo <p>; echo $content; echo [...]</p>; } else { echo <p>; echo $content; echo [...]</p>; } } Luego dentro del bucle se coloca: 123
<?php the_content_limit(150); ?> Aadir texto al final de nuestras entradas en los feeds function feedFilter($query) { if ($query->is_feed) { add_filter(the_content,feedContentFilter); } return $query; } add_filter(pre_get_posts,feedFilter); function feedContentFilter($content) { $content .= <p>Texto extra para los feeds... </p>; } return $content; 124
Aadir iconos segn el myme type del adjunto function get_attachment_icons($echo = false){ $sAttachmentString = <div class=documentIconsWrapper> \n; if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/pdf, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/pdf.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Word Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/msword, //MIME Type condition
))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/word.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Powerpoint Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/vnd.ms-powerpoint, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/PowerPoint.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Excel Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/vnd.ms-excel, //MIME Type condition ))){
125
foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/XLS8.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Zipped Files if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/zip, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/zip.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Audio Files $mp3s = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => audio, //MIME Type condition ) ); if (!empty($mp3s)) :
126
$sAttachmentString .= <ul class=audiofiles>; foreach($mp3s as $mp3) : $sAttachmentString .= <li>; if(!empty($mp3->post_title)) : //checking to make sure the post title isnt empty $sAttachmentString .= <h4 class=title>.$mp3->post_ title.</h4>; endif; if(!empty($mp3->post_content)) : //checking to make sure something exists in post_content (description) $sAttachmentString .= <p class=description>.$mp3>post_content.</p>; endif; $sAttachmentString .= <object width=470 height=24 id=single.$mp3->ID. name=single.$mp3->ID.>; $sAttachmentString .= <param name=movie value=player.swf>; $sAttachmentString .= <param name=allowfullscreen value=true>; $sAttachmentString .= <param name=allowscriptaccess value=always>; $sAttachmentString .= <param name=wmode value=transparent>; $sAttachmentString .= <param name=flashvars value=file=.$mp3->guid.>; $sAttachmentString .= <embed ; $sAttachmentString .= id=single.$mp3->ID. ; $sAttachmentString .= name=single.$mp3->ID. ; $sAttachmentString .= src=.get_ bloginfo(template_directory)./jw/player.swf ; $sAttachmentString .= width=470 ; $sAttachmentString .= height=24 ; $sAttachmentString .= bgcolor=#ffffff ; $sAttachmentString .= allowscriptaccess=always ; $sAttachmentString .= allowfullscreen=true ; $sAttachmentString .= flashvars=file=.$mp3>guid. ; $sAttachmentString .= />; $sAttachmentString .= </object>; $sAttachmentString .= <a href=.$mp3>guid.>Download</a>; $sAttachmentString .= </li>; endforeach; $sAttachmentString .= </ul>; endif; $sAttachmentString .= </div>; if($echo){ echo $sAttachmentString;
127
} add_shortcode(attachment icons, get_attachment_icons); Acortar el ttulo a determinada cantidad de caracteres: function the_title2($before = , $after = , $echo = true, $length = false) { $title = get_the_title(); if ( $length && is_numeric($length) ) { $title = mb_substr( $title, 0, $length, UTF-8 ); } if ( strlen($title)> 0 ) { if ( strlen($title) == $length ) $title = apply_filters(the_title2, $before . $title . $after, $before, $after); if ( $echo ) echo $title; else return $title; } } Luego en el theme colocar la funcin con la cantidad de caracteres a imprimir: <?php the_title2(15); ?>
} return $sAttachmentString;
128
Conclusin
WordPress se populariz como plataforma para blogs, pero fue convirtindose en un potente CMS a la altura de Joomla o Drupal. El diseo de plantillas para WordPress es realmente simple, como pudimos ver, y con los conocimientos previos necesarios nos permite en poco tiempo conquistar la construccin de themes y explotar al mximo las capacidades de la plataforma. No se necesitan grandes conocimientos de php, solo una base sobre la lgica de programacin y algunas funciones sueltas aqu y all. Lo que si resulta importante es tener una buena base de HTML y CSS, y aade un plus especialmente interesante el tener buenos conocimientos de jQuery. La inclusin de los Custom Post Types, adems de los mens, las miniaturas personalizables y otros detalles, marcaron en WordPress un antes y un despus en lo que respecta a disear sitios con organizaciones complejas de contenidos pero manteniendo la simplicidad de uso para el editor y usuario comunes. 129 Una de las cosas que mas nos atrap de WordPress es que al lado de sus competidores resulta muy liviano para el servidor y dispone de actualizaciones constantes parcheando las vulnerabilidades y bugs que surgen. Cada da emergen mas herramientas para administrar mltiples instalaciones de WordPress, backupeos automticos, plugins con medidas de seguridad extra y antivirus que detectan e informan de cualquier cdigo extrao que logre filtrarse. Si bien no es imposible de vulnerar un sitio hecho con WordPress, sigue siendo bastante confiable tomando las medidas del caso. La comunidad desarrolladora es cada da mas grande, y esto impacta directamente en el nmero de plugins y themes disponibles. En resumen, no por nada hoy es la plataforma mas popular del mercado y miles de miles de personas basan su trabajo en WordPress. Esperamos que ustedes disfruten de este taller tanto como nosotros y que puedan sacarle provecho en sus trabajos o como hobbie.