rcmdnk's blog

ローカルで作成する方法

最初、手元でランダムなリストを作ってそのまま送ってしまおう、としたのがこちら。

plugins/random_posts.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'jekyll'
module Jekyll
  class RandomPosts < Generator
    safe :true
    priority :low
    def generate(site)
      # check if random local is required or not
      if !site.config['random_local']
        return
      end
      if site.config['random_posts']
        n_posts = site.config['random_posts']
      else
        n_posts = 5
      end
      popular_posts = site.posts.shuffle
      site.posts.each { |post|
        post.data.merge!("random_posts" => popular_posts[0,n_posts])
      }
      site.pages.each { |page|
        page.data.merge!("random_posts" => popular_posts[0,n_posts])
      }
    end
  end
end

これをplugins/の中に入れておけば page.random_postsという値が使える様になるので、

source/_includes/custom/asides/random_posts.htmlとかいう名前で

source/_includes/custom/asides/random_posts.html
1
2
3
4
5
6
7
8
<section>
  <h1>Random Posts</h1>
  <ul class="posts">
    {% for post in page.random_posts %}
    {% include post_list.html %}
    {% endfor %}
  </ul>
</section>

こんな内容の物を作っておけばサイドバーで使える様になります。

post_list.htmlGoogle AnalyticsのView数を取ってきてランキングを作る で作ったものと同じです。

JavaScriptで動的に変更する方法

上の方法だと新しくビルドするまで全てのページでずっと一緒なので余り面白くありません。

ということで、JavaScriptで動的にその場で作成する方法をやってみます。

今回はリスト用の簡易HTMLを用意しておいて、それをJavaScriptで読み取って 適当に選ぶ、と言う方法でやってみました。

リスト用HTMLの準備

まず、source直下にposts.htmlという名前で

source/posts.html
1
2
3
4
5
6
7
8
---
layout: null
---
<div>
{% for post in site.posts %}
{% include post_list.html %}
{% endfor %}
</div>

こんな感じのファイルを作ります。

これが

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div>
<li class="post index_click_box">
  <div class="group">
    <div class="title-smallthumb">
      <a href="/blog/2015/02/10/blog-octopress/"><img src="/images/post/20150210_popularlist.jpg"></a>
    </div>
    <a class="click_box_link" href="/blog/2015/02/10/blog-octopress/">Google AnalyticsのView数を取ってきてランキングを作る</a>
  </div>
</li>
<li class="post index_click_box">
  <div class="group">
    <div class="title-smallthumb">
...
  </div>
</li>
<div>

こんな感じのHTMLになります。

ここでリストだけアレば良いのですが、一番外側のdiv要素が無いと あとでJavaScript(JQuery)で中身を取得するときに上手く行かないので周りに1つ要素が必要です。 (htmlbody以外で。)

XMLとかにした方が汎用性は出るかと思いますが、 取ってきた後に整形したりするのが面倒なので 今回はそのまま使える様にHTMLにしてあります1

サイドバー用のHTML & JavaScript

source/_includes/custom/asides/random.html を以下のように変更し、取り敢えずJavaScriptもここへ書いておきます。

source/_includes/custom/asides/random.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<section>
  <h1 id="random-link">Random Posts</h1>
  <div id="random-posts"><div>
     <ul>
     </ul>
  </div>
  <script type="text/javascript">
  $(function(){
    $.ajax({
      url:'/posts.html',
      type:'GET',
      dataType:'html'
    }).done(function(data){
      var entry_list = $(data).find('li');
      var nentries = entry_list.length;
      var rand = [];
      var f = document.createDocumentFragment();
      while(rand.length < {% if site.random_posts %}{{site.random_posts}}{% else %}10{% endif %} && rand.length < nentries){
        var r = Math.floor(Math.random()*nentries);
        if(rand.indexOf(r)!=-1)continue;
        f.appendChild(entry_list[r]);
        rand.push(r);
      }
      var t = document.getElementById('random-posts').getElementsByTagName('ul')[0];
      t.appendChild(f);
      var random_url=$(entry_list[Math.floor(Math.random()*nentries)]).find('.click_box_link')[0].href;
      $('#random-link').wrap($('<a href="Random Fly!"/>'));
      $('#random-link').click(function(){
        window.location=random_url;
        return false;
      });
    });
  });
  </script>
</section>

Ajaxを使って作成される/posts.htmlを取得して、その中にある li要素を配列として取ってきています2。 この時に先のdiv要素が周りにないと上手くli要素の配列が取れません。

この辺り、ブラウザによって動作が違ったりしますが、 取り敢えず上のコードだと手元のMac/WindowsでFirefox/Google Chrome/IE/Safariで動いています。

後は適当に乱数を使って必要な数だけ最初に作ったul要素の中に加えて行くだけです。

また、タイトルのRandom Postsの部分も別途適当なページヘのリンクになるようにもしています。

_config.yml

今回はそれ程設定する所はありませんが

_config.yml
1
2
3
# Random posts
random_posts: 5
random_local: false

とでも書いておけば動的な方だけ有効になって5つのランダムな記事が表示されます。

(少なくともコレ書いた時点では)右下にあるRandom Postsリストはリロードするたびに変わるはずです。

Sponsored Links
  1. ちなみXMLを使おうと思った時にも同じような問題が起きて、 全体を一括で囲うようなものがないと

    XML パースエラー: ドキュメント要素の後ろに不正な文字列があります。
    

    というエラーメッセージがブラウザのコンソールで見えたりします。 (一行目の<?xml...>以下の部分全体を<data>~</data>で囲ったりすればコレが消えます。)

  2. 今回はsucccessの代わりにdoneを使ってモダンな感じ?にしてみました。

Sponsored Links

« Google AnalyticsのView数を取ってきてランキングを作る Google ChromeではまだJavaScriptでstr.startsWith()が使えない »

}