spin.jsを使って、スピナー(ローディングアイコン)を設定しよう!

目次

はじめに

今回は Cybozu CDNにストックされた spin.js (External link) を使ったスピナーの設定をしたいと思います。

デモ環境

デモ環境 (External link) で実際に動作を確認できます。
ログイン情報は cybozu developer networkデモ環境で確認してください。

spin.js

spin.js (External link) は、スピナー(スピンアイコン、ローディングアイコン、処理中表示)を設置するためのライブラリです。
ストックされたCDNを見てもわかるとおり、CSSやjQueryを伴わずJavaScriptのみで取扱いできることが特長とされています。

今回の適用方法・シナリオ

spin.jsの基本的な使い方は、設置する要素を設定してスタート/ストップをかけるという流れになります。
今回は、kintoneでの利用ですので、REST APIの処理量が大きくなった時の「処理中」に表示します。
そして、処理が終わったら非表示にするということをやってみたいと思います。

今回のカスタマイズは、落合雄一さんが執筆されている「 一覧画面で条件に応じたレコード件数を取得するテクニック」に適用してみます(まったく同様のアプリではないためqueryは変更しています)。
こちらでは、レコード総数が100件を超えるアプリに対して処理中レコードをカウントできますが、レコード総数が増えてくるとAPIコール数も増え、「処理中のレコード件数」を表示するまでに多少の時間を要するようになってきます。
そこで、処理中ということが分かるようにスピナーを表示させたいと思います。

準備(スピナー表示/非表示関数)

スピナーを表示、非表示させる関数を準備します。
これらの関数を呼び出せるように宣言しておけば、あとはshowSpinnerhideSpinnerを使ってスピナーの表示を切り替えできます。
spin.jsの元の特長を極力損なわず、CSSの指定をし直さなくてよいようこれらの関数中でスタイルを指定しておきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
 * Spinner
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
*/

(() => {
  'use strict';

  // 一覧画面
  kintone.events.on('app.record.index.show', async (event) => {
    showSpinner(); // スピナー表示

    // kintone-rest-api-clientを使う準備
    const client = new KintoneRestAPIClient();
    // 絞り込み条件
    const query = kintone.app.getQueryCondition() ? `${kintone.app.getQueryCondition()} and status in ("処理中")` : 'status in ("処理中")';
    // kintone-rest-api-clientのgetAllRecordsを使って全レコードを取得する
    const res = await client.record.getAllRecords({app: kintone.app.getId(), condition: query});
    kintone.app.getHeaderMenuSpaceElement().textContent = `処理中のレコード件数: ${res.length}`;

    hideSpinner(); // スピナー非表示

    return event;

  });
})();

/**
* スピナー設置用の関数
**/
// スピナーを動作させる関数
const showSpinner = () => {
  // 要素作成等初期化処理
  if (document.getElementsByClassName('.kintone-spinner').length === 0) {

    // スピナー設置用要素の作成
    const spinDiv = document.createElement('div');
    spinDiv.id = 'kintone-spin';
    spinDiv.classList.add('kintone-spinner');

    // スピナーと背景要素の作成
    const spinBgDiv = document.createElement('div');
    spinBgDiv.id = 'kintone-spin-bg';
    spinBgDiv.classList.add('kintone-spinner');

    // スピナー用要素をbodyにappend
    document.body.appendChild(spinDiv);
    document.body.appendChild(spinBgDiv);

    // スピナー動作に伴うスタイル設定
    spinDiv.style.cssText = 'position: fixed; top: 50%; left: 50%; z-index: 510; background-color: #fff; padding: 26px; border-radius: 4px;';
    spinBgDiv.style.cssText = 'position: fixed; top: 0px; left: 0px; z-index: 500; width: 100%; height: 100%; background-color: #000; opacity: 0.5;';


    // スピナーに対するオプション設定
    const opts = {
      color: '#000'
    };

    // スピナーを作動
    new Spinner(opts).spin(document.getElementById('kintone-spin'));
  }

  document.querySelectorAll('.kintone-spinner').forEach(element => {
    element.style.display = 'block';
  });
};

// スピナーを停止させる関数
const hideSpinner = () => {
  // スピナー停止(非表示)
  document.querySelectorAll('.kintone-spinner').forEach(element => {
    element.style.display = 'none';
  });
};

JavaScript/CSSの設定

「PC用のJavaScriptファイル」に、URL指定で次のライブラリを順番に指定します。

  • spin.js
    https://js.cybozu.com/spinjs/2.3.2/spin.min.js
  • kintone REST API Client
    https://js.cybozu.com/kintone-rest-api-client/5.0.5/KintoneRestAPIClient.min.js

上のサンプルコード(countRecords.js)をアップロードして追加します。

動作確認

APIをコールすると、スピナーが表示され、ユーザーに処理中ということを知らせています。

処理が終了すると、スピナーが消えて「処理中のレコード件数」が表示されます。

ポイントとなるスピナー設定箇所は次の部分です。
APIのコール前にshowSpinner、APIの処理終了後にhideSpinnerを記述しています。

 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 一覧画面
kintone.events.on('app.record.index.show', async (event) => {
  showSpinner(); // スピナー表示

  // kintone-rest-api-clientを使う準備
  const client = new KintoneRestAPIClient();
  // 絞り込み条件
  const query = kintone.app.getQueryCondition() ? `${kintone.app.getQueryCondition()} and status in ("処理中")` : 'status in ("処理中")';
  // kintone-rest-api-clientのgetAllRecordsを使って全レコードを取得する
  const res = await client.record.getAllRecords({app: kintone.app.getId(), condition: query});
  kintone.app.getHeaderMenuSpaceElement().textContent = `処理中のレコード件数: ${res.length}`;

  hideSpinner(); // スピナー非表示

  return event;
});

最後に

今回は、spin.jsを使った全画面イメージのスピナーの設定についてお届けしました。
今回のシナリオ(単純なレコード取得)ではあまり支障にはならないと思いますが、請求や勤怠データの翌月コピー等レコードの登録・更新時は途中でユーザー自身が別の操作に移ってしまったりするとトラブルの元になります。
処理中・処理完了がこのような形で表現されると間違い防止・ユーザビリティの向上につながっていくと思います。
ぜひお試しいただければと思います!

information

このTipsは、2024年2月版kintoneで動作を確認しています。