
Drupal 8: Utilizando plugin isotope en una vista
Autor: fjavimartin
Fecha de Creación: 08/04/2017
Categorías:
Metafizzy nos ofrece el plugin isotope cuya principal característica es que permite filtrar elementos de una vista en función de la categoría que tenga asignada, algo que nos viene como anillo al dedo para aplicarlo en una vista de drupal y que sabremos como hacer después de leer este artículo.
¿Que es Isotope?
Isotope es un plugin javascript de Metafizzy que nos permite, entre otras cosas, filtrar los elementos de un contenedor en función de una determinada categoría asignada previamente u ordenarlos por orden alfabético o numérico según los campos que dispongamos. Podéis ver una demo en su web.
Como podréis ver, es un efecto muy atractivo que nos permite filtrar u ordenar elementos de una manera atractiva visualmente y muy dinámica. ¿Os imagináis lo bien que quedarán nuestras vistas en drupal con este plugin?
Objetivo
Desde la versión 7 de drupal podemos encontrar módulos que nos permitirán utilizar este plugin:
En este artículo no pretendo que instalemos uno de estos módulos y creemos una vista para utilizar el plugin sino que incluyamos la librería isotope en nuestro theme para después cargarla en una vista y ejecutarla sobre los elementos que nos devuelva esta vista……...Sí, será más complicado, pero también será mucho más flexible.
Dado que nuestro objetivo no es diseñar un theme para este ejemple utilizaré el theme bootstrap disponible en el siguiente enlace.
Nuestra hoja de ruta será la siguiente:
- Configuraremos la librería isotope dentro de nuestro theme.
- Crearemos una vista muy sencilla (título, categorías y body) que utilizaremos como punto de partida.
- Crearemos un pequeño fichero javascript con el código necesario para crear los botones que nos permitan filtrar el contenido.
Incluir librería en nuestro theme
Una buena práctica que seguiremos a la hora de crear nuestros themes será la de crear dentro de cada uno la carpeta ‘vendor’ en la que incluiremos, cada una en su carpeta, todas las librerías externas que utilizaremos en nuestro proyecto.
En nuestro caso descargaremos la librería desde la página web de metafizzy en el siguiente enlace y copiaremos su contenido dentro de ‘vendor/isotope’ en nuestro theme y procederemos a modificar el fichero libraries.yml para incluir esta librería.
isotope:
version: 3.0.3
js:
vendor/isotope/js/isotope.pkgd.min.js: {}
dependencies:
- core/jquery
custom:
version: VERSION
js:
js/custom.js: {}
dependencies:
- core/jquery
Como veréis, también he añadido una librería custom. Esta librería contendrá el fichero con el código javascript necesario para generar los botones con las categorías asignadas a los elementos que nos devuelva la vista.
Para que nuestras librerías se carguen en todas las página tendremos que editar nuestro fichero info.yml y añadiremos las siguientes líneas a la sección ‘libraries’.
libraries:
- 'bootstrap/theme'
- 'bootstrap/isotope'
Para hilar un poco más fino y que nuestras librerías solamente se carguen cuando estemos ejecutando nuestra vista tendremos:
Crear una plantilla twig en nuestro theme para esta vista e incluirla con las siguientes líneas.
{{ attach_library(‘bootstrap/isotope’) }}
{{ attach_library(‘bootstrap/custom’) }}
Incluir una función en el .theme tal y como podéis ver en el siguiente código:
function bootstrap_preprocess_views-view—vista-isotope—page (&$variables) {
$variables[‘#attached’][‘library’][] = ‘bootstrap/isotope’;
$variables[‘#attached’][‘library’][] = ‘bootstrap/custom’;
}
Nuestra función tiene un nombre peculiar y se forma con ‘views-view’--’nombre_vista’--’display’. Si queréis más información sobre como se forman los nombres de estas páginas podéis visitar el siguiente enlace.
Creación de la vista
Crearemos una vista de tipo página con el formato ‘Lista sin formato’ en la que mostraremos ‘Campos’. Solamente necesitaremos como requisito principal que tenga un campo taxonomía en el que se mostrarán las categoría asignadas a cada elemento separadas por una coma y sin ningún tipo de enlace.
Para este ejemplo he utilizado una vista con datos generados mediante el módulo devel con los campos:
- Título
- Categoría
- Body
Con la finalidad de ocultar todos los wrapper que se generan con cada uno de los elementos he ocultado todos los campos a la presentación e incluido un campo ‘Global: Texto Personalizado’ en el que muestro todos los campos con una estructura muy sencilla:
<div class="titulo">{{ title }}</div>
<div class="taxonomias">{{ field_vistas_taxonomia }}</div>
<div class="body">{{ body }}</div>
A cada una de las filas le he añadido las siguientes clases (Formato/Opciones/Clases de Fila) que nos servirá para posicionar tres elementos en cada fila (bootstrap) e ‘item’ para seleccionar los elementos:
item col-xs-6 col-sm-4
La vista tendrá la siguiente clase (Avanzado/Otros/Clase CSS):
vista-isotope
El código html que generará nuestra vista será muy parecido a lo siguiente:
<div class="container-fluid">
<div class="row">
<div class="vista-isotope contextual-region view view-vista-isotope view-id-vista_isotope view-display-id-page_1 js-view-dom-id-ff82bd06d18d29e91628d530c4aeabef6b5f948366648a3d50118b209980e2e1">
<div data-contextual-id="entity.view.edit_form:view=vista_isotope:location=page&name=vista_isotope&display_id=page_1&langcode=es" class="contextual" role="form">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'links__contextual' -->
<!-- FILE NAME SUGGESTIONS:
* links--contextual.html.twig
x links.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/bootstrap/templates/system/links.html.twig' -->
<ul class="contextual-links" hidden=""><li class="config-translationcontextual-linksentityviewconfig-translation-overview"><a href="/drupal8/admin/structure/views/view/vista_isotope/translate?destination=vista-isotope">Traducir vista
en contexto: tipo de entidad vista</a></li><li class="entityviewedit-form"><a href="/drupal8/admin/structure/views/view/vista_isotope/edit/page_1?destination=vista-isotope">Editar vista</a></li></ul>
<!-- END OUTPUT from 'themes/bootstrap/templates/system/links.html.twig' -->
</div>
<div class="view-content">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_unformatted' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-unformatted.html.twig' -->
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/58" hreflang="es">Turpis</a></div>
<div class="taxonomias">jek, ph</div>
<div class="body"><p>Genitus paulatim praemitto. Aptent commoveo gemino hos vel. Consectetuer exerci lenis. Appellatio blandit caecus dignissim genitus jus oppeto utrum velit. Esca molior rusticus si te wisi.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/61" hreflang="es">Turpis</a></div>
<div class="taxonomias">pos</div>
<div class="body"><p>Imputo jugis nostrud nulla paratus quadrum sed valetudo. Acsi aliquip erat nibh roto tation turpis usitas vulputate. Autem eu gilvus nobis pala quidem suscipere vero.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/60" hreflang="es">Velit</a></div>
<div class="taxonomias">ki, sp</div>
<div class="body"><p>At iusto oppeto pagus tego. Camur comis feugiat importunus incassum melior pertineo. Bene cui facilisi haero imputo pala saepius sed validus. Aptent enim ille illum iustum quidem.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/57" hreflang="es">At Patria</a></div>
<div class="taxonomias">ru, ph</div>
<div class="body"><p>Bene persto qui torqueo. Amet camur cogo gemino. Causa jumentum valde. Fere ibidem immitto laoreet lucidus luptatum mos quia. Bene blandit duis obruo.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/64" hreflang="es">Similis</a></div>
<div class="taxonomias">cl, ki, pos</div>
<div class="body"><p>Enim patria suscipere. At eros exputo ille nisl scisco ymo. Erat eu iaceo meus nisl refoveo vulpes. Abbas in pneum. Abico consectetuer gilvus iaceo neo obruo plaga velit.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/65" hreflang="es">Antehabeo Esca Mos Sagaciter</a></div>
<div class="taxonomias">ph, ph</div>
<div class="body"><p>Dolore gemino in laoreet pecus rusticus suscipere usitas. Augue usitas veniam vindico virtus ymo. Comis damnum neque vindico. Adipiscing causa conventio praesent quia tincidunt typicus vel vero.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/66" hreflang="es">Aliquip Amet Hendrerit Nobis</a></div>
<div class="taxonomias">pos, pi, no</div>
<div class="body"><p>Aliquip antehabeo capto eros. Iustum pertineo quidne similis turpis ullamcorper. Cogo nunc vereor volutpat. Molior te uxor voco vulpes. Consectetuer in tamen. Quadrum quibus si.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/55" hreflang="es">Damnum Haero Illum Validus</a></div>
<div class="taxonomias">pi</div>
<div class="body"><p>Esse nimis praemitto. Esca lobortis torqueo uxor volutpat. Lenis sagaciter typicus. Acsi aliquip dolore exerci facilisi secundum uxor veniam. Abigo diam facilisis luctus neo quia veniam.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/63" hreflang="es">Nobis Pertineo Venio</a></div>
<div class="taxonomias">tro, no, jek</div>
<div class="body"><p>Abluo causa eros lucidus quae roto sed valetudo vel. Cui dolus enim feugiat gilvus sino vulpes. Adipiscing commoveo luptatum mauris nobis quae vereor zelus. Cui lobortis nostrud probo.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/56" hreflang="es">Hendrerit Iusto Os Quibus</a></div>
<div class="taxonomias">no, tro</div>
<div class="body"><p>Abdo abluo causa dolus molior tego venio. Acsi consectetuer dignissim mos refoveo. Jus paratus sudo. Enim tego volutpat. Letalis luctus praesent sagaciter tego usitas verto voco zelus.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/59" hreflang="es">Typicus Velit</a></div>
<div class="taxonomias">no, sp</div>
<div class="body"><p>Metuo meus qui ulciscor. Ad antehabeo autem fere paratus te voco. Cogo damnum ibidem luptatum minim occuro uxor vel zelus.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<div class="item col-xs-6 col-sm-4">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_fields' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<div class="titulo"><a href="/drupal8/node/62" hreflang="es">Capto Commoveo Erat Tincidunt</a></div>
<div class="taxonomias">no</div>
<div class="body"><p>Eros luptatum valde. Neo patria torqueo. Camur facilisi gemino magna saepius similis. Abigo amet cui dignissim iusto nulla qui saluto typicus.</p></div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<!-- END OUTPUT from 'core/modules/views/templates/views-view-fields.html.twig' -->
</div>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-unformatted.html.twig' -->
</div>
</div>
</div>
</div>
Como veis, en este código he dejado incluso los comentario que se generan en el modo debug.
Código Javascript
Una vez que creada la vista necesitamos el código javascript que se encargará de recoger todas las categorías asignadas a cada uno de los elementos de la vista para después generar un bloque con botones donde cada uno de ellos se corresponderá a una categoría distinta. Por último enlazaremos un evento click a cada uno de estos botones para que cada vez que pulsemos en él solamente muestre los elementos con esa categoría asignada.
!function($) {
$(document).ready(function() {
(function () {
console.log('Inicio ejecución vista isotope');
// Función que devolverá los elementos únicos de un array
Array.prototype.unique=function(a){
return function(){return this.filter(a)}}(function(a,b,c){return c.indexOf(a,b+1)<0
});
// Función que devolverá el código html de cada uno de los botones
// que filtrará los elementos de la vista
function boton (clase) {
return '<button class="button" data-filter=".'+clase+'">'+clase+'</button>';
}
var item = $('.vista-isotope .item');
var clases = Array();
// Recorremos los elemenos y extraemos sus taxonomías para:
// - Añadirlas a cada elemento como clase. Después las utilizara isotope para filtrar.
// - Las almacenamos en un array para luego generar los botones que filtrarán elementos.
for( var i = 0; i < item.length; i++ ) {
var taxonomias = $(item[i]).find('.taxonomias').html().trim().split(',');
for (var j = 0; j< taxonomias.length; j++) {
taxonomias[j] = taxonomias[j].trim();
$(item[i]).addClass(taxonomias[j]);
clases.push(taxonomias[j]);
}
}
// Elimino taxonomías repetidas
clases = clases.unique();
// Generamos todos lo botones
var botones = Array();
for (var i = 0; i < clases.length; i++) {
botones.push( boton( clases[i]) );
}
// Añadimos el botón que mostrará todos los elementos y el <div> para el wrapper.
botones.unshift( '<button class="button" data-filter="*">Todos</button>' );
botones.unshift('<div class="botones-isotope">');
botones.push('</div>');
// Elimino las comas entre elementos e inserto el bloque justo delante de la vista
$( botones.toString().replace(/,/g, '') ).insertBefore('.vista-isotope');
// Inicializamos isotope
var $vista = $('.vista-isotope').isotope({
// options
itemSelector: '.item',
layoutMode: 'fitRows'
});
// Enlazamos los botones para que filtren por su clase
$('.botones-isotope').on( 'click', 'button', function() {
var filterValue = $(this).attr('data-filter');
console.log(filterValue);
$vista.isotope({ filter: filterValue });
});
console.log('Fin ejecución vista isotope');
})();
});
}(jQuery);
Espero que hayáis disfrutado implementando el plugin isotope sobre una vista en drupal y si tenéis cualquier duda añadir un comentario.
Saludos.