第 15 回 kintone JavaScript カスタマイズのプログラム実例を学ぼう③(経過年数を表示する)

著者名: 村濱 一樹 (External link) (kintone エバンジェリスト)

目次

information

JavaScript 初心者がカスタマイズに必須の知識をより学べるよう、チュートリアルの内容を充実させてリニューアルしました。
リニューアル後のチュートリアルは次のページを参照してください。
はじめよう JavaScript

はじめに

前回は条件書式のサンプルをもとに Style の変更について学びました。
今回はイベント詳細ページにボタンを設置し、押したときに任意の処理をさせるプログラムについて学んでいきましょう。

題材

今回は 経過年数を表示する というサンプルプログラムについて学んでいきましょう。
kintone アプリは、kintone アプリストアにある「 社員名簿 (External link) 」を使っています。

ボタンの設置とそのボタンを押したときのイベントや時間の計算は、次のライブラリを使って作成されています。

  • jQuery
  • Luxon

プログラム

プログラムは下記です。少しずつピックアップして、内容を解説していきます。

 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
/*
 * Luxon sample program
 * Copyright (c) 2022 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(() => {
  'use strict';
  kintone.events.on('app.record.detail.show', (event) => {
    const record = event.record;

    const birthDayFieldCode = 'BirthDay';
    const spaceFieldCode = 'BirthDay';
    const joiningDayFieldCode = 'JoiningDate';

    /**
     * 経過年月日を計算する
     * @param {string} dateStr 日付文字列
     * @returns {object} 計算結果のオブジェクト
     */
    const calculateDuration = function(dateStr) {
      const currentDate = luxon.DateTime.local().startOf('day');
      const date = luxon.DateTime.fromISO(dateStr).startOf('day');
      // 経過期間を計算する
      const duration = currentDate.diff(date, ['years', 'months', 'days']);
      return duration.toObject();
    };

    // 入社からの経過年月日を表示する
    const joiningDayValue = record[joiningDayFieldCode].value;
    if (joiningDayValue) {
      const joiningDayDuration = calculateDuration(joiningDayValue);
      const joiningDayElement = kintone.app.record.getFieldElement(joiningDayFieldCode);
      const $emLabel = $('<label>');
      const $emDiv = $('<span>');

      $(joiningDayElement).append($emDiv);
      $(joiningDayElement).css({
        width: $(joiningDayElement).innerWidth() + 50 + 'px',
      });

      $emDiv.append($emLabel);
      $emLabel.html('<br>');
      $emLabel.append(
        joiningDayDuration.years + '年' + joiningDayDuration.months + 'ヶ月'
      );

      $emDiv.css({
        color: 'blue',
      });
    }

    // 年齢を計算する
    const birthDayValue = record[birthDayFieldCode].value;
    if (birthDayValue) {
      const birthDayDuration = calculateDuration(birthDayValue);
      const bitrhDayButtonElement = kintone.app.record.getSpaceElement(spaceFieldCode);
      const $emButton = $('<button>', {
        id: 'age_button',
        text: '年齢計算',
      }).on('click', () => {
        alert(birthDayDuration.years + '歳です。');
      });
      $(bitrhDayButtonElement).append($emButton);
    }

    return event;
  });
})();

全体の構成

まずは全体の構成をみていきましょう。
大まかに分けて「日時計算のための関数」と「レコード詳細画面の表示後の処理」があります。

  • 日時計算のための関数

    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    /**
     * 経過年月日を計算する
     * @param {string} dateStr 日付文字列
     * @returns {object} 計算結果のオブジェクト
     */
    const calculateDuration = function(dateStr) {
      const currentDate = luxon.DateTime.local().startOf('day');
      const date = luxon.DateTime.fromISO(dateStr).startOf('day');
      // 経過期間を計算する
      const duration = currentDate.diff(date, ['years', 'months', 'days']);
      return duration.toObject();
    };
  • レコード詳細画面の表示後の処理

    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
    
    // 入社からの経過年月日を表示する
    const joiningDayValue = record[joiningDayFieldCode].value;
    if (joiningDayValue) {
      const joiningDayDuration = calculateDuration(joiningDayValue);
      const joiningDayElement = kintone.app.record.getFieldElement(joiningDayFieldCode);
      const $emLabel = $('<label>');
      const $emDiv = $('<span>');
    
      $(joiningDayElement).append($emDiv);
      $(joiningDayElement).css({
        width: $(joiningDayElement).innerWidth() + 50 + 'px',
      });
    
      $emDiv.append($emLabel);
      $emLabel.html('<br>');
      $emLabel.append(
        joiningDayDuration.years + '年' + joiningDayDuration.months + 'ヶ月'
      );
    
      $emDiv.css({
        color: 'blue',
      });
    }
    
    // 年齢を計算する
    const birthDayValue = record[birthDayFieldCode].value;
    if (birthDayValue) {
      const birthDayDuration = calculateDuration(birthDayValue);
      const bitrhDayButtonElement = kintone.app.record.getSpaceElement(spaceFieldCode);
      const $emButton = $('<button>', {
        id: 'age_button',
        text: '年齢計算',
      }).on('click', () => {
        alert(birthDayDuration.years + '歳です。');
      });
      $(bitrhDayButtonElement).append($emButton);
    }
    
    return event;

使われているライブラリについて

コードを見ていく前に、今回使われているライブラリについて簡単に説明します。
今回紹介しているサンプルの記事にも掲載されていますが、 Cybozu CDN より次のライブラリを使用します。

Luxon

Luxon を使うことで日付の計算やフォーマッティングが簡単になります。
詳細は、 公式サイト (External link) を確認ください。

今回のサンプルでは、次の関数が使われています。

  • luxon.DateTime.local().startOf('引数')
    現時点の日時のオブジェクトを作成します。
    startOf() の引数には year, month, day などを指定できます。
  • luxon.DateTime.fromISO(引数 1).startOf('引数 2');
    引数 1 で指定された日時のオブジェクトを作成します。
    startOf() の引数には year, month, day などを指定できます。
  • diff(引数 1, 引数 2)
    引数 1 との日時の差を取得します。
    引数 2 には years, months, days などを指定できます。
  • toObject()
    日時のオブジェクトを返します。

jQuery

jQuery を使うことでボタンの追加やスタイルの調整などがしやすくなります。
詳細は、 公式サイト (External link) を確認ください。

jQuery をつかった kintone のカスタマイズは 第 12 回 jQuery を利用してみよう を参照してください。

  • ボタンの作成例

    1
    2
    3
    4
    
    const $emButton = $('<button>', {
      id: 'age_button',
      text: '年齢計算'
    })
  • Style の変更

    1
    2
    3
    
    $emDiv.css({
      color: 'blue',
    });

関数の作成

さて、それでは実際のコードをみていきましょう。
今回のサンプルコードでは、日時計算の処理が関数化されています。

  • 現在の日時と、引数で指定した日時のオブジェクトを取得する。

    24
    25
    
    const currentDate = luxon.DateTime.local().startOf('day');
    const date = luxon.DateTime.fromISO(dateStr).startOf('day');
  • diff() を使って差分を取得する。

    26
    27
    28
    
    // 経過期間を計算する
    const duration = currentDate.diff(date, ['years', 'months', 'days']);
    return duration.toObject();

この calculateDuration ですが、指定した日からの今日までの日付の計算が行われ、何年何ヵ月という形式で文字列が返却されます。

18
19
20
21
22
23
24
25
26
27
28
29
/**
 * 経過年月日を計算する
 * @param {string} dateStr 日付文字列
 * @returns {object} 計算結果のオブジェクト
 */
const calculateDuration = function(dateStr) {
  const currentDate = luxon.DateTime.local().startOf('day');
  const date = luxon.DateTime.fromISO(dateStr).startOf('day');
  // 経過期間を計算する
  const duration = currentDate.diff(date, ['years', 'months', 'days']);
  return duration.toObject();
};

レコード詳細画面の表示後イベントのプログラム

レコード詳細画面の表示後イベントのプログラムを、さらに細かく分けてみましょう。

次のとおり、2 つの処理に分けることができます。それぞれみていきましょう。

  1. 入社してからの経年年数を表示

    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    
    // 入社からの経過年月日を表示する
    const joiningDayValue = record[joiningDayFieldCode].value;
    if (joiningDayValue) {
      const joiningDayDuration = calculateDuration(joiningDayValue);
      const joiningDayElement = kintone.app.record.getFieldElement(joiningDayFieldCode);
      const $emLabel = $('<label>');
      const $emDiv = $('<span>');
    
      $(joiningDayElement).append($emDiv);
      $(joiningDayElement).css({
        width: $(joiningDayElement).innerWidth() + 50 + 'px',
      });
    
      $emDiv.append($emLabel);
      $emLabel.html('<br>');
      $emLabel.append(
        joiningDayDuration.years + '年' + joiningDayDuration.months + 'ヶ月'
      );
    
      $emDiv.css({
        color: 'blue',
      });
    }
  2. 年齢計算ボタンの作成と設置
    ここでは、ボタンを作成し、クリックしたときのイベントを定義しています。
    最後にボタンを生年月日フィールドに追加しています。

    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    
    // 年齢を計算する
    const birthDayValue = record[birthDayFieldCode].value;
    if (birthDayValue) {
      const birthDayDuration = calculateDuration(birthDayValue);
      const bitrhDayButtonElement = kintone.app.record.getSpaceElement(spaceFieldCode);
      const $emButton = $('<button>', {
        id: 'age_button',
        text: '年齢計算',
      }).on('click', () => {
        alert(birthDayDuration.years + '歳です。');
      });
      $(bitrhDayButtonElement).append($emButton);
    }

上記 2 つの処理の中に、書式変更したいフィールドの要素を取得する関数も使われています。
次の関数を使うことで、該当の要素を取得できます。

1
2
3
4
5
 // 入社年月日
const joiningDayElement = kintone.app.record.getFieldElement(joiningDayFieldCode);

 // 生年月日
const bitrhDayButtonElement = kintone.app.record.getSpaceElement(spaceFieldCode);

まとめ

今回はボタンを追加したり時間の計算をしたりと、JS カスタマイズにおいてよく行う処理について学ぶことができたと思います。
必要に応じて、jQuery や Luxon については公式ページや cybozu developer network などで検索してみてください。

information

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