読者です 読者をやめる 読者になる 読者になる

ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

javascriptでファイルリストに書かれているファイルを動的に読み込む

Programming

はじめに

音楽を作っているソロプロジェクトのHPを作っています。

とけてなくなる

AWSのS3上において、https対応、circleCIで自動アップロード対応等やりました。

  • レガシーな静的webサイトを一新!軽量cssフレームワークSkelton導入
  • レガシーな静的Webサイトを一新!その② 独自ドメインを使ってAWS S3に静的Webサイト公開
  • レガシーな静的Webサイトを一新!その③ CircleCIとGithub連携でDevOps!
  • レガシーな静的Webサイトを一新!その④ AWS CloudFrontとCertificate Managerでhttps対応する
  • レガシーな静的Webサイトを一新!その⑤ httpsサイトで承認されてないscriptの警告が出てしまう
  • なお、私は本業サーバサイドなのでhtml/javascriptの知識は皆無であり、本質的な解決方法ではないことも、ナンセンスなこともたくさんしているかと思いますが、趣味のHPでなんとかやりたいことをやるために奮闘した記録となっていますので温かい目で見守ってください。

    informationの更新問題

    更新情報を記載するinformationですが私の要望は以下。

    • 更新日ごとにinfo/170101(日付).htmlを追加する
    • index.htmlからinfoフォルダ以下のディレクトリを自動で読み込んで表示する
    • index.htmlでは最新3記事のみ表示する
    • read moreのlinkから全部のinformationをinfoフォルダ以下のディレクトリから自動で読みこんで表示する

    これをやる前の状況は

    • loadするファイルパスがベタ書き
    • 表示部分も記事の分だけベタ書き

    となっており、更新をするたびにindex.htmlに追記するという地獄のような状況になってました。記事数が3,4のうちはいいにしても、早めに対策を打たないといけない。

    こういうことは一気にしてはいけないので、1つずつゆっくり問題を解決していきました。

    記事の読み込みと表示をloopとinnerHTMLを使う

    まずベタ書きの部分をせめて繰り返し可能にします。

    rails(ruby)でいうところのerbみたいにhtmlで書きたかったわけです。これはjqueryのloopを使いました。

    load infomation iterative · takeshe12/toketenakunaru@61fe64f · GitHub

    jqueryで外部htmlファイルをloadする部分

    var num = ["161203","161204","161231","170110","170122","170125"];
    jQuery.each(num,function() {
      var path = 'info/'+ this + '.html';
      $("#" + this).load(path);
    });
    

    表示部分はinnerHTMLを使いました。

    var hoge = ""
    var id = ["170125","170122","170110","161231","161204","161203"];
    $.each(id,function(i,value){
      hoge += "<section class='sec'><div id=\'" + value + "\'</div></section>";
    });
    var elem = document.getElementById("infomation");
    elem.innerHTML = hoge
    

    $(“#” + 170101).load(info/170101)とloadしたら、

    でloadした部分が表示されます。

    今回はinnerHTMLを使ってinformationというidがついた部分にtagを打ち込んでいます。

    昔はdocument.writeというものもあったみたいですが、HTML5では非推奨だそう。

    innerHTMLで注意すべき店はタグ内の要素はシングルクォートでくくらないといけないってことですね。タグ自体をダブルクォートでくくっているので。ところでこのコード閉じカッコがないな。。。なんで動いたんだ。

    参考

    HTML要素の中身を変えるinnerHTML | JavaScript入門編

    filelistが書かれている別ファイルからloadするpathを読み込む

    loadだpathだややこしい説明になってすみません。

    今回やりたかった、infoフォルダ以下の内容を動的に読み込むって、そもそもwebサーバ内のフォルダを除く行為なわけで、クライアントで動くjavascriptでできるわけもないんですね。

    代替案として以下のようなfilelistを用意します。

    • info/filelist
    170101
    170103
    170121

    javascriptでこのファイルを改行で区切って読み込み、配列として取得。あとはその配列を上の例でloopして表示とloadを行います。

    load file list from external file · takeshe12/toketenakunaru@a7053eb · GitHub

    ファイルリストを出すためにゴミシェルも書きました。

    // get early 3 file from info file list.
    var arr = [];
    $.ajax({
      url: 'infolist',
      async:false, //wait to finish ajax connection
      success: function(data){
        arr = data.split(/\r\n|\r|\n/);
        arr.pop(); //delete end value
        var infotag = ""
        $.each(arr,function(i,value){
          infotag += "<section class='sec'><div id=\'" + value + "\'></div></section>";
        });
        var elem = document.getElementById("infomation");
        elem.innerHTML = infotag
      }
    

    ここで謎にajaxを使っています。ちなみにajaxのことは何も知りません。(笑)

    確か非同期通信を実現するためのjavascriptを使った実装の1つ、ですかね。

    今回localhostのfilelistを取得して、取得に成功したら(success)、そのdataを改行でsplitし、arrayに代入。そのあとその値をtagに打ち込んでinnerHTMLとして更新しています。

    ajaxのキモが非同期なわけですが、ここではあえてasync falseとして同期処理としています。同期処理の場合、まだレスポンスが返ってきていないのでタグ生成時にはvalueがundefinedとなってしまいました。そのためasync falseとすることで解決しましたが、良いやりかたではない気もします。

    ちなみにここのarr変数はグローバル変数にしているのでpathをloadするほうでもそのまま使えました。javascriptの変数スコープについては以前勉強したので知っていて、むやみにグローバル変数にするのはよくないのは知っていますが今回はこのまま。

    read moreですべてのinformationを表示

    もっと良いやり方があるとは思ってますが、今回はinformaton.htmlを別ページを作成し、このページ用に全informationのfilelistを作成し、同じ方法で実現しました。全部読み込んでおいて、最初は3つだけ表示、linkをクリックしたら残りも表示、とjavascriptを使えばできるとは思いますが、まずは実現ということで今回は雑な方法で。重複コードができてしまうのでメンテナンス性はさがることからいずれ対処したいです。

    circleCIでfilelist生成を自動化

    さて、今回はfilelistにしたがってinformationを読み込んでいますが、そのfilelistの生成はシェルスクリプトであり、情報を追加するたびにこのシェルを叩いてから、ファイルリストを含めてコミットする必要があります。このひと手間はイケてない。

    exec getfile.sh · takeshe12/toketenakunaru@36a21d0 · GitHub

    circleCIでのbuildの前にこのシェルを叩かせればいいんじゃない?と安易に実行したところ、できました。まぁ、できるよね。gitからcheckoutして、シェル叩いて、それをS3と同期してるわけなので。

    このブログを書くに伴ってゴミシェルをちょっと書き直しました。

    結果的に行数増えとるわ。

    refactor script · takeshe12/toketenakunaru@f8d02c2 · GitHub

    おわりに

    趣味の音楽+仕事のプログラミングということで、楽しいですね。インフラまわりもAWSで整えられたので満足度高いです。肝心のコンテンツ更新も少しずつやっていきます。