Mostrando entradas con la etiqueta Problemas en Blogger. Mostrar todas las entradas
21 febrero 2012

¿No funciona el enlace de "Responder" de los comentarios anidados? Prueba esta solución


Desde ayer por la tarde, empecé a tener problemas con los comentarios anidados de Blogger: no funcionaba el enlace de "Responder" que aparece debajo de cada uno.

Me extrañó, y empece a preguntar si a otros les pasaba en Google+ y Twitter,  y desde G+, el Potro de Ciudad Blogger me comentaba que desde hace aproximadamente dos semanas, empezó a tener algunos problemas de forma esporádica.

Decidí averiguar un poco, y empecé por el script de los comentarios (me alegra haberlo hecho) y es precisamente en éste donde estaba el problema ya que Blogger lo actualizó y en mi plantilla aparecía sin dicha actualización por ello no funcionaban correctamente.

Si tienes el mismo problema muy probablemente se deba a que no tienes en tu plantilla una actualización que hizo Blogger al código del sistema de comentarios anidados, y tendrás que hacerlo manualmente.


Actualización del script, explicándolo paso a paso

Pasos

Paso 1. Ve a Planilla > Editar HTML.

Paso 2. Estando en el editor del código de tu plantilla, haz click dentro de éste, cuidando no mover nada, luego, hay que buscar el código del script para sustituirlo. Para que sea fácil encontrarlo, nos apoyaremos del buscador del editor, mismo que activamos presionando las tecas ctrl + F (presiona las teclas: "Ctrl" y "F" simultáneamente), luego ponemos en el campo esto: <data:post.commentJso/>" y pulsamos enter.


  <script type='text/javascript'>
    (function() {
      var items =
<data:post.commentJso/>;
      var msgs = <data:post.commentMsgs/>;
      var postId = &#39;<data:post.id/>&#39;;
      var feed = &#39;<data:post.commentFeed/>&#39;;
      var authorName = &#39;<data:post.author/>&#39;;
      var authorUrl = &#39;<data:post.authorUrl/>&#39;;
      var blogId = &#39;<data:top.id/>&#39;;
      var baseUri = &#39;<data:post.commentBase/>&#39;;
      var maxThreadDepth = &#39;<data:post.commentMaxThreadDepth/>&#39;;
// <![CDATA[
      feed += '?alt=json&v=2&orderby=published&reverse=false&max-results=50';
      var cursor = null;
      if (items && items.length > 0) {
        cursor = parseInt(items[items.length - 1].timestamp) + 1;
      }
      var bodyFromEntry = function(entry) {
        if (entry.gd$extendedProperty) {
          for (var k in entry.gd$extendedProperty) {
            if (entry.gd$extendedProperty[k].name == 'blogger.contentRemoved') {
              return '<span class="deleted-comment">' + entry.content.$t + '</span>';
            }
          }
        }
        return entry.content.$t;
      }
      var parse = function(data) {
        cursor = null;
        var comments = [];
        if (data && data.feed && data.feed.entry) {
          for (var i = 0, entry; entry = data.feed.entry[i]; i++) {
            var comment = {};
            // comment ID, parsed out of the original id format
            var id = /blog-(\d+).post-(\d+)/.exec(entry.id.$t);
            comment.id = id ? id[2] : null;
            comment.body = bodyFromEntry(entry);
            comment.timestamp = Date.parse(entry.published.$t) + '';
            if (entry.author && entry.author.constructor === Array) {
              var auth = entry.author[0];
              if (auth) {
                comment.author = {
                  name: (auth.name ? auth.name.$t : undefined),
                  profileUrl: (auth.uri ? auth.uri.$t : undefined),
                  avatarUrl: (auth.gd$image ? auth.gd$image.src : undefined)
                };
              }
            }
            if (entry.link) {
              if (entry.link[2]) {
                comment.link = comment.permalink = entry.link[2].href;
              }
              if (entry.link[3]) {
                var pid = /.*comments\/default\/(\d+)\?.*/.exec(entry.link[3].href);
                if (pid && pid[1]) {
                  comment.parentId = pid[1];
                }
              }
            }
            comment.deleteclass = 'item-control blog-admin';
            if (entry.gd$extendedProperty) {
              for (var k in entry.gd$extendedProperty) {
                console.log(entry.gd$extendedProperty[k].name + ' - ' + entry.gd$extendedProperty[k].value);
                if (entry.gd$extendedProperty[k].name == 'blogger.itemClass') {
                  comment.deleteclass += ' ' + entry.gd$extendedProperty[k].value;
                }
              }
            }
            comments.push(comment);
          }
        }
        return comments;
      };
      var paginator = function(callback) {
        if (hasMore()) {
          var url = feed;
          if (cursor) {
            url += '&published-min=' + new Date(cursor).toISOString();
          }
          window.bloggercomments = function(data) {
            var parsed = parse(data);
            cursor = parsed.length < 50 ? null
                : parseInt(parsed[parsed.length - 1].timestamp) + 1
            callback(parsed);
            window.bloggercomments = null;
          }
          url += '&callback=bloggercomments';
          var script = document.createElement('script');
          script.type = 'text/javascript';
          script.src = url;
          document.getElementsByTagName('head')[0].appendChild(script);
        }
      };
      var hasMore = function() {
        return !!cursor;
      };
      var getMeta = function(key, comment) {
        if ('iswriter' == key) {
          var matches = !!comment.author
              && comment.author.name == authorName
              && comment.author.profileUrl == authorUrl;
          return matches ? 'true' : '';
        } else if ('deletelink' == key) {
          return baseUri + '/delete-comment.g?blogID=' + blogId + '&postID=' + comment.id;
        } else if ('deleteclass' == key) {
          return comment.deleteclass;
        }
        return '';
      };
      var replybox = null;
      var replyUrlParts = null;
      var replyParent = undefined;
      var onReply = function(commentId, domId) {
        if (replybox == null) {
          // lazily cache replybox, and adjust to suit this style:
          replybox = document.getElementById('comment-editor');
          if (replybox != null) {
            replybox.height = '250px';
            replybox.style.display = 'block';
            replyUrlParts = replybox.src.split('#');
          }
        }
        if (replybox && (commentId !== replyParent)) {
          document.getElementById(domId).insertBefore(replybox, null);
          replybox.src = replyUrlParts[0]
              + (commentId ? '&parentID=' + commentId : '')
              + '#' + replyUrlParts[1];
          replyParent = commentId;
        }
      };
      var tok = 'comment-form_';
      var hash = window.location.hash || '';
      var startThread = hash.indexOf(tok) == 1 ? hash.substring(tok.length + 1) : undefined;
      // Configure commenting API:
      var configJso = {
        'maxDepth': maxThreadDepth
      };
      var provider = {
        'id': postId,
        'data': items,
        'loadNext': paginator,
        'hasMore': hasMore,
        'getMeta': getMeta,
        'onReply': onReply,
        'rendered': true,
        'initReplyThread': startThread,
        'config': configJso,
        'messages': msgs
      };
      var render = function() {
        if (window.goog && window.goog.comments) {
          var holder = document.getElementById('comment-holder');
          window.goog.comments.render(holder, provider);
        }
      };
      // render now, or queue to render when library loads:
      if (window.goog && window.goog.comments) {
        render();
      } else {
        window.goog = window.goog || {};
        window.goog.comments = window.goog.comments || {};
        window.goog.comments.loadQueue = window.goog.comments.loadQueue || [];
        window.goog.comments.loadQueue.push(render);
      }
    })();
// ]]>
  </script>


Paso 2. Esa parte que he resaltado de rojo, está dentro del script que vamos a sustituir, mismo que he resaltado de color morado. Es fácil, porque el código está envuelto en una etiqueta <script>. Así que va a empezar con: <script type='text/javascript> y va a terminar con </script>.
Ya que lo encontraste,  lo sustituyes por el siguiente:


  <script type='text/javascript'>
    (function() {
      var items = <data:post.commentJso/>;
      var msgs = <data:post.commentMsgs/>;
      var config = <data:post.commentConfig/>;
// <![CDATA[
      var cursor = null;
      if (items && items.length > 0) {
        cursor = parseInt(items[items.length - 1].timestamp) + 1;
      }
      var bodyFromEntry = function(entry) {
        if (entry.gd$extendedProperty) {
          for (var k in entry.gd$extendedProperty) {
            if (entry.gd$extendedProperty[k].name == 'blogger.contentRemoved') {
              return '<span class="deleted-comment">' + entry.content.$t + '</span>';
            }
          }
        }
        return entry.content.$t;
      }
      var parse = function(data) {
        cursor = null;
        var comments = [];
        if (data && data.feed && data.feed.entry) {
          for (var i = 0, entry; entry = data.feed.entry[i]; i++) {
            var comment = {};
            // comment ID, parsed out of the original id format
            var id = /blog-(\d+).post-(\d+)/.exec(entry.id.$t);
            comment.id = id ? id[2] : null;
            comment.body = bodyFromEntry(entry);
            comment.timestamp = Date.parse(entry.published.$t) + '';
            if (entry.author && entry.author.constructor === Array) {
              var auth = entry.author[0];
              if (auth) {
                comment.author = {
                  name: (auth.name ? auth.name.$t : undefined),
                  profileUrl: (auth.uri ? auth.uri.$t : undefined),
                  avatarUrl: (auth.gd$image ? auth.gd$image.src : undefined)
                };
              }
            }
            if (entry.link) {
              if (entry.link[2]) {
                comment.link = comment.permalink = entry.link[2].href;
              }
              if (entry.link[3]) {
                var pid = /.*comments\/default\/(\d+)\?.*/.exec(entry.link[3].href);
                if (pid && pid[1]) {
                  comment.parentId = pid[1];
                }
              }
            }
            comment.deleteclass = 'item-control blog-admin';
            if (entry.gd$extendedProperty) {
              for (var k in entry.gd$extendedProperty) {
                if (entry.gd$extendedProperty[k].name == 'blogger.itemClass') {
                  comment.deleteclass += ' ' + entry.gd$extendedProperty[k].value;
                }
              }
            }
            comments.push(comment);
          }
        }
        return comments;
      };
      var paginator = function(callback) {
        if (hasMore()) {
          var url = config.feed + '?alt=json&v=2&orderby=published&reverse=false&max-results=50';
          if (cursor) {
            url += '&published-min=' + new Date(cursor).toISOString();
          }
          window.bloggercomments = function(data) {
            var parsed = parse(data);
            cursor = parsed.length < 50 ? null
                : parseInt(parsed[parsed.length - 1].timestamp) + 1
            callback(parsed);
            window.bloggercomments = null;
          }
          url += '&callback=bloggercomments';
          var script = document.createElement('script');
          script.type = 'text/javascript';
          script.src = url;
          document.getElementsByTagName('head')[0].appendChild(script);
        }
      };
      var hasMore = function() {
        return !!cursor;
      };
      var getMeta = function(key, comment) {
        if ('iswriter' == key) {
          var matches = !!comment.author
              && comment.author.name == config.authorName
              && comment.author.profileUrl == config.authorUrl;
          return matches ? 'true' : '';
        } else if ('deletelink' == key) {
          return config.baseUri + '/delete-comment.g?blogID='
               + config.blogId + '&postID=' + comment.id;
        } else if ('deleteclass' == key) {
          return comment.deleteclass;
        }
        return '';
      };
      var replybox = null;
      var replyUrlParts = null;
      var replyParent = undefined;
      var onReply = function(commentId, domId) {
        if (replybox == null) {
          // lazily cache replybox, and adjust to suit this style:
          replybox = document.getElementById('comment-editor');
          if (replybox != null) {
            replybox.height = '250px';
            replybox.style.display = 'block';
            replyUrlParts = replybox.src.split('#');
          }
        }
        if (replybox && (commentId !== replyParent)) {
          document.getElementById(domId).insertBefore(replybox, null);
          replybox.src = replyUrlParts[0]
              + (commentId ? '&parentID=' + commentId : '')
              + '#' + replyUrlParts[1];
          replyParent = commentId;
        }
      };
      var hash = (window.location.hash || '#').substring(1);
      var startThread, targetComment;
      if (/^comment-form_/.test(hash)) {
        startThread = hash.substring('comment-form_'.length);
      } else if (/^c[0-9]+$/.test(hash)) {
        targetComment = hash.substring(1);
      }
      // Configure commenting API:
      var configJso = {
        'maxDepth': config.maxThreadDepth
      };
      var provider = {
        'id': config.postId,
        'data': items,
        'loadNext': paginator,
        'hasMore': hasMore,
        'getMeta': getMeta,
        'onReply': onReply,
        'rendered': true,
        'initComment': targetComment,
        'initReplyThread': startThread,
        'config': configJso,
        'messages': msgs
      };
      var render = function() {
        if (window.goog && window.goog.comments) {
          var holder = document.getElementById('comment-holder');
          window.goog.comments.render(holder, provider);
        }
      };
      // render now, or queue to render when library loads:
      if (window.goog && window.goog.comments) {
        render();
      } else {
        window.goog = window.goog || {};
        window.goog.comments = window.goog.comments || {};
        window.goog.comments.loadQueue = window.goog.comments.loadQueue || [];
        window.goog.comments.loadQueue.push(render);
      }
    })();
// ]]>
  </script>




Nota: El código anterior, lo estoy tomando de una plantilla de Blogger sin editar,  y que ha sido actualizada.

Paso 3. Verifica en vista previa que todo luzca bien, y si es así, guarda los cambios.

¡Y listo! ya habrás actualizado el script para que funcione el enlace de "Responder" de los comentarios anidados.

Espero sea útil. Ya me contarás...


Última actualización:  Febrero 25, 2012.
Seguir leyendo
27 mayo 2011

Cómo solucionar el problema de los botones de compartir de Blogger que no aparecen

Hace tiempo había visto que los botones de compartir que no aparecen en algunas plantillas de Blogger personalizadas. Al parecer, ésto obedece a que Blogger tiene algunos problemas para incorporar las lineas de código que hacen que los botones de compartir aparezcan, cuando las plantillas han sido editadas, o no tienen la estructura de las plantillas nativas.

Recientemente Nymai me comentaba que tenía problemas para habilitar estos botones, tal vez tú también tengas el mismo problema, así que veamos cuál es la solución.

Cómo agregar los botones para compartir entradas de Blogger que no aparecen


  1. Asegúrate de tener activada o marcada la casilla de los botones, para ello, ve a "Diseño", luego haces click en "Editar" en la sección de las entradas, para que se abra la ventana de configuración, y marca la casilla de los botones para compartir, como puedes apreciar en la imagen, y guarda los cambios.
    Botones para compartir entradas de Blogger
  2. Si no aparecen haciendo lo anterior, ve a Plantilla ► Editar HTML, y luego, haz click en el botón "Plantilla de formato".
  3.  Luego, pulsa las teclas Ctrl + F al mismo tiempo, y busca esta linea de código, pegando en el campo de búsqueda (search:), lo que resalté de rojo:

    <div class='post-footer-line post-footer-line-3'>

    Editor de Blogger
    Haz click sobre la imagen para ver detalles.


  4. Inmediatamente después del div de cierre: </div> y que esta resaltado con fondo moradito en la imagen, pega el  siguiente código:
    <div class='post-share-buttons goog-inline-block'>
       <b:if cond='data:post.sharePostUrl'>
          <b:include data='post' name='shareButtons'/>
       </b:if>
    </div>

    Si te fijas en la imagen, he resaltado de fondo morado el div que abre (<div class...) y el div que cierra (</div>),  que corresponden a la linea que te mencionaba en el paso 3. Estos divs coinciden, es decir, se ven alineados, de tal modo que puedes saber cuando empieza y cuando termina. Una vez identificado donde cierra ese div, podemos agregar ahí el código de los botones, para que aparezca en la sección del post-footer (la sección debajo de las entradas) que normalmente viene con fondo de color u otro estilo en la nuevas plantillas de Blogger, y donde también se muestran las etiquetas, número de comentarios, etc.
  5. Verifica en vista previa, y si todo luce bien, guarda los cambios en "Guardar plantilla".

Nota: La linea mencionada en le paso 3, generalmente aparece en todas las plantillas editadas o no, si por alguna razón no la tienes en la plantilla, entonces busca la siguiente linea, y pones el código del paso 4, después de ésta:

<data:post.body/>

La segunda de arriba hacia abajo, ya que la primera corresponde a la versión móvil.

Cómo mostrar los botones, sólo al estar dentro de cada post

Si quieres que los botones se muestren sólo al ingresar a la página de cada post, necesitas agregar cierto código al código que usamos en el paso 4. Entonces, el código del paso 4, quedaría así:

<b:if cond='data:blog.pageType == &quot;item&quot;'>
<div class='post-share-buttons goog-inline-block'>

   <b:if cond='data:post.sharePostUrl'>
      <b:include data='post' name='shareButtons'/>
   </b:if>
</div>
</b:if>

Si te fijas, hemos agregado el código resaltado con azul, que sirve para que cualquier elemento se muestre sólo al estar dentro de cada post o entrada, como sucede con los comentarios.


Fuente: Martha Surfer de Google

Última actualización: 01/Mayo/2013.
Seguir leyendo
28 marzo 2011

Error bX-67oaj1 y la solución


Ayer, antes de cambiar mi plantilla, me dí cuenta que tenía un problema al usar los enlaces de navegación de blogger: entradas antiguas y entradas más recientes,  ya que al navegar desde ahí, se mostraban las entradas sin resumen automático y además sin la fecha.

Me sorprendió un poco ese asunto,  ya que no recordaba haber hecho ningún cambio importante, solo había sustituido el texto del enlace por flechas usando caracteres unicode, eso fue todo; posteriormente cuando cambié la plantilla, el problema continuó, lo que me preocupó o mejor dicho ocupo un buen rato.

Como no tenía una idea clara de que se trataba, fui a ver  toda esa parte del código que corresponde a la navegación de blogger, y lo comparé con el código de una plantilla de blogger sin editar, y que es este... (a veces varía un poco en las lineas que corresponden al enlace de la página principal)

<b:includable id='nextprev'>
  <div class='blog-pager' id='blog-pager'>
    <b:if cond='data:newerPageUrl'>
      <span id='blog-pager-newer-link'>
      <a class='blog-pager-newer-link' expr:href='data:newerPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-newer-link&quot;' expr:title='data:newerPageTitle'><data:newerPageTitle/></a>
      </span>
    </b:if>

    <b:if cond='data:olderPageUrl'>
      <span id='blog-pager-older-link'>
      <a class='blog-pager-older-link' expr:href='data:olderPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-older-link&quot;' expr:title='data:olderPageTitle'><data:olderPageTitle/></a>
      </span>
    </b:if>

    <a class='home-link' expr:href='data:blog.homepageUrl'><data:homeMsg/></a>

  </div>
  <div class='clear'/>
</b:includable>

                                                            
Todo se veía igual,  entonces, buscando respuestas, fui a ver otras de mis plantillas para ver si pasaba lo mismo y en la la plantilla Atheros, también  me encontré con el mismo problema,  (no se muestran los resúmenes en las entradas al navegar desde los enlaces de navegación) .

Luego me di cuenta que en las plantillas Mis dulces tentaciones y la  plantilla papel azul y se generaba un error llamado: bX-67oaj1, al navegar desde dichos enlaces, cosa que me hizo sospechar que mi problema con las entradas tenían que ver con ese susodicho error, ya que también provenía de los enlaces de navegación de Blogger.

Teniendo como base ese error,  y ya sabiendo que buscar, fui al foro de Blogger a ver si había reportes sobre ese problema y encontré muchas comentarios mencionando ese error y una solución  planteada por un usuario.

Probé la solución y si funciona pero, posteriormente en una conversación sostenida con JMiur, me comentó que viendo lo del foro, recordó que hace mucho (2007) ya habían tenido un problema con ese código y ahí explicaba una solución, y leyéndola vi que no era necesario eliminar la clase para cada enlace de navegación como se mostraba en la respuesta del foro que les decía, pues lo probé así como dice JMiur y si funciona perfectamente :) Parece que es un fantasma que regresa del pasado para ponerlos los pelos de punta a más de uno, lo bueno es que existen los casa-fantasmas XD

La solución 


Entonces, el problema se soluciona cambiando:

expr:id='data:widget.instanceId + &quot;_blog-pager-newer-link&quot;' 

 por:

id='blog-pager-newer-link'

y...

expr:id='data:widget.instanceId + &quot;_blog-pager-older-link&quot;'

por:

id='blog-pager-older-link'

...del código que se muestra allá arriba, al hacerlo el problema del error bX-67oaj1 desaparece, y también el problema de las entradas que se muestran sin el resumen automático al navegar desde los enlaces en cuestión, como en el caso de mi plantilla.

 A veces los problemas se arreglan solos o mejor dicho Blogger los soluciona, sin embargo a veces hay que echar de mano algunos truquillos mientras las cosas se arreglan.

Quien sabe desde cuando tenía ese problema aquí en mi blog y yo sin enterarme, afortunadamente ya se arregló, así que cuando vean algo raro al navegar en mi blog (siempre y cuando no sea del diseño o una foto mía... jaja) por favor díganmelo, tal vez sea algún problema y la solución ande por ahí navegando como en este caso XD.

Si tienes resumen automático en la entradas o no, sería bueno que revisaras que todo esta bien al navegar por los enlaces de navegación de blogger, tal vez hay un problema y ni siquiera lo sabes, tal y como me paso a mi,  y si lo hay, y se trata de lo que hablamos, pues la solución ya esta dicha, y desde el 2007.

Nota: Ese código lo verán marcando la casilla de expandir plantillas de artilugios, desde la Edición de HTML de su plantilla y utilicen CTRL F para localizarlo más fácilmente escribiendo una de sus lineas de código.
Seguir leyendo