Open Site Navigation

Wix ブログに目次を追加する方法

サイドバーに目次、TOC(Table of contents)を表示する方法があるか調べてみました。


目次を作成する方法はないのか?


Wix Blogのディスカッションでも同様の質問をしている人がいました。

https://www.wix-blog-community.com/blog/discussions/creating-table-of-contents


ざっとみた感じ回答としては下記のコメントなのでしょうが

どちらも手動で作成する必要があり、面倒だなと思い、Wix Veloを使って自動で生成できないか考えてみました。


どのように実装するか


UIの設定

前提として目次のUIは下記の画像を参考に設定してください。

Box要素に toc というIDを割り当て、その配下にリピーター要素を配置します。


Veloコードの設定

スクリプトは下記のコードを使用します。

ポイントとしては9行目の wixData.get("Blog/Posts",postId); で取得したコレクションのブログのデータには richContent というプロパティがあり、このデータをもとに目次のUIに使用するデータを構築していきます。

richContent.nodesには下記のようなデータが入っています。

[
  {
    "type": "HEADING",
    "id": "foo",
    "nodes": [
      {
        "type": "TEXT",
        "id": "",
        "nodes": [],
        "textData": {
          "text": "やること",
          "decorations": []
        }
      }
    ],
    "headingData": {
      "level": 2,
      "textStyle": {
        "textAlignment": "AUTO"
      },
      "indentation": 0
    }
  },
  {
    "type": "PARAGRAPH",
    "id": "ckt4r",
    "nodes": [
      {
        "type": "TEXT",
        "id": "",
        "nodes": [],
        "textData": {
          "text": "Wixでは特定のブログ記事に対して有料プランの設定をしたり、ブログ記事全体に対してアクセス制限を設定することはできる。",
          "decorations": []
        }
      }.......

12から15行目のコードで上記のデータから { _id, headText, level } こんなオブジェクトを作成します。

そのオブジェクトを23から31行目でUIに紐づけていきます。


ハマったポイント

実装しながらハマったのが下記の2点です。ちょいちょい動きが想像と違う時があるのですが、これは知見をストックしていくしかないなー。


IDが思ったのと違う

上記のrichContent.nodesのデータにはidというプロパティがあり、その要素にwindow.localtion.hashを設定すればページ内遷移ができると思ったのですが、下記の通り、IDの前に viewer-という文字列が追加されるようです。

そのため、29行目の目次の項目をクリックした時の処理には下記のようにviewer-という文字列を追加しています。

wixLocation.to(wixLocation.baseUrl+'/'+wixLocation.path.join("/")+`#viewer-${itemData._id}`)

関連記事のクリック時の挙動


$w.onReady initTOC を発火すれば目次が初期化できると思っていましたが、ブログ記事ページ内の関連記事のクリック時には$w.onReadyが発火されないということがわかりました。


まあたしかにページスクリプトは同じものを使っているし、ブログ記事のデータが変更されただけではあるので発火しないのでしょう。


なので、URLが変わった時に動くイベントリスナーを設定します。

let prevPath = String(wixLocation.path)
wixLocation.onChange(({ path }) => {
    const pathStr = String(path)
    if (prevPath !== pathStr) {
        prevPath = pathStr;
        initTOC()
    }
});

上記のように設定することで関連記事の遷移でも目次を再生成することができます。



まとめ

割と短めのスクリプトで生成できたのでよかった。


理想としては下記のページのTOCのようにスクロール位置から現在の目次をハイライトしたいが複雑になりそうなので一旦この程度にしておく。

https://help.wixanswers.com/kb/en/article/getting-started-with-your-knowledge-base-articles


では。


参考Velo API:

head1

id

Table of contents