kintone JavaScript カスタマイズ CheatSheet

kintone カスタマイズをする際によく使うコードを集めてみました。

# JavaScript

## DOM操作

### テキストボックスとボタンの生成

```javascript
        // テキストボックスとボタンを生成
        let newText = document.createElement('input');
        newText.type = 'text';
        newText.id = 'text1';
        let newButton = document.createElement('button');
        newButton.id = 'button1';
        newButton.innerText = '検索';
        kintone.app.getHeaderMenuSpaceElement().appendChild(newText);
        kintone.app.getHeaderMenuSpaceElement().appendChild(newButton);
        // ボタンクリックイベント
        newButton.addEventListener('click', function(){
           console.log(newText.value); 
        });
```

### スペースに jQueryでボタンを設置する

```index.js
(function($){
    // 3. ボタン要素をJavaScriptで作成する。
    var objButton = function(elm){$(elm).append('<button id="kintone-event-test-button">ボタン</button>')};
    kintone.events.on('app.record.detail.show', function(){
        console.log('ボタン作成関数');
        // 2. kintone JavaScriptカスタマイズにて、kintone JavaScript API の [kintone.app.record.getSpaceElement(id)](https://developer.cybozu.io/hc/ja/articles/201942014#step6) 関数で、スペースフィールド[button]の要素を取得する。
        var elmButton = kintone.app.record.getSpaceElement('button');
        console.log('ボタン要素 => ', elmButton);
        // 4. 取得した要素に3.で作成したボタン要素を追加する。
        objButton(elmButton);
        // 5. ボタンを押した時に何かする処理を入れる。
        $('#kintone-event-test-button').on('click', function(){alert('Hi!')});
    });
})(jQuery);
```

# kintone

## kintone JavaScript API
kintoneのフロント側の処理に利用する標準APIです。
https://developer.cybozu.io/hc/ja/articles/360000361686

### 情報取得
https://developer.cybozu.io/hc/ja/articles/201942014


* アプリのIDを取得する

```javascript
var appId = kintone.app.getId();
```

* 現在開いているアプリのレコードIDを取得する

```javascript
const recordId = kintone.app.record.getId();
```


### 詳細画面

#### 詳細の空白スペースにボタンを設置する

```javascript
kintone.app.record.getHeaderMenuSpaceElement().appendChild(myDetailButton);
```

#### フィールド要素取得

```javascript
kintone.app.record.getFieldElement(myFieldEl);
```

#### スペースフィールドの要素を取得

```javascript
kintone.app.record.getSpaceElement(mySpaceEl);
```

#### 詳細画面のメニューの上側の空白部分にボタンを設置
[kintone UI Component](https://kintone.github.io/kintone-ui-component/latest/Getting-Started/QuickStart-Javascript/) 利用

```javascript
(function() {
    "use strict";
    /**
     * レコード詳細画面表示イベント 
     *
    */
    var kintoneEvent;
    (function () {
      kintone.events.on("app.record.detail.show", function (event) {
        kintoneEvent = event;
        var kintoneSpaceElement = kintone.app.record.getHeaderMenuSpaceElement();
        var button = new kintoneUIComponent.Button({ text: 'Submit' });
        console.log(button);
        kintoneSpaceElement.appendChild(button.render());

        button.on('click', function(e){
          viewAlert(kintoneEvent);
        });

        // 処理が少ない時は直接ここに書いても良い。
        // button.on('click', function(e){
        //   alert('kintone event =>' + e);
        // });

      });
    })();
    
    // イベントハンドラを受けての処理を記述
    var viewAlert = e => alert('kintone event =>' + e);

})();
```

### 一覧画面
一覧の空白スペースにボタンを設置する

```javascript
kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
```

### アプリアクション
アプリアクションの動作をプログラムから実行する。

* action=<アプリアクションID>

アプリアクションIDは、[2021年3月のアップデート](https://developer.cybozu.io/hc/ja/articles/900005199263)で追加された、APIから取得しても良い。
[アプリのアクション設定の取得](https://developer.cybozu.io/hc/ja/articles/900005245783)


```javascript
(function() {
  'use strict';
  kintone.events.on('app.record.detail.show', function(event) {
    const ref = kintone.app.record.getFieldElement('関連レコード一覧');
    ref.addEventListener('click', () => {
      const recordId = kintone.app.record.getId();
      window.open(`https://subdomain.cybozu.com/k/123/edit?action=12345678&app=123&record=${recordId}`, '_blank');
    });
    return event;
  });
})();
```

### フィールドの設定を変更する

#### ドロップダウンフィールドの項目を追加する

```javascript
var body = {
  'app': kintone.app.getId(),
  'properties': {
    "ドロップダウン": {
      "type": "DROP_DOWN",
      "code": "ドロップダウン",
      "label": "ドロップダウン",
      "noLabel": false,
      "required": false,
      "options": {
        "sample1": {
          "label": "sample1",
          "index": "0"
        },
        "sample2": {
          "label": "sample2",
          "index": "1"
        },
        "sample3": {
          "label": "sample3",
          "index": "2"
        }
      },
      "defaultValue": ""
    },
  }
};

kintone.api(kintone.api.url('/k/v1/preview/app/form/fields', true), 'PUT', body, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});

var body = {
  'apps': [
    {
      'app': kintone.app.getId()
    },
  ]
};

kintone.api(kintone.api.url('/k/v1/preview/app/deploy', true), 'POST', body, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});
```


## kintone REST API
kintoneのデータベース（いわゆるアプリ）にREST形式でアクセスするAPI群です。
https://developer.cybozu.io/hc/ja/articles/360000313406

---
"kintone REST API" の利用方法

利用方法には大きく以下の２つの方法があります。

1. kintone内部からのアクセス
1.1 kintone.api() 関数を利用する。
1.2 kintone.proxy() 関数を利用する。

2. kintone外部からのアクセス
2.1 curlやその他プログラム言語からHTTPSを利用してよしなにアクセスする。 

kintoneの内部から普通に利用する場合は、1.1のkintone.api()関数からREST APIを利用すれば良いです。
kintone.proxy()は、kintone内部から外部のAPIにアクセスする場合と、例えばログインユーザーにアプリ管理権限
が無い場合に実行にアプリ管理権限が必要なAPIを利用する場合に、アプリのアクセス権限が付与されたAPIトークンを利用してproxyサーバー経由でアクセスする場合にも利用します。

上記のproxyアクセスは、例えば[アプリのアクセス権の取得API](https://developer.cybozu.io/hc/ja/articles/204529754)をアプリの管理権限が無いユーザーが実行したい場合などが考えられます。
その場合は、対象アプリからアプリの管理権限が付与されたAPIトークンを取得して、kintone.proxy()経由でアクセスします。
kintone.proxy()を利用する場合は、APIトークンや外部APIへの認証情報を直接JSに埋め込まない様に注意が必要です。
https://developer.cybozu.io/hc/ja/articles/201919400#step8


### アプリの設計情報取得
コーディング時、アプリのフィールドコードを確認する際にChromeDevToolのコンソールに貼り付けて使ってます。（"app": の後にアプリIDを入力します）

```javascript
kintone.api(kintone.api.url('/k/v1/form', true), 'GET', {"app": kintone.app.getId()}, function(resp) {
    // success
    console.log(resp);
    console.log(JSON.stringify(resp));
}, function(error) {
    // error
    console.log(error);
});
```

### フォーム設定取得
アプリのフォームの設定を取得します。
主に、プラグインの作成時、仕様書を起こす際のレコードレイアウト作成時に使っています。

```javascript
var body = {
    "app": kintone.app.getId()
};
kintone.api(kintone.api.url('/k/v1/app/form/fields', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});
```

#### フォーム設定取得からフィールドコードを抜き出す

前段のAPIから出力した結果をform-fields.jsonに保存したとき。

```
$ cat form-fields.json | jq '.properties | keys'
```

https://stedolan.github.io/jq/manual/


または、


```
$ cat form-fields.json | jq '.properties[] | .code'
```

```
.properties[] | [.label, .code, .type] | @csv
```


### フォームレイアウト取得
フォームのレイアウトを取得する

```javascript
var body = {
    "app": kintone.app.getId()
};

kintone.api(kintone.api.url('/k/v1/app/form/layout', true), 'GET', body, function(resp) {
    // success
    // console.log(resp);
    console.log(JSON.stringify(resp, null, 2)); // JSONを整形して出力
}, function(error) {
    // error
    console.log(error);
});
```


jqオンラインエディター

https://jqplay.org/


## アプリ

### [アプリ情報の一括取得](https://developer.cybozu.io/hc/ja/articles/202931674#step2)
アプリ情報を一括取得します。（最大100件）

100件取得

```
kintone.api(kintone.api.url('/k/v1/apps', true), 'GET', {}, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});
```

次の100件

```
kintone.api(kintone.api.url('/k/v1/apps', true), 'GET', {offset:100}, function(resp) {
  // success
  console.log(resp);
}, function(error) {
  // error
  console.log(error);
});
```

---
## スペース

### [スペース情報の取得](https://developer.cybozu.io/hc/ja/articles/202166200)
スペース内アプリ一覧等が取得出来ます。
kintoneのスペースを開いた状態で、DevTools等のコンソールで実行します。

```javascript
kintone.api(kintone.api.url('/k/v1/space', true), 'GET', {"id": 1}, function(resp) {
    // success
    // console.log(resp);
    console.log(JSON.stringify(resp, null, 2));
}, function(error) {
    // error
    console.log(error);
});
```

#### スペース内アプリ一覧

取得したJSONを使ってスペースのアプリIDとアプリ名を取り出してみる。

まず上記で取得したJSONをファイルに保存して(space.jsonなど)

そのまま出力
`$ cat space.json | jq`

スペース内のアプリ一覧情報は "attachedApps: []" にあるので抽出
`$ cat space.json | jq '.attachedApps'`

配列から外して
`$ cat space.json | jq '.attachedApps | .[]'`

"appId"のみ抽出
`$ cat space.json | jq '.attachedApps | .[] | .appId'`

配列に入れたり
`$ cat space.json | jq '.attachedApps | .[] | [.appId]'`

オブジェクトに入れたり
`$ cat space.json | jq '.attachedApps | .[] | {appId: .appId}'`
`$ cat space.json | jq '.attachedApps | .[] | {appId: .appId, name: .name}'`

アプリIDとアプリ名を抽出して配列にして
`$ cat space.json | jq '.attachedApps | .[] | [.appId, .name]'`

最後にCSVに出力
`$ cat space.json | jq '.attachedApps | .[] | [.appId, .name] | @csv'`

-r オプション付けて
`$ cat space.json | jq -r '.attachedApps | .[] | [.appId, .name] | @csv'`

.nameでソートする
`cat apps.json | jq -r '.attachedApps | sort_by(.name) | .[] | [.name, .appId] | @csv' > apps.csv`

参考：
https://jqplay.org/


## レコード

### レコード１行取得
kintone REST API で取得されるレコードレイアウト確認に使ってます。

```javascript
var body = {
    "app": 1,
    "id": 1001
};
kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});
```

```javascript
var body = {
    "app": kintone.app.getId(),
    "id": kintone.app.record.getId()
};

kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});
```
現在開いているアプリとレコードが対象の時は、アプリIDとレコードIDをAPIでセットしても良い。

良い感じでJSONを整形する

```javascript
var body = {
    "app": kintone.app.getId(),
    "id": kintone.app.record.getId()
};

kintone.api(kintone.api.url('/k/v1/record', true), 'GET', body, function(resp) {
    // success
    console.log(JSON.stringify(resp, null, 4));
}, function(error) {
    // error
    console.log(error);
});
```

### レコード一括取得（クエリ指定）

```javascript

var body = {
    "app": 1,
    "query": "updated_time > \"2012-02-03T09:00:00+0900\" and updated_time < \"2012-02-03T10:00:00+0900\" order by $id asc limit 10 offset 0",
    "fields": ["$id", "created_time", "dropdown"]
};

kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body, function(resp) {
    // success
    console.log(resp);
}, function(error) {
    // error
    console.log(error);
});
```
### 一覧のクエリ文字列を取得する

```javascript

var condition = kintone.app.getQueryCondition();
console.log(condition);

// order by, limit, offset付きで取得する場合はこちら
var condition = kintone.app.getQuery();
console.log(condition);

```

開発者ツールのコマンドラインから打ち込むと、下記のように一覧画面の検索条件がクエリ文字列で表示されるので便利です。

`"更新日時 > FROM_TODAY(-2, DAYS) order by 更新日時 desc limit 100 offset 0"`

### アプリアクション時にルックアップの取得を自動で行う

```javascript
(function() {
  'use strict';
  kintone.events.on('app.record.create.show', function(event) {
    const record = event.record;
    record[<ルックアップのフィールドコード>].lookup = true;
    return event;
  });
})();
```

`record[<ルックアップのフィールドコード>]['lookup'] = 'UPDATE'`
でも同じ

### フィールドのchangeイベントで書き換えられた値を別フィールドにセットする

```javascript

(function() {
    "use strict";
    kintone.events.on(["app.record.edit.change.日付", "app.record.create.change.日付"], function(event) {
        
        console.log(event);
        let changesValue = event.changes.field.value;
        console.log(changesValue);
        let record = event.record;
        // var record = kintone.app.record.get();
        // record.record['最新日付'].value = '書き換えた文字列';
        // kintone.app.record.set(record);
        // changes.field.value
        record['最新日付'].value = changesValue;
        return event;
    });
})();
```
### bulkRequest バルクリクエスト 

複数のアプリに対して、同時に複数の APIをリクエストすることが出来ます。

* 最大20リクエストまで
* いずれかのAPI失敗で、全部がロールバックされます
* パスワード認証で使うが、単一アプリIDへのリクエストならAPIトークン可
* ゲストスペースは注意。同一ゲストスペース内のアプリの処理のみ可能


```
URI https://subdomain.cybozu.com/k/v1/bulkRequest.json
POST
```

```json
{
  "requests": [
    {
      "method": "POST",
      "api": "/k/v1/record.json",
      "payload": {
        "app": 365,
        "record": {
          "文字列1": {
            "value": "文字列__1行を追加します。"
          }
        }
      }
    },
    {
      "method": "PUT",
      "api": "/k/v1/record.json",
      "payload": {
        "app": 369,
        "id": 1,
        "record": {
          "文字列1": {
            "value": "文字列__1行を更新します。"
          }
        }
      }
    }
  ]
}
```

```javascript
(function() {
    "use strict";
    kintone.events.on("app.record.index.show", function(e) {
        // バルクリクエスト発火用のボタンを設置
        var newButton2 = document.createElement('button');
        newButton2.id = 'button1';
        newButton2.innerText = 'バルクリクエスト';
        kintone.app.getHeaderSpaceElement().appendChild(newButton2);
        newButton2.addEventListener('click', function(){
            doBulkRequest();
        });
    });
    var doBulkRequest = function(){
        var body = {
          "requests": [
            {
              "method": "POST",
              "api": "/k/v1/record.json",
              "payload": {
                "app": 365,
                "record": {
                  "文字列1": {
                    "value": "文字列1行とテーブル２行追加"
                  },
                  "Table": {
                      "value": [
                          {
                              "id": 1,
                              "value": {
                                  "文字列": {
                                      "value": "テーブルテスト１行目"
                                  }
                              }
                          },
                          {
                              "id": 2,
                              "value": {
                                  "文字列": {
                                      "value": "テーブルテスト２行目"
                                  }
                              }
                          }
                      ]
                  }
                }
              }
            },
            {
              "method": "PUT",
              "api": "/k/v1/record.json",
              "payload": {
                "app": 369,
                "id": 2,
                "record": {
                  "文字列1": {
                    "value": "文字列1行を更新。"
                  },
                  "文字列2": {
                    "value": "文字列2行を更新。"
                  },
                  "Table": {
                      "value": [
                          {
                              "id": 1,
                              "value": {
                                  "文字列": "テーブル内１行目文字列を更新"
                              }
                          },
                          {
                              "id": 2,
                              "value": {
                                  "文字列": "テーブル内２行目文字列を更新"
                              }
                          }
                    ]
                  }
                }
              }
            }
          ]
        }
        kintone.api(kintone.api.url('/k/v1/bulkRequest', true), 'POST', body, function(resp) {
            //success
            console.log(resp);
        }, function(error) {
            //error
            console.log(error);
        });
    }
})();
```

### kintone.api()にて取得したデータを利用して何か処理した後に、その結果でフィールドを非表示に設定する

例えば、新規レコード追加画面にて、kinton.api()にてREST APIで取得したデータを元に、何か処理をしてから、その結果でフィールドを非表示にしたい場合。
kintone.api()は非同期で実行されるため、eventのリターン時にPromiseオブジェクトをリターンします。

```javascript
  kintone.events.on('app.record.create.show', function(event) {
    const record = event.record;
    const user = kintone.getLoginUser();
    return kintone.api('/v1/user/groups','GET',{code:user.code})
    .then((resp) => {
      // 何かの処理。例えばログインユーザーが特定のグループロールに所属していたら。
      const groups = resp.groups;
      for (const group of groups) {
        const { code } = group;
        if (code === 'sales') { // 特定のグループ（ロール）に所属？
          record['fieldCode'].disabled  = true;
          return event;  
        }
      }
    })
    .catch((error) => {
      console.log(error);
      return event;
    });
  });
```

https://developer.cybozu.io/hc/ja/articles/202166310#step1
https://developer.cybozu.io/hc/ja/articles/204564604
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...of

---
# cybozu.com

## User API

### グループインポート API(JSON)

```javascript
const params = {
    "groups": [
        {
            "code": "group1",
            "name": "group1",
            "type": "static",
            "description": "test group"
        },
        {
            "code": "group2",
            "name": "group2",
            "type": "dynamic",
            "description": ""
        }
    ]
};
kintone.api(kintone.api.url('/v1/groups', true), 'POST', params).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### 組織インポート API（JSON）

```javascript
const params = {
    "organizations": [
        {
            "code": "organization-1",
            "name": "組織-1",
            "description": "組織1のメモ",
        }
    ]
};
kintone.api(kintone.api.url('/v1/organizations', true), 'POST', params).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### ユーザーインポート API（JSON）

```javascript
const params = {
    "users": [
        {
            "code": "demoUser1",
            "valid": false,
            "password": "demoUserDemouseR",
            "name": "デモユーザー1",
        }
    ]
};
kintone.api(kintone.api.url('/v1/users', true), 'POST', params).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

---
### ユーザーエクスポート API（JSON）
https://developer.cybozu.io/hc/ja/articles/202363040#step2
cybozu.com共通管理に登録されたユーザーの情報をJSONで取得することができます。
※全ユーザーでアクセス可能

```
kintone.api(kintone.api.url('/v1/users', true), 'GET', {}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

1回のリクエストで取得できる件数の上限は100件までのため、
それ以上はクエリパラメータに条件をセットする。
例えば100件〜199件を取得する場合は次の通り。

```
kintone.api(kintone.api.url('/v1/users', true), 'GET', {offset: 100}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```


### 組織エクスポート API（JSON）
https://developer.cybozu.io/hc/ja/articles/202124754#step2
cybozu.com共通管理に登録された組織の情報をJSONで取得することができます。
※全ユーザーがアクセス可能

```
kintone.api(kintone.api.url('/v1/organizations', true), 'GET', {}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### グループエクスポート API（JSON）
https://developer.cybozu.io/hc/ja/articles/202363060#step2
cybozu.com共通管理に登録されたグループの情報をJSONで取得することができます。
※全ユーザーがアクセス可能

```
kintone.api(kintone.api.url('/v1/groups', true), 'GET', {}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### ユーザーの所属組織エクスポート API（JSON）
https://developer.cybozu.io/hc/ja/articles/202124774#step2
ユーザーを指定して、指定したユーザーの所属する組織の情報をJSONで取得することができます。
※全ユーザーでアクセス可能

```
kintone.api(kintone.api.url('/v1/user/organizations', true), 'GET', {code:"<ユーザーコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### ユーザーの所属グループエクスポート API（JSON）
ユーザーを指定して、指定したユーザーが所属するグループ（ロール）の情報をJSONで取得することができます。
https://developer.cybozu.io/hc/ja/articles/202124784#step2
※全ユーザーでアクセス可能

```
kintone.api(kintone.api.url('/v1/user/groups', true), 'GET', {code:"<ユーザーコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### 組織の所属ユーザーエクスポート API
https://developer.cybozu.io/hc/ja/articles/203881650
組織を指定して、配下に所属するユーザーの一覧をJSON形式で取得します。

```
kintone.api(kintone.api.url('/v1/organization/users', true), 'GET', {code:"<組織のコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```

### グループの所属ユーザーエクスポート API
https://developer.cybozu.io/hc/ja/articles/208251616
グループ（ロール）を指定して、配下に所属するユーザーの一覧をJSON形式で取得します。

```
kintone.api(kintone.api.url('/v1/group/users', true), 'GET', {code:"<グループのコード>"}).then(function(resp) {
  console.log(resp);
}, function(error) {
  console.log(error);
});
```


---
# curl による kintone API アクセス
https://curl.se/

利用方法について
シェルスクリプトと同じディレクトリにkintone APIに渡す認証情報を .env ファイルに記述します。

例

```
apitoken="<APIトークン>"
```


## アプリのアクセス権の取得(/k/v1/app/acl.json)
https://developer.cybozu.io/hc/ja/articles/204529754
アプリの設定のアクセス権で設定した、ユーザー／組織／グループごとに設定したアプリの権限をJSONで取得できます。

```app_acl.sh
#!/bin/bash

source ./.env
APITOKEN=${apitoken}
APPID=${appid}
SUBDOMAIN=${subdomain}
curl -X GET -H "X-Cybozu-API-Token:${APITOKEN}" "https://${SUBDOMAIN}.cybozu.com/k/v1/app/acl.json?app=${APPID}"
```

---

# jQuery

## jQuery

### 要素を指定して自身の要素を含んだHTMLを取得する

```javascript
const html = `
<div class="content">
  <div id="title" >
    <p>テスト</p>
  </div>
</div>
`;
console.log($(html).find('#title').prop('outerHTML'));

// 結果
//<div id="title">
//    <p>テスト</p>
//  </div>
```

* [テンプレートリテラル](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals)
* [.find()](https://api.jquery.com/find/)

### jQueryの引数に変数を渡して展開する

```javascript
const id = 'title'
console.log($(html).find(`#${id}`).prop('outerHTML'));
```

### jQueryの内側の要素を置き換える

```javascript
const html = `
<div class="content">
  <div id="title" >
    <p>テスト</p>
  </div>
</div>
`;
const replace = `
<div id="title2" >
  <p>テスト2</p>
</div>
`;
console.log($(html).html(replace).prop('outerHTML'))

//結果
//<div class="content">
//<div id="title2">
//  <p>テスト2</p>
//</div>
//</div>
```

### jQueryのセレクタで取得した配列についてプロパティ指定でid名を取得する

```javascript
const Html = `
<div class="main_content">
  <div id="title" class="content_box">
    <p>タイトル</p>
  </div>
  <div id="sub_title" class="content_box">
    <p>サブタイトル</p>
  </div>
</div>
`
function fetchPortalMenuIdes(html, selector) {
  return  $(html).find(selector).map(function(i, v){return $(this).prop('id')});
  // return  $(html).find(selector).map(function(i, v){return $(this).attr('id')}); // attrでも同じ結果
  // return  $(html).find(selector).map((i, v) => {return $(v).prop('id')}); // 無名関数もOK
}
console.log(fetchPortalMenuIdes(Html, 'div.content_box')); // jQueryオブジェクトが返る
console.log(fetchPortalMenuIdes(Html, 'div.content_box').get()) // JavaScript配列が返る;

// 結果
//　S {
//　　0:"title",
//　　1:"sub_title",
//　}
// ["title","sub_title"]
```

## 関数をカリー化する

```javascript
function fetchPortalMenuIdes(html) {
  return (selector) => {
    return  $(html).find(selector).map(function(i, v){return $(this).prop('id')}).get();
  }
}
console.log(fetchPortalMenuIdes(Html)('div.content_box'));
console.log(fetchPortalMenuIdes(Html)); // 内側の関数が返る
```



## jQuery UI
ダイアログ

```javascript

<script src="https://js.cybozu.com/jquery/2.2.4/jquery.min.js"></script>
<script src="https://js.cybozu.com/jqueryui/1.12.0/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://js.cybozu.com/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">

var compiled = _.template('<div id="dialog" title="Hello"> Hello,<%= echo %></div>')({echo: 'World'});
var elMyBt = _.template('<button id="myBt">click</button>');
$(kintone.app.record.getHeaderMenuSpaceElement()).append(elMyBt);
$('#myBt').on('click', function() {
    viewDialog();
});
function viewDialog() {
    $(compiled).dialog({autoOpen: false, modal: true}).dialog('open');
}
```

# JavaScript
## 関数
関数を作る

```javascript

function square(number) {
  return number * number;
}
```
## クラスを作る

```javascript
var SampleLib = (function () {
  'use strict';

  // コンストラクタ
  function SampleLib() {
  }

  SampleLib.prototype.hello = () => {
    return 'Hello from kintone CLI';
  }

  return SampleLib;
})();
```

呼び出し側

```javascript
(function () {
  'use strict';
  kintone.events.on('app.record.index.show', function (event) {
    const samplelib = new SampleLib(); // インスタンス生成
    console.log(samplelib.hello());
    return event;
  });
})();
```



## Promise

```javascript

var funcA = function promiseSampleA() {
                // Promiseを返す処理A
            };
var funcB = function promiseSampleB() {
                // Promiseを返す処理B
            };
function main() {
    return Promise.all([promiseSampleA(), promiseSampleB()]);
}
// 実行例
main().then(function (value) {
    console.log(value);
}).catch(function(error){
    console.error(error);
});
```

## kintone.Promise()

```javascript
  kintone.events.on('<kintoneイベント>', (event) => {
    return new kintone.Promise((resolve) => {
      // 何か処理
      resolve(<次に渡したい結果など>); // Promiseチェーンで繋げたい結果はresolve()で返却する
    })
    .then(result => {
      // 何か処理
      // REST APIでレコードを取得など。 下記の書き方をすれば、処理結果がPromiseで返される。
      return kintone.api(kintone.api.url('<REST API エンドポイント>', true), '<GET/POST>', <パラメータ>);
    })
    .then(result => {
      // 何か処理
      return event; // 結果をレコードに反映するなどの処理に応じて、最後にeventをリターンする。
    })
    .catch(error => {
      console.error(error);
    });
  });
```

## undefined 判定

```javascript
var foo = {'name': "bar"};
console.log('foo.name =>', foo.name); // foo.name => bar
console.log('foo.value =>', foo.value); // foo.value => undefined
if (typeof foo.value === 'undefined') {
    console.log('foo.value of undefined');
}
```

## オブジェクトの値でソートして、オブジェクトのキーの配列を返す

```javascript
const obj = {
  test01:900,
  test03:2,
  test02:1,
  test04:3000,
  test05:4
}
console.log(obj);
const sortedKeys = Object.keys(obj).sort((a, b) => {
  return obj[a] - obj[b]
});
console.log(sortedKeys); //  ["test02","test03","test05","test01","test04"]

```

## 複数の配列を1つの配列に展開して、重複を取り除いた配列を返す

```javascript
const menus1 = ['test01', 'test03']
const menus2 = ['test01', 'test02', 'test04', 'test05']
const flattenedMenus = [menus1, menus2].reduce(
  ( accumulator, currentValue ) => accumulator.concat(currentValue),
  []
).reduce(function (accumulator, currentValue) {
  if (accumulator.indexOf(currentValue) === -1) {
    accumulator.push(currentValue)
  }
  return accumulator
}, [])
console.log('flattenedMenus =>', flattenedMenus);
// flattenedMenus => ["test01","test03","test02","test04","test05"]
```