ボタンでサーバ処理実行後にJavaScriptの処理を実行する方法

- 環境
    - CentOS Linux release 7.8.2003 (Core)
    - Eclipse IDE for Enterprise Java Developers.Version: 2020-03 (4.15.0)
    - openjdk version "11.0.7" 2020-04-14 LTS
    - JSF 2.3.9

# やりたいこと
1. ポップアップで開いた子画面を閉じたい
1. 閉じる時にサーバで処理したい

# 方法1 : h:commandButtonでサーバ処理実行前にJavaScriptの処理を実行する
1. `h:commandButton`の`actionListener`属性にサーバ処理を書く
2. `h:commandButton`の`onclick`属性に[子画面を閉じる処理]+[`return true;`]を書く

```xml:子画面のxhtml
<!--省略-->
<h:commandButton value="閉じる" actionListener="#{uploadBean.close}" onclick="window.close(); return true;" />
<!--省略-->
```

# 方法2 : h:commandButtonでサーバ処理実行後にJavaScriptの処理を実行する
1. `h:commandButton`の`action`属性にサーバ処理を書く
2. `h:commandButton`の子要素に`f:ajax`を書く(ボタンのサーバ処理はAjaxで実行する)
3. `f:ajax`の`onevent`属性にJavaScriptの関数名を書く
4. JavaScriptの関数でUI eventをパラメータとして定義する
5. UI eventの`status`が`complete`だったら処理を実行する

```xml:子画面のxhtml
<!--省略-->
<h:commandButton value="閉じる" actionListener="#{uploadBean.close}">
  <p:ajax oncomplete="window.close();" />
</h:commandButton>
<!--省略-->
```

```javascript:JavaScriptの関数
/**
 * eventが完了していたら画面を閉じる.
 * @param  {Object} event UI event
 */
function windowClose(event) {
    if (event.status == 'complete') {
        window.close();
    }
}
```

```java:UploadBean.java
// ...省略...
    /** 子画面の[閉じる]ボタン押下処理. */
    public void close() {
        System.out.println("サーバでやりたい処理。");
    }
// ...省略...
```

```html:子画面で出力されたhtml
<input id="j_idt11:j_idt14" type="submit" name="j_idt11:j_idt14" value="閉じる" onclick="mojarra.ab(this,event,'action',0,0,{'onevent':windowClose});return false">
```

## 調べた情報
今回は最初に`h:commandButton`の`action`属性でサーバ処理を実行していた。

> ◆actionとactionListenerをきちんと使い分ける
> 用途が異なる
>　action：ナビゲーション（画面遷移）用途
>　actionListener：UI操作のハンドリング用途
> [【もうハマらない！】JSFをきちんと理解しよう。 - Qiita](https://qiita.com/3san-yamagami3/items/1b9d7d98c6476d5b1508#action%E3%81%A8actionlistener%E3%82%92%E3%81%8D%E3%81%A1%E3%82%93%E3%81%A8%E4%BD%BF%E3%81%84%E5%88%86%E3%81%91%E3%82%8B)

今回の場合は、`action`属性じゃなくて`actionListener`属性を使うべきじゃね？と気がついた。

> f:ajaxの属性
> onevent
> Ajax処理の起動時に、ブラウザ側で起動するJavaScriptのメソッドを指定する。このメソッドには、サーバーからAjax処理の実行状況を示すデータが渡される。
> [わかりやすいJava EE ウェブシステム入門 - 秀和システム](https://www.shuwasystem.co.jp/book/9784798042169.html)

「実行状況を示すデータ」って何だ？

> onevent
> The name of the JavaScript function that will handle UI events.
> [ajax(JSF 2.2 View Declaration Language: Facelets Variant)](https://docs.oracle.com/javaee/7/javaserver-faces-2-2/vdldocs-facelets/f/ajax.html)

「UI event」のことのようだが、いろいろあるし・・・

> MouseEvent、TouchEvent、FocusEvent、KeyboardEvent、WheelEvent、InputEvent、CompositionEvent といったインターフェイスが、このインターフェイスの直接または間接の子孫です。
> [UIEvent - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/UIEvent)

ステータスには、`begin`と`complete`と`success`のいずれかが設定されるようだが・・・いまいちJavaScriptの処理に渡されるものがUIEventの何かがよくわからない。
誰か教えてほしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/6fdbb56c-8d4e-c054-a636-e34220f0eb83.png)

# 方法2 : p:commandButtonでサーバ処理実行後にJavaScriptの処理を実行する

# 失敗したやり方
サーバ処理は実行されず・・・子画面が閉じた。
`return true;`を追記すれば、子画面を閉じる処理の後にサーバ処理が動いてくれる。

```xml:子画面のxhtml
<!--省略-->
<h:commandButton value="閉じる" action="#{uploadBean.close}" onclick="window.close();" />
<!--省略-->
```

> ⑥JavaScriptを起動しactionも実行するボタン
> onclick属性とaction属性を指定する例です。
> `<h:commandButton value="JS+送信" action="#{bb.next()}" onclick="alert('ボタンが押された')" />`
> この場合は、JavaScriptのプログラムが先に起動します。action属性のnextメソッドはサーバで実行されるのに対して、JavaScriptはブラウザで実行されるからです。
> [わかりやすいJava EE ウェブシステム入門 - 秀和システム](https://www.shuwasystem.co.jp/book/9784798042169.html)