InputManJSのツアーコンポーネントを使用してわかりやすい画面操作ガイドを実装する

日本仕様の入力用JavaScriptコントロールセット「InputManJS(インプットマンJS)」の「V6J」では、画面上の各入力要素を順番にガイドし、ツールチップで入力方法や操作手順を分かりやすく案内する「ツアーコンポーネント(GcTour)」が追加されています。

ツアーコンポーネント

本記事では、ツアーコンポーネントの基本的な使い方とカスタマイズの方法について紹介します。

開発環境の準備とInputManJSの参照

今回は開発環境として以下を使用します。

作成するファイルは以下の3つです。

index.htmlページ本体。ページの要素としてGcTextBoxとGcMaskを配置します
app.jsGcTextBox、GcMask、GcTour、GcValidatorを作成するコードを記載します
style.css各種ページ要素のスタイル定義を記載します

GcTourコンポーネントなどのInputManJSの各種コントロールを使用するには、InputManJSのモジュールを環境にインストールする必要があります。CDNを参照したり、npmなどから入手したりする方法もありますが、今回は環境に直接モジュールを配置していきます。あらかじめInputManJSの製品版かトライアル版をご用意ください。トライアル版は以下より無償で入手可能です。

製品版、またはトライアル版をダウンロードしたら、ZIPファイルを解凍し、以下のファイルを環境にコピーします。

  • css/gc.inputman-js.css
  • scripts/gc.inputman-js.ja.js

ツアーコンポーネントを実装する

それではツアーコンポーネントを実装するサンプルを作成していきます。ここでは、入力コントロールとしてGcTextBoxコントロールとGcMaskコントロールを使います。

最初に、前述の各モジュールと「app.js」および「styles.css」への参照設定をHTMLファイルに追加します。
※ CDNから参照する場合はコメントアウトされている部分とライブラリの参照先を入れ替えてください。

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>InputManJSのツアーコンポーネント</title>

  <!-- ローカルのライブラリを参照する場合 -->
  <link rel="stylesheet" href="css/gc.inputman-js.css" />
  <script src="scripts/gc.inputman-js.ja.js"></script>

  <!-- CDNからライブラリを参照する場合 -->
  <!-- <link rel="stylesheet" href="https://cdn.mescius.com/inputmanjs/hosted/css/gc.inputman-js.css">
  <script src="https://cdn.mescius.com/inputmanjs/hosted/scripts/gc.inputman-js.ja.js"></script> -->

  <link rel="stylesheet" href="css/styles.css" />
  <script src="scripts/app.js"></script>
</head>

<body>
  <div class="container">
    <div><button type="button" id="start">入力ガイドを開始</button></div>
    <div><input id="gcTextBox1" class="required"></div>
    <div><input id="gcTextBox2" class="required"></div>
    <div><input id="gcMask1"></div>
  </div>
</body>

</html>

続いて「app.js」を以下のように作成します。
※ ライセンスキーを設定しない場合トライアル版を示すメッセージが表示されます。ライセンスキーの入手や設定方法についてはこちらをご覧ください。

このコードでは、GcTextBoxコントロール(gcTextBox1とgcTextBox2)、GcMaskコントロール(gcMask1)、およびGcTourコンポーネント(gcTour1)を生成します。gcTour1がガイドの対象とするのはgcTextBox1、gcTextBox2、gcMask1の3つの入力コントロールです。

入力コントロールには未入力時に表示する代替テキストやフローティングラベルを設定し、gcTour1のstepsプロパティにはITourStep インターフェイスの5つのプロパティを設定します。

プロパティ説明
targetステップが対象とするコントロール
titleツールチップに表示するステップのタイトル
descriptionツールチップに表示するステップの説明
messageツールチップに表示するメッセージ
autoFocusTarget対象コントロールにフォーカスを自動設定するかどうか

なお、下記の「・・・(中略)・・・」については以降の項目で解説します。

// ライセンスキーの設定
// GC.InputMan.LicenseKey = 'ここにInputManJSのライセンスキーを設定します';

var gcTextBox1;
var gcTextBox2;
var gcMask1;
var gcTour1;
var gcValidator1;

document.addEventListener("DOMContentLoaded", () => {
  // InputManJSコントロールのデザインの指定
  GC.InputMan.appearanceStyle = GC.InputMan.AppearanceStyle.Modern;

  // コントロールの生成と設定
  setControl();

  // GcTourの生成と設定
  setGcTour();

  // GcValidatorの生成と設定
  ・・・(中略)・・・
});

// コントロールの生成と設定
const setControl = () => {
  // ツアーガイドの開始
  document.getElementById("start").addEventListener("click", () => {
    gcTour1.start();
  })

  // 入力コントロールの生成と設定
  gcTextBox1 = new GC.InputMan.GcTextBox(
    document.getElementById("gcTextBox1"),
    {
      floatingLabelType: GC.InputMan.FloatingLabelType.Always,
      floatingLabelText: "名前(必須)",
      watermarkDisplayNullText: "例)入力太郎",
      width: 350,
    }
  );
  gcTextBox2 = new GC.InputMan.GcTextBox(
    document.getElementById("gcTextBox2"),
    {
      floatingLabelType: GC.InputMan.FloatingLabelType.Always,
      floatingLabelText: "メールアドレス(必須)",
      width: 350,
    }
  )
  gcMask1 = new GC.InputMan.GcMask(
    document.getElementById("gcMask1"),
    {
      floatingLabelType: GC.InputMan.FloatingLabelType.Always,
      floatingLabelText: "電話番号(任意)",
      formatPattern: '\\D{2,4}-\\D{2,4}-\\D{4}',
      width: 350,
    }
  )
};

// GcTourコンポーネントの生成と設定
const setGcTour = () => {
  gcTour1 = new GC.InputMan.GcTour({
    steps: [
      {
        title: '<div style="color: green;">登録フォームへようこそ<div>',
        description: "ガイドに従って各項目を入力してください。",
        message: '<div style="color: silver;">'
          + "ガイドを中止するには、右上の[×]ボタンをクリックするか[Esc]キーを押下します。"
          + "<div>",
      },
      {
        target: gcTextBox1,
        title: `<div style="color: blue;">${gcTextBox1.floatingLabelText}<div>`,
        description: "名前を全角で入力してください。",
        autoFocusTarget: true,
      },
      {
        target: gcTextBox2,
        title: `<div style="color: blue;">${gcTextBox2.floatingLabelText}<div>`,
        description: "メールアドレスを半角で入力してください。",
        autoFocusTarget: true,
      },
      {
        target: gcMask1,
        title: gcMask1.floatingLabelText,
        description: "電話番号を半角で入力してください。",
        message: '<div style="color: silver;">'
          + "この項目は省略することができます。"
          + "<div>",
        autoFocusTarget: true,
      },
    ],
    // カスタムチップの設定
    ・・・(中略)・・・
  });

  // ツールチップにラジオボタンを設定
  ・・・(中略)・・・

  // ステップ切り替え時に検証を実行
  ・・・(中略)・・・

// GcValidatorコントロールの生成と設定
・・・(中略)・・・

最後に「styles.css」にスタイルを記述します。

/* 入力コントロールのスタイル */
.gcim_watermark_null {
  color: silver;
}

.gcim-floating-label__container {
  color: silver;
}

.required .gcim-floating-label__container {
  color: blue;
}

/* GcTourのスタイル */
・・・(中略)・・・

/* InputManJS以外のスタイル */
body {
  display: flex;
  align-items: center;
  justify-content: center;
}

.container {
  border: 1px solid silver;
  block-size: 300px;
  inline-size: 480px;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 25px;
}

以上を記述した後にアプリケーションを実行し、[入力ガイドを開始]ボタンをクリックすると、ツアーガイドが開始されます。ツールチップ内の[次へ]ボタンまたは[前へ]ボタンをクリックすると前後のステップへ移動し、最後のステップで[完了]ボタンをクリックするとツアーガイドを終了します。

ツアーガイドの開始と終了

ツアーコンポーネントのツアーガイドを開始するには、GcTourクラスのstartメソッドを実行し、ツアーガイドを終了するときはcloseメソッドを実行します。

このサンプルでは、<button>要素(id="start")がクリックされたときにGcTourクラスのstartメソッドを呼び出してツアーガイドを開始しています。

ツアーガイドを終了する方法については、既定ではツアーコンポーネントのツールチップがモーダル表示なので、ツールチップ外のコントロールを操作してツアーガイドを終了することはできません。そのためcloseメソッドを使ってツアーガイドを独自の方法で終了するには、デモで紹介しているようにツールチップをカスタマイズしてツールチップ内に実装する必要があります。

また、ユーザー操作によってツアーガイドを終了できるように、GcTourクラスには次の3つのプロパティが用意されています。これらの動作については、こちらのデモで確認できます。

プロパティ説明既定値
closeOnEscESCキー押下による終了true
closeOnOverlayClick空白領域のクリックによる終了false
showCloseButton閉じるボタンを表示true

ツールチップのカスタマイズ

続いてツアーガイドが開始されたときに表示されるツールチップをカスタマイズします。

ツールチップのスタイルはヘルプに記載しているCSSを設定することで変更できます。ここでは.gcim__tour-done-btnを設定して[完了]ボタンの背景色とホバー色を変更します。

/* GcTourのスタイル */
.gcim__tour-done-btn {
  background-color: green;
}

.gcim__tour-done-btn:hover {
  background-color: rgb(0 128 0 / 0.75);
}

また、ヘルプデモで解説しているように、GcTourクラスのcustomTipプロパティを使ってツールチップ上に表示する要素を変更できます。次のコードは、ツールチップ上の左下のインジケータをラジオボタンに置き換えて、ユーザーが移動先を直接指定できるようにします。

移動先ステップの指定は、ラジオボタン用に生成したdiv要素のchangeイベント内でGcTourクラスのgoToメソッドを呼び出すことで行います。

const setGcTour = () => {
  gcTour1 = new GC.InputMan.GcTour({
    ・・・(中略)・・・
    // カスタムチップの設定
    customTip: (context) => {
      context.dom.progress.replaceWith(renderProgress(context.tour));
    },
  });

  // ツールチップにラジオボタンを設定
  const renderProgress = (tour) => {
    const progress = document.createElement("div");
    let radio = "";
    for (let i = 0; i < tour.length; i++) {
      if (i === tour.activeIndex) {
        radio += `<input type="radio" name="tour" value=${i} checked>`
      } else {
        radio += `<input type="radio" name="tour" value=${i}>`
      }
    }
    progress.innerHTML = radio;
    progress.id = "radiogroup";
    progress.addEventListener("change", (e) => {
      tour.goTo(Number(e.target.value));
    });
    return progress;
  };

  // ステップ切り替え時に検証を実行
  ・・・(中略)・・・
}

以下は、カスタマイズする前と後のツールチップです。

カスタマイズ前

カスタマイズ前

カスタマイズ後

カスタマイズ後

検証コントロールとの連携

最後に、ツアーコンポーネントを検証コントロール(GcValidator)と連携させて検証結果をツールチップに表示し、検証に失敗したときには他のステップへの移動を禁止する方法を紹介します。

「app.js」で省略していた箇所に次のようなコードを記述して、検証コントロールの生成とツアーコンポーネントとの連携を行います。

追加するコードで行う処理:

  • 検証コントロールの生成
  • 検証コントロールのValidationFailedイベントとValidationSucceededイベントの実装
  • ツアーコンポーネントのStepChangedイベントの実装

ステップが移動したときに、ツアーコンポーネントのStepChangedイベントで検証コントロールのvalidateメソッドを呼び出して検証を実行します。そして検証時に発生する検証コントロールのValidationFailedイベントまたはValidationSucceededイベントでツールチップの表示と動作を切りかえます。

document.addEventListener("DOMContentLoaded", () => {
  ・・・(中略)・・・
  // GcValidatorの生成と設定
  setGcValidator();
});

// コントロールの生成と設定
・・・(中略)・・・

// GcTourコンポーネントの生成と設定
const setGcTour = () => {
  ・・・(中略)・・・
  // ステップ切り替え時に検証を実行
  gcTour1.addEventListener(GC.InputMan.GcTourEvent.StepChanged, (s, e) => {
    gcValidator1.validate(e.newStep.target);
  });
}

// GcValidatorコントロールの生成と設定
const setGcValidator = () => {
  gcValidator1 = new GC.InputMan.GcValidator({
    items: [
      {
        control: gcTextBox1,
        ruleSet: [{
          rule: GC.InputMan.ValidateType.Required,
          failMessage: "必須項目です!",
        }],
        validateWhen: GC.InputMan.ValidateWhen.Typing,
      },
      {
        control: gcTextBox2,
        ruleSet: [
          {
            rule: GC.InputMan.ValidateType.Required,
            failMessage: "必須項目です!",
          },
          {
            rule: (control) => {
              const regexp =
                /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/;
              return regexp.test(control.value);
            },
            failMessage: "メールアドレスの形式が不正です!",
          },
        ],
        validateWhen: GC.InputMan.ValidateWhen.Typing,
      }
    ],
    defaultNotify: {
      fail: {
        icon: {
          direction: GC.InputMan.IconDirection.Outside,
        }
      },
    },
  });

  // 検証失敗
  const failedEvent = GC.InputMan.GcValidatorEvent.ValidationFailed;
  gcValidator1.addEventListener(failedEvent, (s, e) => {
    const step = gcTour1.steps.find(item => item.target === e.control);
    if (step === gcTour1.steps[gcTour1.activeIndex]) {
      // エラーメッセージの表示と移動の禁止   
      step.message = `<div style="color: red;">${e.context.failMessage}<div>`;
      step.disableNextButton = true;
      step.disablePreviousButton = true;
      const children = document.getElementById("radiogroup").childNodes;
      children.forEach((node) => {
        node.disabled = true;
      });
    }
  });

  // 検証成功
  const succeededEvent = GC.InputMan.GcValidatorEvent.ValidationSucceeded;
  gcValidator1.addEventListener(succeededEvent, (s, e) => {
    const step = gcTour1.steps.find(item => item.target === e.control);
    if (step === gcTour1.steps[gcTour1.activeIndex]) {
      // エラーメッセージの削除と移動の許可   
      step.message = "";
      step.disableNextButton = false;
      step.disablePreviousButton = false;
      const children = document.getElementById("radiogroup").childNodes;
      children.forEach((node) => {
        node.disabled = false;
      });
    }
  });

  // 検証の実行
  gcValidator1.validate();
}

以上を記述してアプリケーションを実行すると下のようになります。

「名前」と「メールアドレス」は必須項目なので未入力時にはツールチップ上に警告メッセージが表示されます。また、「メールアドレス」では入力された文字列が適切でない場合にも警告メッセージが表示されます。警告メッセージが表示されている状態では、他のステップへの移動を抑止するためにラジオボタン、[前へ]ボタン、および[次へ]ボタンが不活性になります。適切な値が入力されると、警告メッセージが消えて他のステップへの移動が可能になります。

今回ご紹介したGcTourコントロールの機能は以下のデモアプリケーションでも確認できます(“Run Project”をクリックするとデモが起動します)。

さいごに

今回の記事では、「InputManJS」に含まれるツアーコンポーネントの基本的な使い方とツールチップをカスタマイズする方法、および検証コントロールと組み合わせる方法についてご紹介しました。

InputManJSは、リッチテキスト、テキスト、マスク、日付時刻、数値、コンボなど用途別に最適化された入力用コントロールを収録したJavaScript製品です。Webアプリケーションにおけるストレスフリーのきめ細かい入力フォームの開発に、ぜひInputManJSをご検討いただければと思います。

製品サイトでは、InputManJSの機能を手軽に体験できるデモアプリケーションやトライアル版も公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。

\  この記事をシェアする  /