Showing posts with label Breadcrumb. Show all posts
Showing posts with label Breadcrumb. Show all posts

2017-12-26

Blogger: Sort Breadcrumbs by Label Frequency

日本語»

In my previous post, “Breadcrumb with Structured Data for Blogger”, I mentioned that breadcrumbs are listed in alphabetical order, not showing the actual hierarchy.

If the labels are in a hierarchical (tree) structure, a label at the upper level is used more often than (or equal to) the labels at lower levels. So sorting labels by their frequency order, you can show the breadcrumbs in hierarchical order approximately (except when labels have the same frequency).

In this post, I change the breadcrumbs’ order from alphabetical to labels frequency by JavaScript.

Prerequisites

  • Show the Labels gadget and check “Show number of posts per label” in “Configure Labels”.
  • The label gadget id must be Label1 (normally Label1).
  • The breadcrumb list id must be breadcrumb.
  • The breadcrumb list uses tags <li> and its structured data format is RDFa.

FYI

These prerequisites are based on the following posts.

JavaScript

Insert the following JavaScript just before </body> in Edit HTML.

JavaScript
<script type='text/javascript'>
//<![CDATA[
(function(){
  var label = document.getElementById('Label1');
  if (label == null) return;
  var breadcrumb = document.getElementById('breadcrumb');
  if (breadcrumb == null) return;
  // store label name and count into object
  var labelCounts = {};
  // 'div ul li' is for List, 'div>span' is for Cloud 
  var elms = label.querySelectorAll('div ul li, div>span');
  [].forEach.call(elms, function(elm) {
    if (elm.childElementCount == 2) {
      labelCounts[elm.children[0].innerHTML] = Number(elm.children[1].innerHTML.replace(/[()]/g, ''));
    }
  });
  // sort breadcrumbs by label frequency
  var i = 0;
  [].slice.call(breadcrumb.querySelectorAll('li'))
    .sort(function (a, b) {
      var a = a.textContent.replace(/\r?\n/g, '');
      var b = b.textContent.replace(/\r?\n/g, '');
      if (labelCounts[a] == null || labelCounts[b] == null) return 0;
      if (labelCounts[a] > labelCounts[b]) return -1;
      if (labelCounts[a] < labelCounts[b]) return 1;
    }).forEach(function(li) {
      // set content attribute for RDFa
      pos = li.querySelector('[property="position"]');
      if (pos != null) {
        pos.setAttribute('content', ++i);
      }
      breadcrumb.appendChild(li);
    });
})();
//]]>
</script>

Then, the breadcrumb list is displayed in label frequency order.

Note:

When the labels have the same frequency, the labels are sorted in alphabetical order (not changed).

2017-12-20

Breadcrumbs with Structured Data for Blogger

日本語»

A lot of blogs refer to

Breadcrumb for Blogger - Blogger Widgets

And the original idea is based on

Hoctro’s Archived Blog - Trang Lưu Trữ Học Trò: Archived Post: Adding a Breadcrumb Trail to your Blogger Post

Thank you, Hoktro-san, Aneesh-san. It’s still useful but has the following issues at present.

  • The structured data type definition is based on the obsolete Data-Vocabulary.org, not schema.org.
  • Not using ordered list (<ol> <li>), commonly used for breadcrumbs.

I try to modify these issues.

FYI

1. Add <b:includable>

The modified code snippet of <b:includable> is as follows.
It uses RDFa as a structured data format.

<b:includable id='breadcrumb' var='posts'>
<!-- breadcrumb start -->
<ol id='breadcrumb' typeof='BreadcrumbList' vocab='http://schema.org/'>
<b:if cond='data:blog.homepageUrl != data:blog.url'>
  <li property='itemListElement' typeof='ListItem'>
    <a expr:href='data:blog.homepageUrl' property='item' typeof='WebPage'>
    <span property='name'>Home</span></a>
    <meta content='1' property='position'/>
  </li>
  <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
    <li><data:blog.pageName/></li>
  <b:else/>
    <b:if cond='data:blog.pageType == &quot;item&quot;'>
      <!-- breadcrumb for the post page -->
      <b:loop values='data:posts' var='post'>
        <b:if cond='data:post.labels'>
          <b:loop index='index' values='data:post.labels' var='label'>
          <!-- b:if cond='data:label.isLast == &quot;true&quot;' -->
            <li property='itemListElement' typeof='ListItem'>
              <a expr:href='data:label.url' property='item' typeof='WebPage'>
              <span property='name'><data:label.name/></span></a>
              <meta expr:content='data:index + 2' property='position'/>
            </li>
          <!-- /b:if -->
          </b:loop>
          <li><data:post.title/></li>
        <b:else/>
          <li>Unlabelled</li>
        </b:if>
      </b:loop>
    <b:else/>
      <b:if cond='data:blog.pageType == &quot;archive&quot;'>
        <!-- breadcrumb for the label archive page and search pages.. -->
        <li>Archives for <data:blog.pageName/></li>
      <b:else/>
        <b:if cond='data:blog.pageType == &quot;index&quot;'>
          <b:if cond='data:blog.pageName == &quot;&quot;'>
            <li>All posts</li>
          <b:else/>
            <li>Posts filed under <data:blog.pageName/></li>
          </b:if>
        </b:if>
      </b:if>
    </b:if>
  </b:if>
</b:if>
</ol>
<!-- breadcrumb end -->
</b:includable>

Insert this snippet before <b:includable id='main' var='top'> in Edit HTML.

* I recommend the backup before editing.

Note:

After saving it, the formatter of Edit HTML moves the snippet, as snippets are in an alphabetical order of id, and indent the first line of the snippet.

  • If you comment out <b:if cond='data:blog.homepageUrl != data:blog.url'> and end-tag </b:div>, you can display the breadcrumb trail at all times including top page.
  • If you comment in <!-- b:if cond='data:label.isLast == &quot;true&quot;' --> and <!-- /b:if -->, the breadcrumbs include only the last label (in alphabetical order).
    (When you use more than one label, labels are sorted forcibly in alphabetical order.)

Usage of Search Function in Edit HTML

In Edit HTML, press Ctrl + F keys, then search box is displayed in upper right corner.
Input the search string and press Enter key. Each time press Enter key, the cursor jumps to the next match.

2. Add <b:include>

Next, insert the following widget tag for display before the part of <b:include data='top' name='status-message'/>.

<b:include data='posts' name='breadcrumb'/> 
  • If you put it just before </div> corresponding to <div class='blog-posts hfeed'>, the breadcrumb list is placed at the bottom of the page.
  • If you put it before <b:if cond='!data:mobile'>, the breadcrumb list can be shown in mobile pages as well.

3. Add CSS

Finally, add CSS as follows. Please modify as needed.

/* breadcrumb */
ol#breadcrumb{
    font-size:13px;
    padding: 8px;
}
#breadcrumb li {
    display: inline;
    list-style-type: none;
}
#breadcrumb li:after {
    content: " > ";
}
#breadcrumb li:last-child:after {
    content: none;
}

It’s all done.

Structured Data Testing Tool

You can check whether the breadcrumb list is working properly with Google Structured Data Testing Tool.

You must input URLs showing breadcrumbs.

You may find some errors in BlogPosting (not breadCrumbList).
You don’t have to care about it unless you want to reflect these error items correctly to search results. See Structured Data testing Tool errors on Blogpost Blogger - Google Product Forum.

If you want to fix them, this site may help you.

Remaining issue

Breadcrumbs are listed in alphabetical order, not showing the actual hierarchy.
To be continued in Blogger: Sort Breadcrumbs by Label Frequency.