2012-11-15T23:14:00+01:00

Gadget de Calendario para Blogger

Estrenamos un gadget nuevo en el blog, algo que hacía tiempo buscaba: un calendario, similar al que te ofrece WordPress, donde los días con entradas vengan marcados de alguna forma especial y pinchando sobre ellos te lleve a la entrada o entradas de ese día.
Se que parece una tontería, que hacer un calendario en una página web es fácil, pero la verdad es que hacerlo en blogger y que cada día que tenga entradas puedas enlazarlas en el calendario no resulta tan simple.
Al final acabé utilizando las librerías de siempre, las que me solucionan mil y un problemas, DOJO for ever!!

Voy a intentar explicar un poco el proceso, habitualmente me explico como un libro cerrado pero espero que sirva de ayuda para quién busque algo similar.

No hay que montar ni configurar en el blog ningún tipo de Archivo o similar, directamente se cargarán las 1.000 últimas entradas del diario (creo que son más que suficientes, al menos en mi caso) y probado en Internet Explorer Versión 8.0, Chrome Versión 23.0, Opera 12.10 y FireFox 3.6.28 funciona sin aparentemente problemas.

Lo más importante de todo es que antes de empezar saquemos una COPIA DE LA PLANTILLA, por si hacemos algo mal y hay que recuperar el diseño.
Lo siguiente es editar la plantilla del blog, en la forma habitual de hacerla y marcando la casilla de Expandir plantillas de artilugios (ver unos volcados de pantalla en un post antiguo).
Buscamos el tag HTML </head> y justo antes de él colocamos el siguiente código (que es el encargado de crear el calendario con las entradas).

Si es la primera vez que utilizamos DOJO en nuestro blog, ni la hoja de estilo CSS ni la librería estarán cargadas, con lo que pondremos las dos líneas siguientes. Si ya están cargadas podemos ignorarlas.

<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dijit/themes/nihilo/nihilo.css"/>
<script data-dojo-config='async: false, parseOnLoad:true' src='http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js'/>

<!-- Definicions de funcions pel calendari de entrades. -->
<script type="text/javascript">
// <![CDATA[
function createCalendar(root)
{
  var objEntries=root.feed.entry;
  var jsonObj, Year, Month, Day, href, titleText;
  var entry, published, updated;
  var objDate;
  var urlBlog='http://www.nekofan.net.ms/search';
  var calendarNodeName='calendarContainer';
  var url, publishedMin, publishedMax;

  document._globalFeedsObject={};
  for (var I=0;I<objEntries.length;I++)
  {
    entry=objEntries[I];
    published=entry.published.$t;
    updated=entry.updated.$t;
    href='';
    titleText='';
    objDate=new Date(published);
    if (!isNaN(objDate))
      {
         Year=''+objDate.getFullYear();
         Month=''+(objDate.getMonth()+1);
         Day=''+objDate.getDate();
      } else {
               Year=published.split('-')[0];
               Month=published.split('-')[1];
               Day=(published.split('-')[2]).substring(0,2);
             }
    if (Month.length<2) Month='0'+Month;
    if (Day.length<2) Day='0'+Day;
    
    dateText=Year+'_'+Month+'_'+Day;
    for (var J=0;J<entry.link.length;J++)
      {
        if (entry.link[J].rel=='alternate') { href=entry.link[J].href; titleText=entry.link[J].title; }
      }
    if (href!='')
    {
      jsonObj={title: titleText, url: href, pub: published, upd: updated};
      var pp=document._globalFeedsObject[dateText];
      if (typeof pp != 'undefined')
        {
         publishedMin=''+Year+'-'+Month+'-'+Day+'T00:00:00-01:00';
         publishedMax=''+Year+'-'+Month+'-'+Day+'T23:59:59-01:00';
         url=urlBlog+'?updated-min='+publishedMin+'&updated-max='+publishedMax+'&orderby=published&by-date=true';
        
         jsonObj={title:'Ver entradas del día', url: url, pub:'', upd: ''};
        }
      document._globalFeedsObject[dateText]=jsonObj;
    }
  }
  require(['dojo/ready','dijit/Calendar','dojo/dom'],
           function(ready,Calendar,dom){
             ready(function(){createCalendarWithEntries(calendarNodeName);});
           }
         );
}
function createCalendarWithEntries(nodus)
{
   var calendarNodeName=nodus;
   var ejson=document._globalFeedsObject;

   var calendarProps={};
   calendarProps.isDisabledDate= function(d){
                                var dd=new Date(d);
                                var dei=''+dd.getDate();
                                var monz=''+(dd.getMonth()+1);
                                if (dei.length<2) dei='0'+dei;
                                if (monz.length<2) monz='0'+monz;
                                var ddd=dd.getFullYear()+'_'+monz+'_'+dei;
                                return !ejson[ddd];
                              }
   var cal=new dijit.Calendar(calendarProps, dojo.byId(calendarNodeName));
   cal.monthWidget.old_setMonthAttr=cal.monthWidget._setMonthAttr;
   cal.entriesJSON=ejson;
   cal.connect(cal.monthWidget,'_setMonthAttr', function(value) {setDaysWithEntries(calendarNodeName,value);cal.monthWidget.old_setMonthAttr(value);});
   setDaysWithEntries(calendarNodeName);
}
function setDaysWithEntries(calendarNode,dateSelected)
{
   var cal=dijit.byId(calendarNode);
   var dateLabels=cal.dateLabels;
   var start=-1,end=-1;
   var selectedDate=(!dateSelected?cal.get('value'):dateSelected);
   var entriesJSON=cal.entriesJSON;
   var Day,Month,Year;
   
     
     if (!selectedDate) selectedDate=new Date();
     Day=selectedDate.getDate();
     Month=''+(selectedDate.getMonth()+1);
     if (Month.length<2) Month='0'+Month;
     Year=selectedDate.getFullYear();

     for(var I=0;I<dateLabels.length;I++)
     {
        if ((parseInt(dateLabels[I].innerHTML)=='1') && (start==-1)) start=I;
        if ((parseInt(dateLabels[I].innerHTML)>=28) && (start!=-1)) end=I;
     }
     for (var I=start; I<=end; I++)
     {
       var dayTag=dateLabels[I];
       var dayText=''+parseInt(dayTag.innerHTML);
       var publishedMin, publishedMax;
       var url;
       
       if (dayText.length<2) dayText='0'+dayText;
       if (entriesJSON[Year+'_'+Month+'_'+dayText])
       {
         publishedMin=''+Year+'-'+Month+'-'+dayText+'T00:00:00-01:00';
         publishedMax=''+Year+'-'+Month+'-'+dayText+'T23:59:59-01:00';
         
         title=entriesJSON[Year+'_'+Month+'_'+dayText].title;
         url=entriesJSON[Year+'_'+Month+'_'+dayText].url;

         dayTag.innerHTML='<a href="#" onclick="location.href=\''+url+'\'" alt="" title="'+title+'">'+parseInt(dayText)+'</a>';
       }
     }
}
// Final Codi Calendari.
// ]]>
</script>

<!-- Definicions d'estil pel calendari de entrades. -->
<style type="text/css">
    .nihilo table.dijitCalendarContainer
    {
        font-family: Verdana, Tahoma, Arial;
        font-size: 9pt;
        font-weight: normal;
        /*margin: 25px auto;*/
        width:100%;
        border: 1px solid #615D5D;
    }
    .nihilo .dijitCalendarMonthLabel 
    {
        font-weight: bold;
        text-align: center;
        font-family: Verdana;
        font-size: 10pt;
        color: #ffffff !important;
    }
    .nihilo .dijitCalendarDateTemplate
    {
        cursor: default;
        font-size: inherit;
        font-weight: normal;
        background-color: #292625 !important;
        border:solid 1px #292625 !important;
    }
    .nihilo .dijitCalendarDisabledDate 
    {
        text-decoration: none !important;
    }
    .nihilo .dijitCalendarDateTemplate a
    {
        text-decoration: none;
        font-weight:bold;
    }
    .nihilo .dijitCalendarCurrentDate 
    {
        text-decoration: none;
        /*color: #339900;*/
        font-weight: bold;
    }
    .nihilo .dijitCalendarPreviousMonth, .nihilo .dijitCalendarNextMonth
    {
        background-color: #3d3d3d !important;
        border: #3d3d3d solid 1px !important;
    }
    .nihilo .dijitCalendarSelectedDate 
    {
        font-weight: bold;
    }
    .nihilo .dijitCalendarMonthContainer
    {
    }
    .nihilo .dijitCalendarMonthContainer th 
    {
        background: #292625;
        color: white !important;
    }
    .nihilo .dijitMenu, .nihilo .dijitMenuBar
    {
        /*background-color: #393636;*/
    }
    .nihilo .dijitCalendarMonthMenu
    {
        background-color: #292625;
    }
    .nihilo .dijitCalendarYearContainer
    {
        background-color: #292625 !important;
        background-image: none !important;
    }
    .nihilo .dijitCalendarYearLabel
    {
      border-top: solid 1px #615D5D;
    }
    .nihilo .dijitCalendarNextYear, .nihilo .dijitCalendarPreviousYear
    {
      color: #b29d85 !important;
    }
    .nihilo .dijitCalendarSelectedYear
    {
      background-color: #FCB03E !important;
      border: solid 1px #FFE284 !important;
      -moz-border-radius: 0.35em;
      -webkit-border-radius: 0.35em;
      -goog-ms-border-radius: 0.35em;
      border-radius: 0.35em;
    }
    .nihilo .dijitCalendarDayLabelTemplate
    {
      background-color: #292625 !important;
      background-image: none !important;
      color: #B29D85;
      border-top: solid 1px #393636;
      border-bottom: solid 1px #615D5D;
    }
    .nihilo .dijitCalendarMonthMenu .dijitCalendarMonthLabelHover
    {
       color: #393636 !important;
    }
    .nihilo .dijitCalendar .dijitButtonNode
    {
       border: solid 1px #615D5D !important;
    }
</style>

Veamos las funciones una a una:
  • createCalendar: es la encargada de crear el calendario en sí. Recibe la lista de entradas y hemos de modificar las variables urlBlog y calendarNodeName por la dirección de nuestro blog y el nombre del contenedor donde poner el calendario.
  • createCalendarWithEntries: es la encargada de crear el objeto calendario e inhabilitar los días que no tienen entradas.
  • setDaysWithEntries: Establece los link a los días con entradas para el mes/año que muestra el calendario.
Además, se define también el estilo del calendario definiendo sus propiedades CSS, con nombres que creo son bastante aclaratorios, por lo que obviaré el describir cada clase.

Sin embargo, hasta ahora solo hemos definido los estilos y funciones para crear el calendario, pero no lo hemos usado. Para ello, guardamos los cambios efectuados y cerramos todo hasta volver al panel de control de nuestro blog en blogger, seleccionamos el apartado de Diseño, y en la zona donde queramos poner el calendario le damos al enlace de Añadir un gadget, escogiendo el de HTML/Javascript.
En la ventana que nos aparece, tan solo debemos insertar el siguiente código HTML:
<div id="calendarContainer">
  <script src="http://nekofan.net.ms/feeds/posts/summary?max-results=1000&amp;alt=json-in-script&amp;callback=createCalendar" type="text/javascript"></script>
</div>
sustituyendo el nombre del blog por el apropiado.
Esta llamada carga las mil últimas entradas en una variable de tipo JSON y la utiliza como parámetro para llamar a la función definida en callback, que en nuestro caso es la definida previamente en los pasos anteriores.

Bien, si se ha colocado todo correctamente el resultado debería ser un calendario como el que veis en este blog, en el lateral derecho.

Para evitar copiar tanto código, dejo todo en un archivo de texto en el enlace del final, espero que sea de utilidad, quien lo quiera utilizar no hace falta que ponga la fuente, ni agradecimientos a Sammy (ni nada por el estilo), puede modificar el código a su gusto, etc. etc.

En un futuro, espero que no muy lejano, intentaré incrustar todo el código en un único gadget que pueda ser cargado facilmente desde blogger en el apartado de diseño, mientras tanto hay que trabajarlo un poco para poder añadirlo al blog deseado.

Larga Vida y Prosperidad.

2 comentarios:

  1. Hola! que tengo que modificar en el código para que en el calendario me salgan solo entradas de una determinada etiqueta?

    ResponderEliminar
  2. Si solo quieres mostrar una determinada etiqueta deberás cambiar la parte de

    src="http:///feeds/posts/summary?max-results=1000&alt=json-in-script&callback=createCalendar" type="text/javascript"

    por

    src="http:///feeds/posts/default/-/?max-results=6&amp;orderby=published&amp;alt=json-in-script&amp;callback=createCalendar" type="text/javascript"

    Creo que te funcionará.
    Ya me dirás

    Salu2

    ResponderEliminar

Sobre NekoFan

Dos cuartas partes de "Anime",una de Japón y otra de videojuegos,mezclado con programación y Dojo hacen la receta (im)perfecta de este blog.




Enlaces

Visitas