IT the Best

はてなブログのカスタマイズ情報を中心に、WEBデザインからJavaScriptまでWEB系の開発情報を発信します。便利ツールや暇つぶしのゲームなど開発物も公開します。

はてなブログのカテゴリーとパンくずリストを階層化表示にする -SEOに効果あり- #カテゴリーの表示を変える

f:id:Surprisedblog:20190619185106j:plain


初期Scriptファイルのため、不備などがありあまり参考になりません。

 

新しく、カテゴリー・パンくずリストを階層化表示にする機能を作成しました。こちらの方が扱いやすく、不具合が起こる可能性も低いと思われます。

www.it-the-best.com

ほとんどの機能変更はありませんが、パンくずリストの区切り文字や階層化させるカテゴリーリストの選択など新たに独自カスタマイズができるようになりました。すべてのコードを見直し約5千行省略したためほんの少しですが軽くなりました。
しかし、大きな変更点として新しいScriptコード(ファイル)では、最初に表示されているカテゴリーをパンくずリストに表示するようにしました。
また、新しく投稿した記事の方がスマホからのカスタマイズも容易です。

 

 

当記事は、階層カテゴリーを表示するために開発したJavaScriptファイルの説明になります。#カテゴリーの表示を変える

https://cdn.it-the-best.com/js/category/2.2/category.min.jsの説明

 

www.it-the-best.com

カテゴリーの表示を変える 

 カテゴリーが表示される主な場所

・カテゴリータグ:記事一覧、記事内

・カテゴリーリスト:カテゴリー一覧、パンくずリスト

カテゴリー情報を取得する

 ほとんどのページで表示されるカテゴリーの要素は、クラスに"category-[カテゴリー名]"というクラス名を持っています。例)class="category-HTML"

var categories_list=$("[class*='category-']")

階層化カテゴリータグを表示させない

 記事にサブカテゴリーを追加しただけでは、ハイフンを含めたカテゴリータグが表示されてしまうので、カテゴリーの表示全てを変更します。

var categories_list=$("[class*='category-']")//カテゴリー要素を取得
    for (var element of categories_list) {
        if (element.tagName !== "BODY" && element.className.match(/ category-[\w].*-| category-[\W].*[\W].*-/)) {//"、'などの記号で始まるものは対象外
            element.style.display="none"//階層化カテゴリーを非表示にする
        }
    }

簡略

$("[class*='category-']").each(function (index, element) {
        if (element.tagName !== "BODY" && element.className.match(/ category-[\w].*-| category-[\W].*[\W].*-/)) {
            element.style.display = "none"//階層化カテゴリーを非表示にする
        }
    })

階層化カテゴリーの表示を変える

 表示を変えるために階層化カテゴリーリストを作ります。 

  すべてのカテゴリーを取得

まず、すべてのカテゴリーを取得します。

var m_clist = [], s_clist = [], clist = [], m_clist_json = {}
//カテゴリー一覧のカテゴリー名をすべて取得・階層化カテゴリーを非表示
function getcategorylist_hiddencategory() {
    $(".hatena-module-category ul").each(function (index, element) {
        for (var e of element.children) {
            var categoryname = e.children[0].innerText
            var re = categoryname.match(/ [\W]\d*[\W]$/g)
            categoryname = categoryname.replace(re, "")
            if (clist.indexOf(categoryname) < 0) {
                add_category_list(categoryname)
            }
        }
    })
    if (m_clist == "") { return }
    Organize_mcl(m_clist)
}
//カテゴリーリストに追加する
function add_category_list(categoryname) {
    clist.push(categoryname)
    if (categoryname.match(/^[\w].*-|^[\W].*[\W].*-/)) {
        m_clist.push(categoryname)//サブカテゴリーを含むカテゴリー
    } else {
        s_clist.push(categoryname)//独立カテゴリー
    }
}
//カテゴリーを整理する
function Organize_mcl(destination_list) {
    var list = destination_list
    var num = []
    for (var i of list) {
        var i_clist = sorting_categories(i)
        for (var i2 of list) {
            var len = i_clist.length
            var len_list = i
            if (i == i2) { continue }
            var i2_clist = sorting_categories(i2)
            if (i_clist.length > i2_clist.length) {
                len = i2_clist.length
                len_list = i2
            }
            var push_flag = false
            for (let k = 0; k < len; k++) {
                if (i_clist[k] === i2_clist[k]) {
                    push_flag = true
                } else {
                    push_flag = false
                    break
                }
            }
            if (push_flag) {
                if (num.indexOf(len_list) < 0) {
                    num.push(len_list)
                }
            }
        }
    }
    for (let n of num) {
        list.splice(list.indexOf(n), 1)
    }
}

階層化カテゴリー用のjsonデータを作成

//階層化カテゴリー用のjsonデータ作成
function createjson_for_hierarchy(list, json) {
    for (let i = 0; i < list.length; i++) {
        var cn_1 = list[i]
        var cnlist_1 = sorting_categories(cn_1)
        try {
            var P = sorting_categories(json[cnlist_1[0]][0])[0]
            if (P == cnlist_1[0]) {
                continue
            }
        } catch (error) { }
        for (let k = i + 1; k < list.length; k++) {
            var cn_2 = list[k]
            var cnlist_2 = sorting_categories(cn_2)
            if (cnlist_1[0] == cnlist_2[0]) {
                if (json[cnlist_1[0]]) {
                    json[cnlist_1[0]].push(cn_2)
                } else {
                    json[cnlist_1[0]] = [cn_1, cn_2]
                }
            }
        }
    }
}
// カテゴリーを仕分けする
function sorting_categories(str) {
    var cs_list = [], cs = ""
    var flag = true
    for (var s of str) {
        if (s == "'" || s == '"') {
            flag = !flag
        }
        if (flag && s == "-") {
            cs_list.push(cs)
            cs = ""
        } else {
            cs = cs + s
        }
    }
    cs_list.push(cs)
    return cs_list
}
 カテゴリー一覧(階層化表示にする)

 カテゴリー一覧を、階層化カテゴリーリストをもとに階層化表示にします。

//カテゴリー一覧の表示を変える
function Change_display_categorylist() {
    var Pc_list = []
    for (var mc of m_clist) {
        var list = sorting_categories(mc)
        var P = list[0]
        $(".hatena-module-category ul").each(function (index, element) {
            for (var e of element.children) {
                var categoryname = e.children[0].innerText
                var re = categoryname.match(/ [\W]\d*[\W]$/g)
                categoryname = categoryname.replace(re, "")
                for (var i of list) {
                    if (i == categoryname && e.className.indexOf("descendant-li") < 0) {
                        e.style.display = "none"
                        e.style.borderTop = "0px"
                    }
                }
                //階層カテゴリの最上位と同じカテゴリ
                if (P == categoryname && Pc_list.indexOf(sorting_categories(mc)[0]) < 0) {
                    Create_Element_categorylist(mc, e, re)
                    Pc_list.push(sorting_categories(mc)[0])
                    //階層カテゴリの最上位と同じカテゴリ名のリスト項目の非表示
                    e.style.display = "none"
                }
            }
        })
    }
    hidden_categorylist_d()
}
function hidden_categorylist_d() {
    $(".hatena-module-category ul").each(function (index, element) {
        for (var e of element.children) {
            var categoryname = e.children[0].innerText
            var re = categoryname.match(/ [\W]\d*[\W]$/g)
            categoryname = categoryname.replace(re, "")
            //階層化カテゴリーを非表示にする
            if (categoryname.match(/^[\w].*-|^[\W].*[\W].*-/)) {
                e.style.display = "none"
                e.style.borderTop = "0px"
            }
        }
    })
}
// 階層化カテゴリーリストの要素を作る
function Create_Element_categorylist(categoryname, element, cnum) {
    var cn_list = sorting_categories(categoryname)
    var li = document.createElement("li")
    li.classList.add("descendant-li", "descendant-li-" + cn_list[0])
    element.parentNode.insertBefore(li, element.nextSibling);
    var a = document.createElement("a")
    a.classList.add("categoryname")
    a.innerText = cn_list[0] + cnum
    a.href = location.origin + "/archive/category/" + cn_list[0]
    li.append(a)
    var span = document.createElement("span")
    span.classList.add("icon-arrow-down")
    a.after(span)
    element = li
    var m_cname = cn_list[0]
    for (let i = 1; i < cn_list.length; i++) {
        var c = cn_list[i]
        m_cname = m_cname + "-" + c
        element = form_dc_element(c, element, m_cname)
    }
    //階層がわかれる場合
    if (m_clist_json[cn_list[0]]) {
        for (var cname of m_clist_json[cn_list[0]]) {
            element = li
            var cname_list = sorting_categories(cname)
            var m_cname = cn_list[0]
            for (let i = 1; i < cname_list.length; i++) {
                var c = cname_list[i]
                m_cname = m_cname + "-" + c
                var li_ele = document.getElementsByClassName("descendant-li-" + m_cname)
                if (li_ele.length > 0) {//すでにある場合
                    element = li_ele[0]
                } else {
                    element = form_dc_element(c, element, m_cname)
                }
            }
            try {
                bottompotch_hidden(element)
            } catch (error) {
                element.each(function (index, e) {
                    bottompotch_hidden(e)
                })
            }
        }
    } else {
        bottompotch_hidden(element)
    }
}
//リスト項目エレメントの生成
function form_dc_element(categoryname, topelement, fq_cname) {
    var num = get_contentnum(fq_cname)
    var ul = document.createElement("ul")
    ul.classList.add("descendant-ul")
    topelement.append(ul)
    var li = document.createElement("li")
    li.classList.add("descendant-li", "descendant-li-" + fq_cname)
    ul.append(li)
    var a = document.createElement("a")
    a.classList.add("categoryname")
    a.innerText = categoryname + num
    //a.style.display = "none"
    a.href = location.origin + "/archive/category/" + fq_cname
    li.append(a)
    var span = document.createElement("span")
    span.classList.add("icon-arrow-right")
    a.before(span)
    return li
}
//bottomカテゴリーのポッチをなくす
function bottompotch_hidden(element) {
    for (var e of element.children) {
        if (e.tagName == "A") {
            e.style.display = "block"
        } else {
            e.style.display = "none"
        }
    }
}
//カテゴリーの記事数を取得する
function get_contentnum(categoryname) {
    var number
    $(".hatena-module-category ul").each(function (index, element) {
        for (var e of element.children) {
            var c = e.children[0].innerText
            var re = c.match(/ [\W]\d*[\W]$/g)
            c = c.replace(re, "")
            if (categoryname == c) {
                number = re
            }
        }
    })
    return number
}

 クリック・タッチイベントの設定

//click/touch eventを設定
function set_event() {
    var ua = navigator.userAgent
    if (ua.match(/iphone|ipod|ipad|android/i)) {
        //タッチデバイスの場合
        set_event_touchdevice()   
    }
    else {
        // PCの場合
        set_event_pc()
    }
}
//pc
function set_event_pc() {
    var target = document.getElementsByClassName("icon-arrow-right")
    for (var i of target) {
        i.addEventListener("click", function (e) {
            for (var c of e.target.parentNode.children) {
                if (c.tagName == "UL") {
                    if (c.style.display == "block" && e.target.className.indexOf("icon-arrow-right") >= 0) {
                        c.style.display = "none"
                        e.target.classList.remove("icon-arrow-right-down")
                    } else {
                        c.style.display = "block"
                        e.target.classList.add("icon-arrow-right-down")
                    }
                }
            }
        })
    }
    var target = document.getElementsByClassName("icon-arrow-down")
    for (var i of target) {
        i.addEventListener("click", function (e) {
            for (var c of e.target.parentNode.children) {
                if (c.tagName == "UL") {
                    if (c.style.display == "block" && e.target.className.indexOf("icon-arrow-down") >= 0) {
                        c.style.display = "none"
                        e.target.classList.remove("icon-arrow-down-up")
                    } else {
                        c.style.display = "block"
                        e.target.classList.add("icon-arrow-down-up")
                    }
                }
            }
        })
    }
    var target = document.getElementsByClassName("descendant-li")
    for (var i of target) {
        i.addEventListener("click", function (e) {
            for (var c of e.target.children) {
                if (c.tagName == "SPAN" && c.className.indexOf("icon-arrow-down") >= 0) {
                    if (c.className.indexOf("icon-arrow-down-up") < 0) {
                        c.classList.add("icon-arrow-down-up")
                    } else {
                        c.classList.remove("icon-arrow-down-up")
                    }
                }
                else if (c.tagName == "UL") {
                    if (c.style.display == "block") {
                        c.style.display = "none"
                    } else {
                        c.style.display = "block"
                    }
                }
            }
        })
    }
    var target = document.getElementsByClassName("descendant-ul")
    for (var i of target) {
        i.addEventListener("click", function (e) {
            var ctag = ""
            for (var c of e.target.children) {
                if (c.tagName == "SPAN" && c.className.indexOf("icon-arrow-right") >= 0) {
                    ctag = c
                }
                else if (c.tagName == "UL") {
                    if (c.style.display == "block") {
                        c.style.display = "none"
                        ctag.classList.add("icon-arrow-right-down")
                    } else {
                        c.style.display = "block"
                        ctag.classList.remove("icon-arrow-right-down")
                    }
                }
            }
        })
    }
}
//touchdevice
function set_event_touchdevice() {
    var touch_flag=false
    var target = document.getElementsByClassName("descendant-li")
    for (var i of target) {
        i.addEventListener("touchstart",touch_start,false)
        i.addEventListener("touchmove",touch_move,false)
        i.addEventListener("touchend", function (e) {
            if(!touch_flag){return}
            for (var c of e.target.children) {
                if (c.tagName == "SPAN" && c.className.indexOf("icon-arrow-down") >= 0) {
                    if (c.className.indexOf("icon-arrow-down-up") < 0) {
                        c.classList.add("icon-arrow-down-up")
                    } else {
                        c.classList.remove("icon-arrow-down-up")
                    }
                }
                else if (c.tagName == "SPAN" && c.className.indexOf("icon-arrow-right") >= 0) {
                    if (c.className.indexOf("icon-arrow-right-down") < 0) {
                        c.classList.add("icon-arrow-right-down")
                    } else {
                        c.classList.remove("icon-arrow-right-down")
                    }
                }
                else if (c.tagName == "UL") {
                    if (c.style.display == "block") {
                        c.style.display = "none"
                    } else {
                        c.style.display = "block"
                    }
                }
            }
            touch_flag=false
        },false)
    }
    function touch_start(){
        touch_flag=true
    }
    function touch_move(){
        touch_flag=false
    }
}
  カテゴリータイトルの表示を変える
//カテゴリータイトル名の階層化表示
function change_categoryname_title() {
    var categoryname = false
    $(".archive-header-category h2").each(function (i, e) {
        categoryname = e.innerText
        var category_list = sorting_categories(e.innerText)
        if (category_list.length == 1) { return }
        var category_title, category_htitle, count = 0
        e.innerText = null
        for (var c of category_list) {
            count = count + 1
            if (count == 1) {
                category_htitle = c
                category_title = c
            } else {
                category_htitle = category_htitle + " > " + c
                category_title = category_title + "-" + c
            }
            var a = document.createElement("a")
            a.classList.add("archive-header-d-categoryname")
            a.href = location.origin + "/archive/category/" + category_title
            a.innerText = c
            e.append(a)
            if (category_list.length !== count) {
                var span = document.createElement("span")
                span.classList.add("archive-header-d-categoryname", "breadcrumb-gt")
                span.innerText = ">"
                e.append(span)
            }
        }
        var span = document.createElement("span")
        span.innerText = category_htitle
        span.classList.add("archive-header-categoryname")
        span.style.display = "none"
        e.insertBefore(span, e.firstChild)
        /*$("header .archive-header-d-categoryname").css({
            "display":"none"
        })*/
    })
    if (!categoryname) { return }
    /*パンくずリストを表示*/
    var breadcategoryname = categoryname
    var bc_list = sorting_categories(breadcategoryname)
    var ol = document.createElement("ol")
    ol.setAttribute("itemscope", "")
    ol.setAttribute("itemtype", "https://schema.org/BreadcrumbList")
    //homeを追加
    var li = document.createElement("li")
    li.setAttribute("itemprop", "itemListElement")
    li.setAttribute("itemscope", "")
    li.setAttribute("itemtype", "https://schema.org/ListItem")
    ol.append(li)
    var a = document.createElement("a")
    a.setAttribute("itemtype", "https://schema.org/Thing")
    a.setAttribute("itemprop", "item")
    a.setAttribute("href", location.origin)
    li.append(a)
    var span = document.createElement("span")
    span.setAttribute("itemprop", "name")
    span.innerText = "トップ"
    a.append(span)
    var meta = document.createElement("meta")
    meta.setAttribute("itemprop", "position")
    meta.setAttribute("content", 1)
    li.append(meta)
    var span = document.createElement("span")
    span.innerText = ">"
    span.classList.add("breadcrumb-gt")
    ol.append(span)
    //jsonデータ作成
    var breadcrumb_json = {}
    breadcrumb_json["@context"] = "https://schema.org"
    breadcrumb_json["@type"] = "BreadcrumbList"
    breadcrumb_json["itemListElement"] = []
    var json = {}
    //jsonデータ追加
    json["@type"] = "ListItem"
    json["position"] = 1
    json["name"] = "トップ"
    json["item"] = location.origin
    breadcrumb_json["itemListElement"].push(json)
    for (let i = 0; i < bc_list.length; i++) {
        var bc = bc_list[0]
        if (i !== 0) {
            for (let k = 1; k < i + 1; k++) {
                bc = bc + "-" + bc_list[k]
            }
        }
        var li = document.createElement("li")
        li.setAttribute("itemprop", "itemListElement")
        li.setAttribute("itemscope", "")
        li.setAttribute("itemtype", "https://schema.org/ListItem")
        ol.append(li)
        //Myblog情報
        var a = document.createElement("a")
        a.setAttribute("itemtype", "https://schema.org/Thing")
        a.setAttribute("itemprop", "item")
        a.setAttribute("href", location.origin + "/archive/category/" + bc)
        li.append(a)
        var span = document.createElement("span")
        span.setAttribute("itemprop", "name")
        span.innerText = bc_list[i]
        a.append(span)
        var meta = document.createElement("meta")
        meta.setAttribute("itemprop", "position")
        meta.setAttribute("content", i + 2)
        li.append(meta)
        if (bc_list.length - 1 !== i) {
            var span = document.createElement("span")
            span.innerText = ">"
            span.classList.add("breadcrumb-gt")
            li.append(span)
        }
        //jsonデータ追加
        var json = {}
        json["@type"] = "ListItem"
        json["position"] = i + 2
        json["name"] = bc_list[i]
        json["item"] = location.origin + "/archive/category/" + bc
        breadcrumb_json["itemListElement"].push(json)
    }
    try {
        var bc = document.getElementsByClassName("breadcrumb")
        bc[0].innerText = null
        bc[0].append(ol)
    } catch (error) { }
    /*パンくずリストを表示*/
    //scriptデータ追加
    var script_ele = document.createElement("script")
    script_ele.setAttribute("type", "application/ld+json")
    script_ele.innerText = JSON.stringify(breadcrumb_json)
    ol.parentNode.insertBefore(script_ele, ol.nextSibling);
}