ModalWindow で処理中を表現する

先日、Wicket の ModalWindow の close ボタンを非表示にする - Oboe吹きプログラマの黙示録
を書きました。

↓ ↓ ↓  2018-12-6 に、更に改善 ↓ ↓ ↓ ↓
LazyModalPanel - Oboe吹きプログラマの黙示録

これを書いて思ったのですが、処理中画面操作させたくない時の為に ModalWindow を表示することを考えました。
CLOSE ボタンが無いモーダルウィンドウで、処理が終わったら自動的に閉じるものです。
注意が必要なのは、絶対、例外発生で閉じることができなくなってしまわないようにすることです。

処理中表現は、プログレスバーなどいろいろあるとは思いますが、進捗率が解らないことを想定して、
https://spin.js.org/
で表示しておくことにします。
f:id:posturan:20181124164735j:plain
表示中にユーザに中断させない。モーダルの後ろの画面コンテンツを触らせない。
という目的で、あえて CLOSEボタンが全くなく、右上端に CLOSE [×] もないようにします。
これを汎用的に使用できるようにします。

モーダルウィンドウのHTML :LazyModalPanel.html

<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:panel>
   <form wicket:id="lazy_mocal_form" id="lazy_mocal_form" >
      <section class="lazy-modal-panel">
         <div>
            <ul>
               <li><div id="lazy_modal_progress"></div></li>
               <li><span wicket:id="message"></span></li>
               <li style="display:none"><button wicket:id="lazy_mocal_close" id="lazy_mocal_close" type="button">CLOSE</button></li>
            </ul>
         </div>
      </section>
   </form>
<script type="text/javascript">
$(function(){
   new Spinner().spin(document.getElementById('lazy_modal_progress'));
   setTimeout("$('#lazy_mocal_form').parent().parent().parent().parent().parent().prev().children('a').css('display','none');",100);
});
</script>
</wicket:panel>
</body>
</html>

モーダルウィンドウ表示の Java
内部で、
https://github.com/yipuran/yipuran-wicketcustom
にある、SerialThrowableConsumer :例外捕捉可能な シリアライズ可能な Consumer を使います。
これで、CLOSEボタンが無くても、永久ループにならない限りモーダルは必ず閉じます。

LazyModalPanel.java

import java.util.Optional;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.core.util.string.JavaScriptUtils;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.danekja.java.util.function.serializable.SerializableConsumer;
import org.yipuran.wicketcustom.function.SerialThrowableConsumer;
/**
 * LazyModalPanel
 */
public class LazyModalPanel extends Panel{

   public LazyModalPanel(String id, IModel<String> model, SerializableConsumer<AjaxRequestTarget> consumer, SerializableConsumer<Exception> oncatch){
      super(id, model);
      queue(new Form<Void>("lazy_mocal_form"));
      queue(new Label("message", Optional.ofNullable(model.getObject()).orElse("")));
      queue(new Button("lazy_mocal_close").add(AjaxEventBehavior.onEvent("click", SerialThrowableConsumer.of(t->{
         consumer.accept(t);
         ModalWindow.closeCurrent(t);
      },(t, x)->{
         oncatch.accept(x);
         ModalWindow.closeCurrent(t);
      }))));
   }
   @Override
   protected void onAfterRender(){
      super.onAfterRender();
      JavaScriptUtils.writeJavaScript(getResponse(), "setTimeout('sizefitMessageModal();$(\"#lazy_mocal_close\").trigger(\"click\");', 100);" );
   }
   @Override
   public void renderHead(IHeaderResponse response){
      super.renderHead(response);
      response.render(CssHeaderItem.forReference(new CssResourceReference(LazyModalPanel.class, "lazymodal.css")));
      response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(LazyModalPanel.class, "spin.min.js")));
      response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(LazyModalPanel.class, "lazymodal.js")));
   }
}

スタイルシート
lazymodal.css

@CHARSET "UTF-8";
/* lazymodal.css */
.lazy-modal-panel ul{
   margin: 10px 0;
   padding: 10px;
}
.lazy-modal-panel li{
   list-style-type: none;
   white-space: nowrap;
   display: flex;
   align-items: center;
   justify-content: space-around;
}
.lazy-modal-panel li span{
   margin: 40px 0 5px 0;
}
#lazy_modal_progress{
   position: absolute;
   margin-top: 10px;
}

描画時のサイズ調整 JavaScript
lazymodal.js

var sizefitMessageModal = function(){
   $('.w_content_container').css("height", $('.lazy-modal-panel ul').outerHeight(true) + "px" );
   $('.wicket-modal').css("width", $('.lazy-modal-panel ul').outerWidth(true) + 22 + "px" );
};

このモーダルウィンドウを呼出し表示の処理

final ModalWindow window = new ModalWindow("lazy_window").setResizable(true).setAutoSize(true);
queue(window);

queue(new Button("link").add(AjaxEventBehavior.onEvent("click", t->{
   window.setContent(new LazyModalPanel(window.getContentId(), Model.of("処理中..."), u->{

      // 時間がかかる処理

   }, x->{
      // 例外捕捉
   }));
   window.show(t);
})));