【解説】第二弾 Instagram相互フォローチェッカー

blog

解説対象ツール

以下で作成したツールのJavaScript部分のみを解説させていただきます。
※ html,CSS(Bootstrapを使用しています)部分は解説はしていません。

ソースコード解説

JavaScriptの記述を以下に分けて解説していきたいと思います。

  • ソースコード全体
  • 1〜12行目:変数、および定数を定義
  • 13〜22行目:フォロワーファイルの読み込み処理
  • 23〜33行目:フォローファイルの読み込み処理
  • 34〜52行目:JSONファイルの加工処理
  • 53〜60行目:タブ別の処理
  • 61〜103行目:ユーザーIDの編集処理(html)
  • 104〜109行目:ユーザーIDの更新処理(html)

ソースコード全体

部分的な解説をする前に、まずはソースコードの全体を添付させていただきます。
色で分けて部分的に解説をしているので、解説を確認したい部分を確認してみてください。

  1:<script>
  2:  let conFollowers = '';
  3:  let conFollowing = '';
  4:  let conMutual = '';
  5:  
  6:  window.onload = function() {
  7:    const reader = new FileReader();
  8:    const inputFollowers = document.getElementById('followersFile');
  9:    const inputFollowing = document.getElementById('followingFile');
 10:    let wkFollowers = new Array();
 11:    let wkFollowing = new Array();
 12:   
 13:    inputFollowers.addEventListener('change', function(e) {
 14:      reader.readAsText(e.target.files[0]);
 15:      reader.onload = function(e) {
 16:        let tmp = '';
 17:        tmp = JSON.parse(e.target.result);
 18:        for(let i = 0; i < tmp.relationships_followers.length; i++){
 19:          wkFollowers.push(tmp.relationships_followers[i].string_list_data[0].value);
 20:        }
 21:      };
 22:    });
 23:    inputFollowing.addEventListener('change', function(e) {
 24:      reader.readAsText(e.target.files[0]);
 25:      reader.onload = function(e) {
 26:        let tmp = '';
 27:        tmp = JSON.parse(e.target.result);
 28:        for(let i = 0; i < tmp.relationships_following.length; i++){
 29:          wkFollowing.push(tmp.relationships_following[i].string_list_data[0].value);
 30:        }
 31:      };
 32:    });
 33:   
 34:    document.getElementById("button").onclick = function(e) {
 35:      let mutual = '';
 36:      mutual = wkFollowing.filter((val)=>{
 37:        return wkFollowers.indexOf(val) !== -1
 38:      })
 39:      conMutual = mutual;
 40:      wkFollowers = wkFollowers.filter((val)=>{
 41:        return mutual.indexOf(val) == -1
 42:      })
 43:      conFollowers = wkFollowers;
 44:      wkFollowing = wkFollowing.filter((val)=>{
 45:        return mutual.indexOf(val) == -1
 46:      })
 47:      conFollowing = wkFollowing;
 48:      window.alert("読み込み完了");
 49:    };
 50:    
 51:    let checkOption = document.getElementsByName('options');
 52:   
 53:    checkOption.forEach(function(e) {
 54:      e.addEventListener("click", function() {           
 55:        let select = document.querySelector("input:checked[name=options]").value;
 56:        let columnCount = 0;
 57:        let content = '';
 58:        let number_people ='';
 59:        user_name.innerHTML = '';
 60:        number_people.innerHTML = '';
 61:        if(select === '1'){
 62:          number_people = conFollowers.length +'人';
 63:          for(let user in conFollowers){
 64:            if(columnCount===0){
 65:              content += '<tr><td>' + conFollowers[user] + '</td>'
 66:              columnCount++;
 67:            }else if(columnCount < 3){
 68:              content += '<td>' + conFollowers[user] + '</td>';
 69:              columnCount++;
 70:            }else{
 71:              content += '<td>' + conFollowers[user] + '</td></tr>';
 72:              columnCount=0;
 73:            }
 74:          }
 75:        }else if(select === '2'){
 76:          number_people = conFollowing.length +'人';
 77:          for(let user in conFollowing){
 78:            if(columnCount===0){
 79:              content += '<tr><td>' + conFollowing[user] + '</td>'
 80:              columnCount++;
 81:            }else if(columnCount < 3){
 82:              content += '<td>' + conFollowing[user] + '</td>';
 83:              columnCount++;
 84:            }else{
 85:              content += '<td>' + conFollowing[user] + '</td></tr>';
 86:              columnCount=0;
 87:            }
 88:          }
 89:        }else if(select === '3'){
 90:          number_people = conMutual.length +'人';
 91:          for(let user in conMutual){
 92:            if(columnCount===0){
 93:              content += '<tr><td>' + conMutual[user] + '</td>'
 94:              columnCount++;
 95:            }else if(columnCount < 3){
 96:              content += '<td>' + conMutual[user] + '</td>';
 97:              columnCount++;
 98:            }else{
 99:              content += '<td>' + conMutual[user] + '</td></tr>';
100:              columnCount=0;
101:            }
102:          }
103:        }
104:        user_name.innerHTML = content;
105:        window.alert(number_people);
106:      });
107:    });
108:  }
109:</script>

1〜12行目:変数、および定数を定義

1〜12行目は、全体で使用する変数、および定数の定義を記述しています。

  1:<script>
    //最終出力フォロワーのリストを変数として定義
  2:  let conFollowers = '';

    //最終出力フォローのリストを変数として定義
  3:  let conFollowing = '';

    //最終出力相互フォローのリストを変数として定義
  4:  let conMutual = '';
  5:  
    //DOMのレンダリングやCSS・画像などの関連リソースをすべて読み込んだ後に実行される処理を定義
    //↑要するに、Webページを全て読み込んだ後に実行したい処理をonloadで囲んで記述しているということです
  6:  window.onload = function() {

    //後々データファイル(JSONファイル)を読み込む “FileReaderクラス” を定数として定義
  7:    const reader = new FileReader();

    //フォロワーのファイルを読み込む場所を定数として定義
    //↑ファイルの中身を定義しているのではなく、ファイルを読み込んでいる場所のみを定義している
  8:    const inputFollowers = document.getElementById('followersFile');

    //フォローのファイルを読み込む場所を定数として定義
    //↑ファイルの中身を定義しているのではなく、ファイルを読み込んでいる場所のみを定義している
  9:    const inputFollowing = document.getElementById('followingFile');

    //一時的にフォロワーのデータを保存する変数を配列で定義(相互フォローも含んでいる)
 10:    let wkFollowers = new Array();

    //一時的にフォローのデータを保存する変数を配列で定義(相互フォローも含んでいる)
 11:    let wkFollowing = new Array();
 12:   

13〜22行目:フォロワーファイルの読み込み処理

13〜22行目は、フォローファイル(followers.json)を読み込む処理を記述しています。

    //8行目で定義していたフォロワーリストファイルの読み込み場所に変化があった場合の処理を定義
 13:    inputFollowers.addEventListener('change', function(e) {

    //7行目で定義していたクラスを使用してフォロワーリストファイルを文字列として読み込む
 14:      reader.readAsText(e.target.files[0]);

    //14行目でファイルの読み込みが完了して、利用可能になった場合の処理を定義
 15:      reader.onload = function(e) {

    //一時的にファイル内の文字列を格納する変数として定義
 16:        let tmp = '';

    //14行目で読み込んだ文字列をJSONとして解析し、変数のtmpに格納する
 17:        tmp = JSON.parse(e.target.result);

    //JSONファイル内の “relationships_followers” がキーになっている数分ループする処理を定義
 18:        for(let i = 0; i < tmp.relationships_followers.length; i++){

    //JSONファイル内の “relationships_followers.string_list_data[0]” が
    //キーになっている “value” のみを “wkFollowers” の配列に格納
    //↑要するに、InstagramにおけるフォロワーのユーザーIDのみを切り出して “wkFollowers” の配列に格納している
 19:          wkFollowers.push(tmp.relationships_followers[i].string_list_data[0].value);
 20:        }
 21:      };
 22:    });

23〜33行目:フォローファイルの読み込み処理

23〜33行目は、フォローファイル(following.json)を読み込む処理を記述しています。

    //9行目で定義していたフォローリストファイルの読み込み場所に変化があった場合の処理を定義
 23:    inputFollowing.addEventListener('change', function(e) {

    //7行目で定義していたクラスを使用してフォローリストファイルを文字列として読み込む
 24:      reader.readAsText(e.target.files[0]);

    //24行目でファイルの読み込みが完了して、利用可能になった場合の処理を定義
 25:      reader.onload = function(e) {

    //一時的にファイル内の文字列を格納する変数として定義
 26:        let tmp = '';

    //24行目で読み込んだ文字列をJSONとして解析し、変数のtmpに格納する
 27:        tmp = JSON.parse(e.target.result);

    //JSONファイル内の “relationships_following” がキーになっている数分ループする処理を定義
 28:        for(let i = 0; i < tmp.relationships_following.length; i++){

    //JSONファイル内の “relationships_following.string_list_data[0]” が
    //キーになっている “value” のみを “wkFollowing” の配列に格納
    //↑要するに、InstagramにおけるフォロワーのユーザーIDのみを切り出して “wkFollowing” の配列に格納している
 29:          wkFollowing.push(tmp.relationships_following[i].string_list_data[0].value);
 30:        }
 31:      };
 32:    });
 33:   

34〜52行目:JSONファイルの加工処理

34〜52行目は、JSONファイル(フォローファイル、およびフォロワーファイル)の加工をする処理を記述しています。

    //実行ボタンを押した場合の処理を定義
 34:    document.getElementById("button").onclick = function(e) {

    //一時的な相互フォローのリストを変数として定義
 35:      let mutual = '';

    // “wkFollowing” 内のユーザーIDが “wkFollowers” 内にある場合は、 “mutual” に格納
    //ない場合は、wkFollowers.indexOf(val)がエラーである -1 となるため、 “mutual” に格納されない
 36:      mutual = wkFollowing.filter((val)=>{
 37:        return wkFollowers.indexOf(val) !== -1
 38:      })

    //一時的な相互フォローリストを最終出力相互フォローのリストに格納
 39:      conMutual = mutual;

    // “wkFollowers” 内のユーザーIDが “mutual” 内にある場合は、 “wkFollowers” に格納
    //ない場合は、mutual.indexOf(val)がエラーである -1 となるため、 “wkFollowers” に格納されない
 40:      wkFollowers = wkFollowers.filter((val)=>{
 41:        return mutual.indexOf(val) == -1
 42:      })

    //一時的なフォロワーリストを最終出力フォロワーのリストに格納
 43:      conFollowers = wkFollowers;

    // “wkFollowing” 内のユーザーIDが “mutual” 内にある場合は、 “wkFollowing” に格納
    //ない場合は、mutual.indexOf(val)がエラーである -1 となるため、 “wkFollowing” に格納されない
 44:      wkFollowing = wkFollowing.filter((val)=>{
 45:        return mutual.indexOf(val) == -1
 46:      })

    //一時的なフォローリストを最終出力フォローのリストに格納
 47:      conFollowing = wkFollowing;

    //アラート機能で “読み込み完了” と通知
 48:      window.alert("読み込み完了");
 49:    };
 50:    

    //フォローのみ、フォロワーのみ、相互フォローのみがどれかを指定している場所を変数として格納
 51:    let checkOption = document.getElementsByName('options');
 52:   

53〜60行目:タブ別の処理

53〜60行目は、タブ別(フォローのみ、フォロワーのみ、相互フォローのみ)で選択した際の処理を記述しています。


    //フォローのみ、フォロワーのみ、相互フォローのみ分(3回)ループする処理を定義
 53:    checkOption.forEach(function(e) {

    //フォローのみ、フォロワーのみ、相互フォローのみがどれかを指定している場所をクリックした場合の処理を定義
 54:      e.addEventListener("click", function() {

    //フォローのみ、フォロワーのみ、相互フォローのみがどれをクリックしたかの値を格納
 55:        let select = document.querySelector("input:checked[name=options]").value;

    //テーブルカラムカウントを0に初期化する
 56:        let columnCount = 0;

    //ユーザー名に出力する文字列の変数を定義
 57:        let content = '';

    //ユーザー数に出力する文字列の変数を定義
 58:        let number_people ='';

    //ユーザー名に出力する文字列(html)の変数を定義
 59:        user_name.innerHTML = '';

    //ユーザー数に出力する文字列(html)の変数を定義
 60:        number_people.innerHTML = '';

61〜103行目:ユーザーIDの編集処理(html)

61〜103行目は、html上でユーザーIDを表示するために編集する処理を記述している。

    //フォロワーのみをクリックした場合の処理を定義
 61:        if(select === '1'){

    //最終出力フォロワーの人数を “number_people” に格納
 62:          number_people = conFollowers.length +'人';

    //最終出力フォロワーの人数分ループする処理を定義
 63:          for(let user in conFollowers){

    //テーブルカラムカウントが0の場合の処理を定義
 64:            if(columnCount===0){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最初に<tr>も追加する(今1列目))
 65:              content += '<tr><td>' + conFollowers[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 66:              columnCount++;

    //テーブルカラムカウントが1または2の場合の処理を定義
 67:            }else if(columnCount < 3){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>のみを追加する(今2,3列目))
 68:              content += '<td>' + conFollowers[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 69:              columnCount++;

    //テーブルカラムカウントが3の場合の処理を定義
 70:            }else{

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最後に</tr>も追加する(今4列目))
 71:              content += '<td>' + conFollowers[user] + '</td></tr>';

    //テーブルカラムカウントを0に初期化する
 72:              columnCount=0;
 73:            }
 74:          }

    //フォローのみをクリックした場合の処理を定義
 75:        }else if(select === '2'){

    //最終出力フォローの人数を “number_people” に格納
 76:          number_people = conFollowing.length +'人';

    //最終出力フォローの人数分ループする処理を定義
 77:          for(let user in conFollowing){

    //テーブルカラムカウントが0の場合の処理を定義
 78:            if(columnCount===0){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最初に<tr>も追加する(今1列目))
 79:              content += '<tr><td>' + conFollowing[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 80:              columnCount++;

    //テーブルカラムカウントが1または2の場合の処理を定義
 81:            }else if(columnCount < 3){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>のみを追加する(今2,3列目))
 82:              content += '<td>' + conFollowing[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 83:              columnCount++;

    //テーブルカラムカウントが3の場合の処理を定義
 84:            }else{

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最後に</tr>も追加する(今4列目))
 85:              content += '<td>' + conFollowing[user] + '</td></tr>';

    //テーブルカラムカウントを0に初期化する
 86:              columnCount=0;
 87:            }
 88:          }

    //相互フォローのみをクリックした場合の処理を定義
 89:        }else if(select === '3'){

    //最終出力相互フォローの人数を “number_people” に格納
 90:          number_people = conMutual.length +'人';

    //最終出力相互フォローの人数分ループする処理を定義
 91:          for(let user in conMutual){

    //テーブルカラムカウントが0の場合の処理を定義
 92:            if(columnCount===0){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最初に<tr>も追加する(今1列目))
 93:              content += '<tr><td>' + conMutual[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 94:              columnCount++;

    //テーブルカラムカウントが1または2の場合の処理を定義
 95:            }else if(columnCount < 3){

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>のみを追加する(今2,3列目))
 96:              content += '<td>' + conMutual[user] + '</td>';

    //テーブルカラムカウントをプラス1する
 97:              columnCount++;

    //テーブルカラムカウントが3の場合の処理を定義
 98:            }else{

    //ユーザーIDとタグを “content” に格納(テーブルは4列なので<td></td>に加えて最後に</tr>も追加する(今4列目))
 99:              content += '<td>' + conMutual[user] + '</td></tr>';

    //テーブルカラムカウントを0に初期化する
100:              columnCount=0;
101:            }
102:          }
103:        }

104〜109行目:ユーザーIDの更新処理(html)

104〜109行目は、html上でユーザーIDを表示するためにhtmlを更新する処理を記述している。


    //ユーザー名に出力する文字列(html)の変数に “content” を格納
104:        user_name.innerHTML = content;

    //アラート機能で人数を通知
105:        window.alert(number_people);
106:      });
107:    });
108:  }
109:</script>

まとめ

初めて自身で記述したソースコードを解説してみましたが、
よくよく見返してみると、処理の無駄が多すぎるということがわかりましたので、
近いうちに作成したツールを修正してより処理が簡潔なツールを作成したいと思います。

何か気になることや、問題などがありましたら、コメントやお問い合わせをいただけると嬉しいいです。

最後までご覧いただきありがとうございました!!