Wicket ModalWindow の Autosize

Wicket の ModalWindow のサイズを任意に指定するには、ModalWindow #setInitialWidth #setInitialHeight
でpixelサイズ指定するが自動でコンテンツのサイズ自動調整するには、
setAutoSize(true) を呼ぶことにになっている。

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

しかし、width だけが調整されて、height に対して効かない。
height : 120px のコンテンツを描画しても、ModalWindow のHTMLは、

<div id="_wicket_window_3" class="w_content_container" style="overflow: auto; height: 200px;">

のように、style 属性で、height が書き込まれてしまう。
古い Wicket 1.5 の頃は、AjaxRequestTarget で ModalWindow をshow() で描画後、以下のように
JavaScript を実行していたみたいだが、

target.appendJavaScript("Wicket.Window.get().autoSizeWindow();");

これでは、最新のWicket では、ダメだった。
仕方なく以下、jQuery を実行することで解決はするが、setTimeout で実行する分、どうしてもそれだけ時間がかかる。

 window.show(target);
 target.appendJavaScript("setTimeout(\"$('div.w_content_container').css('height','');\",100);");

CSSだけでサイド開閉メニュー

jQuery を使用しないで、CSSだけでサイド開閉メニューのサンプルメモ

HTML サンプル

<link rel="stylesheet" type="text/css" href="home.css">
<link rel="stylesheet" type="text/css" href="sidemenu.css">
</head>
<body>

<input id="menuopen-input" type="checkbox">
<nav id="menu-nav">
   <ul>
      <li><span><b>メニュー</b></span><span><label for="menuopen-input"><b>×</b></label></span></li>
      <li><a href="#">ABOUT</a></li>
      <li><a href="#">CONTENT</a></li>
   </ul>
</nav>
<div id="main-container">
   <div class="main-header">
   <label for="menuopen-input"><i class="menu-icon">&#xf0c9;</i></label>
   </div>
   <h2>content</h2>
</div>

</body>
</html>

sidemenu.css の内容、

@charset "UTF-8";
/* sidemenu.css */

/*----------------- left-slide-menu ----------------------------*/
#menuopen-input{
   display: none;
}
#menuopen-input:checked ~ #menu-nav{ left: 0; }
#menuopen-input:checked ~ #main-container{ left: 240px; }

#menu-nav{
   position: fixed;
   height: 100%;
   width: 240px;
   top: 0;
   left: -240px;
   background: #123490;
   color: #ffffff;
   z-index: 1000000000;
   transition: left 0.1s linear;
   -webkit-transition: left 0.1s linear;
}
#menu-nav li{
   list-style: none;
   height: 48px;
   line-height: 48px;
   padding-left: 24px;
}
#menu-nav li a{
   color: #ffffff;
}

#menu-nav li:nth-child(1) span:nth-child(2){
   padding-left: 120px;
   font-size: 18px;
   cursor: pointer;
}
#menu-nav li:nth-child(1) span label{
   cursor: pointer;
}


#main-container{
   position: relative;
   left: 0;
   width: 100%;
   height: 100%;
   box-sizing: border-box;
   z-index: 1;
   transition: left 0.1s linear;
   -webkit-transition: left 0.1s linear;
}
/*---  menu icon ---*/
@font-face{
   font-family: 'fontello';
   src: url('font/fontello.eot');
   src: url('font/fontello.eot#iefix') format('embedded-opentype'),
        url('font/fontello.woff') format('woff'),
        url('font/fontello.ttf') format('truetype'),
        url('font/fontello.svg#fontello') format('svg');
   font-weight: normal;
   font-style: normal;
}
.menu-icon{
   font-family: "fontello";
   font-style: normal;
   font-weight: normal;
   font-size: 32px;
   display: inline-block;
   text-decoration: inherit;
   cursor: pointer;
   color: #ffffff;
   margin: 4px 4px;
}

jQuery を使用せずに、checkbox の input 疑似クラス ":checked" でコントロールする。
フォントアイコンを使用している。→ http://fontello.com/ から持ってくる。
f:id:posturan:20180102160434j:plain

Java AES 256 暗合・複合

過去に何度も書いた Java AES 暗合・複合
秘密鍵、初期ベクトルをどう作成するか、いろんな方法あるが、
改めて、256bit で、SHA-256 ハッシュ値を使う方法。

暗合

public static String encrypt(String passwd, String message){
   try{
      byte[] key = passwd.getBytes();
      MessageDigest sha = MessageDigest.getInstance("SHA-256");
      key = sha.digest(key);
      key = Arrays.copyOf(key, 32);
      SecretKeySpec keyObj = new SecretKeySpec(key, "AES");
      IvParameterSpec ivObj = new IvParameterSpec(Arrays.copyOf(key, 16));
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      cipher.init(Cipher.ENCRYPT_MODE, keyObj, ivObj);
      byte[] byteCipherText = cipher.doFinal(message.getBytes());
      return Base64.getEncoder().encodeToString(byteCipherText);
   }catch(Exception e){
      throw new RuntimeException(e);
   }
}

複合

public static String decrypt(String passwd, String cryptText){
   try{
      byte[] key = passwd.getBytes();
      MessageDigest sha = MessageDigest.getInstance("SHA-256");
      key = sha.digest(key);
      key = Arrays.copyOf(key, 32);
      SecretKeySpec keyObj = new SecretKeySpec(key, "AES");
      IvParameterSpec ivObj = new IvParameterSpec(Arrays.copyOf(key, 16));
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      cipher.init(Cipher.DECRYPT_MODE, keyObj, ivObj);
      byte[] cipherBytes = Base64.getDecoder().decode(cryptText);
      byte[] byteDecryptedText = cipher.doFinal(cipherBytes);
      return new String(byteDecryptedText);
   }catch(Exception e){
      throw new RuntimeException(e);
   }
}

Java8では、このままでは、java.security.InvalidKeyException: Illegal key size
となってしまうので、
JCEポリシーの制限を無くすために下記から policy の JAR をダウンロード
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 8 Download

jre/lib/security の下の
local_policy.jar
US_export_policy.jar

を置き換える。

Java9 では、

      Security.getProperty("crypto.policy");

の結果が、 unlimited  であるので、Java8のように置き換えは不要。

Security.setProperty("crypto.policy", "limited")

を実行すれば、制限かかって、InvalidKeyException になる。

ブラウザウィンドウサイズが変化した時に処理する jQuery

ブラウザウィンドウサイズが変化した時に処理する jQuery
関数定義する。

var resizeProcess = function(p){
   var timer = false;
   $(window).resize(function(){
      if (timer !== false) clearTimeout(timer);
      timer = setTimeout(p, 200);
   });
};

使用する。

resizeProcess(function(){
     // 処理
});

祝日計算にstatic listHolidayBundle (year, month)メソッドを追加した。

祝日計算、「Java祝日計算」と命名して Java版だけのつもりだったが、途中から JavaScript版も追加
Java祝日計算 プロジェクト日本語トップページ - OSDN
このJava版の方に、日付の LocalDate オブジェクトと祝日名 String を束ねた HolidayBundle のリストを返すものを
年指定で取得できるようにしていたが、年と月、指定でも該当の月のリストを取得するものを追加した。

2019年 天皇即位の日が、祝日として休日になるのかどうか、現在まだ、わからないのでこれは未対応だ。

HolidayBundle のリストを返す listHolidayBundle (year) は、元々、

 Map<LocalDate, String> map
 = Holiday.listHolidayBundle(2018).stream().collect(()->new TreeMap<LocalDate, String>(), (r, t)->{
         r.put(t.getDate(), t.getDescription());
         Optional.ofNullable(t.getChangeDate()).ifPresent(d->r.put(d, "振替休日"));
 }, (r, u)->r.putAll(u));

こんな目的で用意していた。
でも、年と月を指定して該当月だけを取得したい場合があるので、Holiday に、

   public  static List<HolidayBundle> listHolidayBundle(int year, int month)

を追加した。

knockout.js の computed の注意

以下のような、HTMLとスクリプト

<input type="text" data-bind="value: msg1" />
<input type="text" data-bind="value: msg2" />
<span data-bind="text: res"></span>

と、

$(function(){
   var ViewModel = function(){
      this.msg1 = ko.observable('111');
      this.msg2 = ko.observable('222');
      this.res = ko.computed(function(){
         return this.msg1() + ":" + this.msg2();
      }, this);
   };

   var viewModel = new ViewModel();
   ko.applyBindings(viewModel);
});

f:id:posturan:20171220122350j:plain
で、input の valueが変化したときに、span の内容が変化するものを作ると、crome , edge はきちんと動くが
IE11では valueが変化したときに動かない。
computed に、通知をいつでも=always にしないとならない。

      this.res = ko.computed(function(){
         return this.msg1() + ":" + this.msg2();
      }, this).extend({ notify: 'always' });

書き直すと以下のとおり。

$(function(){
   var ViewModel = function(){
      this.msg1 = ko.observable('111');
      this.msg2 = ko.observable('222');
      this.res = ko.computed(function(){
         return this.msg1() + ":" + this.msg2();
      }, this).extend({ notify: 'always' });
   };

   var viewModel = new ViewModel();
   ko.applyBindings(viewModel);
});

wicket-guice 使用の見直し

だいぶ昔、6年も前、Wicket のバージョンが、1.5 に、wicket-guice の GuiceComponentInjector を
JSR330 対応させる為に、自分で書き直したりしていた。
Wicket1.5.3 の guice - IOC で、Behaviorも対象に - Oboe吹きプログラマの黙示録

そのまま同じコードが、本来の Wicket に採用されてたのを知ってはいたけど、書き直したものを
いつまでも使ってると、間接参照の問題になり、Java9 の時代のコンパイルの時代に、非常によろしくない。
見直すことなくそのまま書き直したものを使ってたというのは、反省して
WebApplication の init() で書く、getComponentInstantiationListeners() で取得したリスナにセットする
インジェクションふるまい定義として使用は、
   getComponentInstantiationListeners().add(new GuiceComponentInjector(this, new AbstractModule(){ ...
で使用するように気をつけよう。