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 コール数も増え、「処理中のレコード件数」を表示するまでに多少の時間を要するようになってきます。
そこで、処理中ということが分かるようにスピナーを表示させたいと思います。

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

スピナーを表示、非表示させる関数を準備します。
これらの関数を呼び出せるように宣言しておけば、あとは showSpinner で表示、hideSpinner で非表示できます。
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 で動作を確認しています。