特定ユーザーのQiita記事一覧を得る(5)

[前回の記事](https://qiita.com/ELIXIR/items/5972aec6833504293e45)のアップデートです。
uriのクエリに&tag=[key]を追加することでタグを選択した状態で記事一覧を表示できます。

自分自身の備忘録として記事を書いてきたのに、記事が増えすぎて調べるのに手間取るようになってしまったのですが、これのおかげでとても助かっています。

API使用制限(60回/時間)があるのでその点のみご注意ください。
また、記事が多いと表示まで数秒かかることがあります。

[動作デモ](https://elix.jp/app/tools/qiita_index.html?uuid=ELIXIR&tag=Unity)
前回同様ローカル環境でも動作します。

```
<!DOCTYPE html>
<html><head><title>Qiita index</title>
    <style type="text/css">
      .cOnButton { color: #111; background-color: #fc8; }
      .cOffButton { color: #888; }
      button{ margin: 1px; height: 30px; font-size: 1rem;}
    </style>
    <script>
    var USER_ID='ELIXIR';
    var ALL_DISP_TAG = 'All';
    const PAR_PAGE=100; // Qiita API の上限
    var resArr = [];
    var qVar='';
    var existTagArr = [];

    var TmGetUrlVarByKeys = function(){
      var vars = {}; 
      var param = location.search.substring(1).split('&');
      for(var i = 0; i < param.length; i++) {
          var keySearch = param[i].search(/=/);
          var key = '';
          if(keySearch != -1) key = param[i].slice(0, keySearch);
          var val = param[i].slice(param[i].indexOf('=', 0) + 1);
          if(key != '') vars[key] = decodeURI(val);
      } 
      return vars; 
    }

    function onSearch(_tag=''){
      USER_ID = document.getElementById('iUuid').value;
      if(USER_ID==''){
        return;
      }
      resArr = [];
      document.title=USER_ID;
      var vars = TmGetUrlVarByKeys();
      if(qVar != USER_ID) {
        window.location.search = '?uuid='+USER_ID+(_tag==''?'':('&tag='+_tag));
      }else{
        getUser(_tag);
      }
    }

    function onLoad(){
      var vars = TmGetUrlVarByKeys();
      if(!(typeof vars["uuid"] === "undefined")) {
        qVar = vars["uuid"];
        document.getElementById('iUuid').value = qVar;
        var qTag = (!(typeof vars["tag"] === "undefined")) ? vars["tag"] : '';
        onSearch(qTag);
      }
    }

    function apiCall(_api, _callback, _userData=0){
      var req = new XMLHttpRequest();
      req.responseType="json";
      req._userData=_userData;
      req.addEventListener("load", _callback);
      req.open('GET', 'https://qiita.com/api/v2/'+_api, true);
      req.send();
    }

    function getUser(_tag){
      apiCall('users/'+USER_ID,function(){
        if(this.response["items_count"]==undefined)
          document.getElementById('iResult').innerHTML = 'エラーまたはapi使用上限(60回/時間)に達しました。';
        else
          getData(Math.floor((this.response["items_count"]+(PAR_PAGE-1))/PAR_PAGE),_tag);
      });
    }

    function getData(_page=1,_tag=''){
      apiCall('users/'+USER_ID+'/items?per_page='+PAR_PAGE+'&page='+_page,function(){
        resArr=resArr.concat(this.response);
        if(this._userData>1)
          getData(this._userData-1,_tag);
        else
          dispData(resArr,_tag);
      },_page);
    }

    function sortButtons(_sortByCount=false){
      var buttonsEle = document.getElementById('iButtons');
      var btnArr = Array.from(document.getElementById('iButtons').children);
      btnArr.sort(
        function(v0,v1){
          if(_sortByCount){
            return (v0.existCnt > v1.existCnt) ? -1:1;
          }else{
            return (v0.innerText < v1.innerText) ? -1:1;
          }
        }
      );
      buttonsEle.innerHTML="";
      for(var i=0;i<btnArr.length;++i){
        buttonsEle.appendChild(btnArr[i]);
      }
    }
    function createButton(_name,_tag){
      existTagArr.push(_name);
      var btn = document.createElement('button');
      btn.innerHTML=_name;
      btn.className=(_name==_tag)?'cOnButton':'cOffButton';
      btn.onclick=function(){dispData(resArr,_name);}
      btn.id = 'i_btn'+_name;
      btn.existCnt=1;
      return btn;
    }
    function createButtons(_resArr,_tag){
      var buttonsEle = document.getElementById('iButtons');
      existTagArr=[];
      buttonsEle.innerHTML = '';
      if(_resArr.length>1){
        buttonsEle.appendChild(createButton(ALL_DISP_TAG,''));
        document.getElementById('i_btn'+ALL_DISP_TAG).existCnt=_resArr.length;
      }
      for(var i=0;i<_resArr.length;++i){
        var tagArr=_resArr[i]['tags'];
        for(var j=0;j<tagArr.length;++j){
          if(!existTagArr.includes(tagArr[j]['name'])){
            buttonsEle.appendChild(createButton(tagArr[j]['name'],_tag));
          }else{
            document.getElementById('i_btn'+tagArr[j]['name']).existCnt+=1;
          }
        }
      }
      sortButtons(true);  //false if sort by name
    }

    function articleContainsTag(_article,_tag){
      for(var i=0;i<_article['tags'].length;++i)
          if(_article['tags'][i]['name']==_tag)
            return true;
        return false;
    }

    function dispData(_resArr,_tag=''){
      createButtons(_resArr,_tag);
      var articles = [];
      for(var i=0;i<_resArr.length;++i){
        if((_tag=="")||(_tag==ALL_DISP_TAG)||(articleContainsTag(_resArr[i],_tag))){
          var tmpStr = '<a href="'+_resArr[i]['url']+'" target="_blank">'+ _resArr[i]['title']+'</a>';
          articles.push({'title':tmpStr, 'created_at':_resArr[i]['created_at']});
        }
      }
      articles.sort(function(a,b){ return ( a.created_at < b.created_at ) ? 1 : -1; });

      var str="";
      for(var i=0;i<articles.length;++i)
        str += articles[i]['title']+"<br/>";
      
      str += (articles.length>1) ? '('+articles.length+' articles)<br/>' : '';

      document.getElementById('iResult').innerHTML = str;
    }

  </script>
</head>
<body onload="onLoad()">
user_id@<input id="iUuid" type="text" onchange="onSearch()"> <input type="button" value="search" onclick="onSearch()"><div id="iButtons"></div><div id="iResult"></div></body>
<br/>
</html>
```