JavaSriptであなたのいいところ診断を作ろう

    「あなたのいいところ診断」の要件を考える
    ・名前を入力すると、診断結果が表示される
    ・同じ名前なら、必ず同じ診断結果が表示される
    ・診断後に、自分の名前が入った診断結果が表示される

    今回はフォルダの中にindex.htmlとseikaku.cssとseikaku.jsという3つのファイルを用意します。フォルダ・ファイル名は何でもいいです。拡張子だけ気をつけてください( .html .css .js)
    JavaScriptを基礎から学びたい方は、誰もがあきらめずにすむJavaScriptの記事をご覧ください。

    目次

    index.html

    <!DOCTYPE html><html lang=”ja”>
    <head><meta charset=”UTF-8″>
    <link rel=”stylesheet” href=”seikaku.css”>
    <title>あなたのいいところ診断</title>
    </head>
    <body>
    <h1> あなたのいいところは ?</h1>
    <p> 診断したい名前を入れて下さい </p>
    <input type=”text” id=”user-name” size=”40″ maxlength=”20″>
    <button id=”assessment”>診断する</button>
    <div id=”result-area”></div> <div id=”tweet-area”>
    </div> <script src=”seikaku.js”></script>
    </body>
    </html>

    pタグは段落 buttonタグはボタン inputタグは入力欄を作っています。inputタグとbuttonにはJavaScript(JS)プログラムから指名するためのID属性(名札)をつけています。maxlengthは最大文字数を設定しています。
    これだけで見た目の部分ができました。このような利用者が直接触れる部分のことをユーザーインターファース、略してUIと呼びます。
    「診断結果を表示する場所」と「ツイートボタンの表示場所」をdivタグで作っています。divタグは他のタグと異なり、単体では何の意味も持ちません。ただし、JSのプログラムやcssから操作したい場所にdivタグを使ってマークアップしておくと、そこにプログラムから何かしらの表示をさせたり、cssで表示を変更したりすることができて、便利です。

    seikaku.css

    body {
    background-color: #04a6eb;
    color: #fdffff;
    width: 500px;
    margin-right: auto;
    margin-left : auto;
    }
    button {
    padding: 5px 20px;
    background-color: #337ab7;
    color: #fdffff;
    border-color: #2e6da4;
    border-style: none;
    }
    input {
    height: 20px;
    }

    色はカラーコードで設定されます。三原色、赤・緑・青を2桁16進数で表します。16進数とは、0〜9までは10進数と同じで、16で1つ上のけたに上がります。数値が上がるほど色は明るくなります。Googleなどで、「カラーコード一覧」と検索すると、調べられます。
    白 #FFFFFF 赤#FF0000 青0000FF 緑#00FF00 
    など(覚える必要はありません)
    widthで幅を設定 margin autoで外側の余白を自動調整 pxは画素数
    paddingで線の内側の余白を調整

    seikaku.js

    ‘use strict’;const userNameInput =document.getElementById(‘user-name’);
    const assessmentButton =document.getElementById(‘assessment’);
    const resultDivided = document.getElementById(‘result-area’);
    const tweetDivided = document.getElementById(‘tweet-area’);
    /*** 指定した要素の子要素を全て削除する
    * @param {HTMLElement} element HTMLの要素
    */
    function removeAllChildren(element) {
    while (element. firstChild) {
    element.removeChild(element.firstChild);
    }
    }
    assessmentButton.onclick = () => {
    const userName = userNameInput.value;
    if (userName.length === 0) {
    // 名前が空の時は処理を終了する
    return;
    }
    // 診断結果表示エリアの作成
    removeAllChildren(resultDivided);
    const header = document.createElement(‘h3’);
    header.innerText = ‘診断結果’;
    resultDivided.appendChild(header);
    const paragraph = document.createElement(‘p’);
    const result = assessment (userName);
    paragraph.innerText = result;
    resultDivided.appendChild(paragraph);
    //TODO ツイートエリアの作成
    removeAllChildren(tweetDivided);
    const anchor = document.createElement(‘a’);
    const hrefValue= ‘https://twitter.com/intent/tweet?button_hashtag=’ + encodeURIComponent(‘あなたのいいところ’) + ‘&ref_src=twsrc%5Etfw’;
    anchor.setAttribute(‘href’, hrefValue);
    anchor.className=’twitter-hashtag-button’;
    anchor.setAttribute(‘data-text’, result);
    anchor.innerText=’Tweet #あなたのいいところ’;
    tweetDivided.appendChild(anchor);
    // widgets.js の設定
    const script = document.createElement(‘script’);
    script.setAttribute(‘src’,’https://platform.twitter.com/widgets.js’);
    tweetDivided.appendChild(script);
    };
    const answers = [‘{userName}のいいところは声です。{userName}の特徴的な声は皆を惹きつけ、心に残ります。’,
    ‘{userName}のいいところはまなざしです。{userName} に見つめられた人は、気になって仕方がないでしょう。’,
    ‘{userName}のいいところは情熱です。{userName}の情熱に周りの人は感化されます。’,
    ‘{userName}のいいところは厳しさです。{userName}の厳しさがものごとをいつも成功に導きます。’,
    ‘{userName}のいいところは知識です。博識な{userName}を多くの人が頼りにします。’,
    ‘{userName}のいいところはユニークさです。{userName}だけのその特徴が皆を楽しくさせます。’,
    ‘{userName}のいいところは用心深さです。{userName} の洞察に、多くの人が助けられます。’,
    ‘{userName}のいいところは見た目です。内側から溢れ出る {userName}の良さに皆が気を惹かれます。’,
    ‘{userName}のいいところは決断力です。{userName}がする決断にいつも助けられる人がいます。’,
    ‘{userName}のいいところは思いやりです。 {userName} に気にかけてもらった多くの人が感謝しています。’,
    ‘{userName} のいいところは感受性です。 {userName} が感じたことに皆が共感し、わかりあうことができます。’,
    ‘{userName} のいいところは節度です。強引すぎない {userName} の考えに皆が感謝しています。’,
    ‘{userName} のいいところは好奇心です。新しいことに向かっていく {userName}の心構えが多くの人に魅力的に映ります。’,
    ‘{userName}のいいところは気配りです。 {userName}の配慮が多くの人を救っています。’,
    ‘{userName} のいいところはその全てです。ありのままの {userName}自身がいいところなのです。’,
    ‘{userName}のいいところは自制心です。やばいと思ったときにしっかりと衝動を抑えられ{userName} が皆から評価されています。’
    ];
    /**
    *名前の文字列を渡すと診断結果を返す関数
    * @param {string} userName
    * @return {string} 診断結果
    */
    function assessment(userName) {
    // 全文字のコード番号を取得してそれを足す
    let sumOfCharCode = 0;for (let i = 0; i < userName.length; i++) {
    sumOfCharCode = sumOfCharCode + userName.charCodeAt(i);
    }
    // 文字のコード番号の合計を回答の数で割って添字の数値を求める
    const index = sumOfCharCode % answers.length;
    let result = answers[index];
    result = result.replace(/\{userName\}/g, userName);
    return result;
    }
    // テストコード
    console.assert(
    assessment(‘ 太郎 ‘) ===’太郎のいいところは決断力です。太郎がする決断にいつも助けられる人がいます。’,’診断結果の文言の特定の部分を名前に置き換える処理が正しくありません。’);
    console.assert(
    assessment(‘太郎’) === assessment(‘太郎’), ‘入力が同じ名前なら同じ診断結果を出力する処理が正しくありません。’
    );

    JSコードの解説

    診断機能の要件

    ・診断結果のパターンのデータが取得できる

    ・名前を入力すると診断結果が出力される関数

    ①入力が同じ名前なら、同じ診断結果を出力する処理

    ②診断結果の文章のうち名前の部分を、入力された名前に置き換える処理
    これらの要件をJSで実装していきます。

    「’use strict”;」は、宣言後の記述ミスをエラーとして表示してくれる機能を呼び出すための記述です。日本語では「厳格モードを使う」という意味です。

    const と let

    ・一度しか代入できない変数であるconst(コンスト)という宣言

    ・{ }で囲まれた中でのみ使える変数である let(レット)という宣言

    が利用できます。

    変数の有効な範囲をスコープ (scope) といいます。これは本格的なプログラムを書いていくとき、予想していない部分の変数が意図せず変更されないよう制限するのに役立ちます。

    関数の実装

    次に、JavaScriptの関数を実装しましょう。要件は以下のとおりでした。

    利用者が入力した名前を元に、診断結果を1つだけ選択・出力する

    ・入力が同じ名前なら同じ診断結果を出力する

    ・診断結果の文章内にある仮の名前を入力された名前に置き換える

    /**
    * 名前の文字列を渡すと診断結果を返す関数
    * @param { string} userName ユーザーの名前
    * @return {string} 診断結果
    */
    function assessment(userName) {
    // TODO 診断処理を実装する
    return ”;
    }

    「/*」ではじまり「*」で終わる文字列の中身は、コメントです。/を使ったコメントと同じく、コメント部分はソースコードとしては実行されず、無視されます。

    今回、関数の上に書かれているコメントは、JSDocと呼ばれる形式です。このコメントは直下のassessment(userName)という関数を説明しています。

    つまり、このJSDoc という形式のコメントは「関数 assessment(userName)の引数が文字列で、戻り値も文字列」ということを表しています。

    JSDocとインタフェース

    関数の内部の処理と、外部からの入力や外部への出力(ここでは引数と戻り値)を定義している「内外の境界」のことをインタフェースと呼びます。JavaScriptは「変数の型の情報をソースコードに書かない言語」であり、インタフェースを明らかにするためには、このようにコメントで明示する必要があります。

    一方、JavaScriptの仲間のTypeScript という言語のように、ソースコードの中に型の情報を書ける言語もあります。JSDocの記述方法は DevDocsというサイトで使い方が解説されていますが、Googleなどで「JSDoc 書き方」などと検索すると日本語の解説サイトも沢山あるので、参考にしてみて下さい。JSDocはあくまでコメントですので、書かなくてもプログラムは動作します。しかしJSDoc形式でインタフェースが定義されていると、プログラムがとても読みやすいものになります。

    それだけではなく、JSDocは「ソースコードからドキュメントを自動生成する機能」や「エディタでカーソルを合わせるとインタフェースが表示される機能」などを持っていて大変便利です。

    入力が同じ名前なら同じ診断結果を出力する処理

    「入力が同じ名前なら同じ診断結果を出力する」処理を考えてみます。ここでは、名前の文字列の1文字が、実はただの整数である、という事実を利用します。これはデジタル技術全般に通じるのですが、プログラム上で現れるデータは、元は2進数の整数値でもあります。

    Chromeのデベロッパーツールの「Console] タブに

    ‘ABC’.charCodeAt(0);

    と入力すると、

    65

    と表示されます。これは、文字列を配列とみなして添字が0番目の値(つまり最初の文字のA) を整数値とすると、そのコードは65であることを表しています。

    この仕組みを使って、以下の3つのステップで診断結果を取得する処理を作ります。

    1.名前の全文字のコードの整数値を足し合わせる

    2.足した結果を、診断結果のパターンの数で割った余りを取得する

    3.余りを診断結果の配列の添字として、診断結果の文字列を取得する

    このような、ソフトウェアの動きを決める処理のことをロジックと呼びます。先ほどのロジックによって実装すると、次のようになります。

    function assessment(userName) {
    // 全文字のコード番号を取得してそれを足し合わせる
    let sumofCharCode = 0;
    for (let i = 0; i < userName.length; i++) {
    sumOfCharCode = sumofCharCode + userName.charCodeAt(i);
    }
    // 文字のコード番号の合計を回答の数で割って添字の数値を求める
    const index = sumOfCharCode % answers.length;
    const result = answers[index];
    // TODO {userName} をユーザーの名前に置き換える
    return result;
    }

    あとはfor文を使って、名前の全ての文字のコードを足し合わせています。

    const index = sumOfCharCode % answers.length;
    const result = answers[index];

    ここでは、名前から計算した文字コードの合計値を、診断結果のパターンの数で割った余りを求め、それを利用して配列から診断結果を取得しています。

    {userName}をユーザーの名前に置き換える

    最後に、「{userName}」をユーザーの名前に置き換えます。ここでは正規表現という機能を使います。まずはassessment関数内で宣言している定数 resultを変数に変更します。定数を宣言するためのキーワード「const」を「let」に書き換えましょう。次に、コメント 「TODO {userName} をユーザーの名前に置き換える」を削除し、変数 resultに埋め込まれている「{userName}」をユーザー名に置き換えるコードを入力します。

    入力するコードは次のようになります。

    let result = answers[index];] //「const」を「let」に変更//
    result = result.replace(/\{userName\}/g, userName);

    この、「ハ{userNamell/g」と書かれている部分が正規表現です。正規表現とは、さまざまな文字列のパターンを表現するための記述方法のことです。

    「1…/g」が正規表現の本体で、これは「1….」で囲まれた文字列と一致する部分を全て選択することを意味しています。なお、中身の「八」の部分は「{」を正規表現の中に書くための特別な記号(エスケープシーケンス)です。「」の部分も同様です。

    result=result.replace(/\{userName\}/g, userName);

    つまりこの記述は、result 内の{userName}という文字列のパターンを全て選択し、それら全てを変数 userName の表す部分文字列に置き換えています。そうして新たにできた文字列を変数 result に再代入しているのです。

    なお、resultを宣言するときの修飾子を constから let に変えました。これは、先ほどまではresult は一度代入されたら再代入されない定数だったのに対して、今回はresult.replace()という関数の戻り値を再代入しているからです。

    正規表現について調べる

    JavaScriptの正規表現の詳しい説明は、MDNの日本語の解説サイト (https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions) & BRELて下さい。また、GoogleやYahoo!で「正規表現 JavaScriptサンプル」と検索することで、正規表現のさまざまな活用例を見られます。

    テストを書いてみよう

    これまで、機能の確認には「console.log」を使い、そのログ出力を目視で確認してきました。この方法だと、人間が確認している以上、もしかしたら間違いを見落としてしまうかもしれません。たとえば、本来は

    太郎のいいところは決断力です。太郎がする決断にいつも助けられる人がいます。

    と出力されなくてはいけないところが、

    太郎のいいところは決断力です。次郎がする決断にいつも助けられる人がいます。

    と誤って出力されてしまっていた場合に、間違いに確実に気づけるかどうか不安です。

    こんなときのために、処理の結果が意図したとおりになっているかをテストする機能が、JavaScript には備わっています。それが「console.assert」という関数です。

    診断機能の開発と、Webページへの表示は完成しました。ここでは、Web

    ページに表示された診断結果をツイートできるようにします。

    ツイートボタンを作ってみよう

    ツイートボタンは、Twitter の公式サイトにて、ボタンを作成するためのHTMLタグが提供されています。Googleなどの検索サイトで「Twitterボタン」と検索して、Twitter が公式で提供している Twitter ボタン作成サイト (https://publish.twitter.com/#) を開いて下さい。

    今回は、ハッシュタグを付けてツイートできるようにしたいので、「#あなたのいいところ」と入力して下さい。なお、「#」は半角で入力するようにして下さい。入力し終わったら、右側にある→をクリックして下さい。

    カスタマイズする画面が開いたら、「Do you want to prefill the Tweet text?」という一番上の欄に「診断結果の文章」などと入力します。「診断結果の文章」の部分は、後で実際の診断結果に置き換えるため、自分がわかるようであれば何と入力しても構いません。
    入力が完了したら右下の「Update」をクリックします。

    先ほどコピーした文字列をindex.htmlの<div id=”tweet-area”></div>の中に貼り付けてみましょう。無事に貼り付け終わったらTwitterボタン作成のページは閉じて構いません。

    <div id=”tweet-area”>
    <a
    href=”https://twitter.com/intent/tweet?button_hashtag=htTOLKIE3 &ref_src=twsrc%5Etfw”
    class=”twitter-hashtag-button”
    data-text=”TO”
    data-show-count=”false”
    >Tweet #tota TEDLICIEZZ</a>
    <script
    async
    src=”https://platform. twitter.com/widgets.js”charset=”utf-8″
    X</script>
    </div>

    ツイートボタンをプログラムから扱ってみよう

    先ほど見たとおり、TwitterからコピーしたHTMLは

    ・aタグ
    ・scriptタグ

    の2つから構成されていることがわかります。まずはaタグから見ていきましょう。

    <a
    href=”https://twitter.com/intent/tweet?button_hashtag= ts to あなたのいいところ&ref_src=twsrc%5Etfw”
    class=”twitter-hashtag-button”
    data-text=”診断結果の文章”
    data-show-count=”false”
    >Tweet #あなたのいいところ</a>

     

    <script
    async src=”https://platform.twitter.com/widgets.js”
    charset=”utf-8″
    ></script>

    先ほどassessment.htmlに貼り付けたaタグと scriptタグを削除し、assessment.htmlを以下のようにします。

    <body>
    <h1> あなたのいいところは?</h1>
    <p> 診断したい名前を入れて下さい </p>
    <input type=”text” id=”user-name” size=”40″ maxlength=”20″>
    <button id=”assessment”>診断する</button>
    <div id=”result-area”></div>
    <div id=”tweet-area”></div>
    <script src=”assessment.js”></script>
    </body>
    </html>

    seikaku.js内に書いたコメント「IN TODOツイートエリアの作成」と removeAllChildren関数の下の行に、次のようにコードを追加します。hrefValue と anchor.innerTextに代入するURLと文字列は、Twitter からコピーしたHTMLのものを使って下さい。

    seikaku.js

    // TODO ツイートエリアの作成
    removeAllChildren(tweetDivided);
    const anchor document.createElement(‘a’);
    const hrefValue =
    ‘https://twitter.com/intent/tweet?button_hashtag= あなたのいいとろ&ref_src=twsrc%5Etfw’;
    anchor.setAttribute(‘href’, hrefValue);
    anchor.className = ‘twitter-hashtag-button’;
    anchor.setAttribute(‘data-text’, ‘診断結果の文章’);
    anchor.innerText = ‘Tweet # あたたのいいところ’;
    tweetDivided.appendChild(anchor);

    なお、class属性については setAttribute() を用いず、anchor.className というプロバ

    ティに値を設定しています。hrefなどほかの属性と異なり、class属性とid属性に関し、

    てはそれぞれ専用のプロパティが用意されているからです。

    複数のclassを管理する場合

    HTMLの要素には複数の classを持たせることができます。たとえば、以下のようなHTMLタグを書くことができます。

    <a href=”https://nnn.ed.nico/” class=”nnn-link large-buttongreen-text”>N 予備校へアクセス</a>

    こうした複数の classをJavaScript から管理する場合は classList を使うことができま

    す。追加する場合は以下のように add()メソッドを使います。

    const anchor = document.createElement(‘a’);
    anchor.classList.add(‘nnn-link’);
    anchor.classList.add(‘large-button’, ‘green-text’); // 複数のclassを一度に追加することもできる

    ここまで入力できたら、Chromeで assessment.html を再読み込みして、動作を確認してみましょう。ただのaタグが表示されたと思います。このaタグをクリックすると、ツイートを実行することができます。

    続いてseikaku.jsスクリプトを設定し実行するコードを追加します。

    const script document.createElement(‘script’);
    script.setAttribute(‘ src’, ‘https://platform.twitter.com/widgets.js’);
    tweetDivided.appendChild(script);

    これにより読み込んだ widgets.jsが動作し、ただのリンクで表示されていた部分が、Twitter のボタンのような見た目になります。

    Chromeで再読み込みして確認してみましょう。

    URIエンコードとは

    URLエンコードとは、URIのクエリに含めることのできない文字のために、それらの文字を % (パーセント)という記号からはじまる16進数で表現するための変換方法のことです。URLエンコードやパーセントエンコーディングなどということもあります。

    JavaScriptでは、以下の2つの関数で「文字列を URIエンコードに変換」と「URI エンコードから文字列に復元」することができます。

    encodeURIComponent関数で文字列をURIエンコードされたものへ変換

    decodeURIComponent関数でURIエンコードされた文字列から元のものへ復元

    Chromeのデベロッパーツールのコンソールで動作を試してみましょう。

    encodeURIComponent(‘あ’);
    > “%E3%81%82”
    decodeURIComponent(‘%E3%81%82’);
    > “あ”

    1行目と3行目のコードを入力してEnter]キーを押すと、2行目・4行目のように、文字列が変換・復元されます。

    それでは、URIエンコードを使ってハッシュタグを「#あなたのいいところ」になるようにコードを下記のように変えましょう。

    const hrefValue =
    ‘https://twitter.com/intent/tweet?button_hashtag=’ +
    encodeURIComponent(‘あなたのいいところ’) +
    ‘&ref_src=twsrc%5Etfw’;

    ツイートの文章に診断結果をのせてみよう

    なお、この時点ではツイートに診断結果が組み込まれないはずです。

    data-text属性の箇所を見てみましょう。

    anchor.setAttribute(‘data-text’, ‘診断結果の文章’);

    先ほど設定した診断結果の文章がここに設定されています。ツイートの文章を実際の診断結果にするため、コードを下記のように変えましょう。

    anchor.setAttribute(‘data-text’, result);

    ここでは、ツイートの文章を、診断結果が入っている変数 result に変えています。

    よかったらシェアしてね!
    • URLをコピーしました!
    目次