モーダルウィンドウ使用時の datepicker

Wicket のモーダルウィンドウ使用時に注意しなければならないのは、
呼び出し Page とモーダルウィンドウの Panel 両方で jQuery Datepicker を配置したときである。
モーダルウィンドウを起動したとき、モーダルウィンドウの中で Datepicker が効かなかったり、
モーダルウィンドウを起動後、むりやり Datepicker を再配備しても、モーダルウィンドウのを閉じた後に
Page の Datepicker が効かなくなったりした。

対処:

モーダルウィンドウ起動後、描画が終わったら、、

$("#ui-datepicker-div").remove();
$.datepicker.setDefaults( $.datepicker.regional["ja"] );
$("input[class='datepicker']").datepicker({
   prevText:"前月", nextText:"翌月",
   changeMonth: true,
   changeYear: true, yearRange: '-4:+6',
});

モーダルウィンドウを閉じたら、

$("#ui-datepicker-div").remove();
$("input[class='datepicker']").removeClass("hasDatepicker");
$("input[class='datepicker']").datepicker({
   prevText:"前月", nextText:"翌月",
   changeMonth: true,
   changeYear: true, yearRange: '-4:+6',
});

という datepicker設置で作られるdocumentを削除して、
datepicker にされた inputタグを、一度 hasDatepicker と付与されたクラス属性を削除してから
datepicjer 再定義をする。

datepicker の destroy かと思ったけどこの方が確実みたい。

任意のセレクタまで、アニメーションでスクロール

memo

任意のセレクタまで、アニメーションでスクロールさせる。

例)table の tbody でスクロールを書いた時など。。。

$('tbody').animate({scrollTop:$('tbody tr:nth-child(20)').offset().top});

offset() でスクロールで表示させたい行のオブジェクトを取得して top で位置を参照する。

Wicket 8.0.0-M4 から M5 で、AjaxButton.onSubmit が。。。

Wicket 8 の機能として注目だったラムダの対応も、 8.0.0-M4 までは、

onSubmit(String id, SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onSubmit
  , SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onError)

onSubmit(String id, SerializableBiConsumer<AjaxButton, AjaxRequestTarget> onSubmit)

これらのメソッドが加わっていて喜んだのだが、

8.0.0-M5 で、消えている!! 従来の onSubmit と onError をオーバーライドで書かなくてはならない。

非常に残念だ!


もう、本当になくなってしまうのか!


いや!!心配ない。

5月24日に書いた。。。

oboe2uran.hatenablog.com

Wicket8 の Tomcat 8 で Websocket に苦戦中

2017-6-25 に回答

oboe2uran.hatenablog.com


先日、Wicket 8 の websocket - Oboe吹きプログラマの黙示録 で書いたが、改めて取り掛かった。

Wicket の native-Websocket を使おうと、Tomcat 8.0.43 で起動できない。
Websocket にそんなに魅力を感じてるわけでもなく別の手段を選ぶことが多いのだが。。。調べてみる。

    <dependency>
      <groupId>org.apache.wicket</groupId>
      <artifactId>wicket-native-websocket-tomcat</artifactId>
      <version>8.0.0-M3</version>
   </dependency>

   <dependency>
     <groupId>org.apache.wicket</groupId>
      <artifactId>wicket-native-websocket-javax</artifactId>
      <version>8.0.0-M5</version>
   </dependency>

もう、この時点、wicket-native-websocket-tomcat 8.0.0-M3 と名前になっていても、中は、Tomcat7 の
org.apache.wicket.protocol.ws.tomcat7.Tomcat7WebSocketFilter なので、うまく動かないのはあたりまえだ。


たくさんエラー出て起動できない

Caused by: java.lang.ClassNotFoundException: org.apache.coyote.http11.upgrade.UpgradeInbound
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167)
	... 20 more

重大: Failed to destroy end point associated with ProtocolHandler ["http-nio-8080"]
java.lang.NullPointerException
	at org.apache.tomcat.util.net.NioEndpoint.releaseCaches(NioEndpoint.java:315)
	at org.apache.tomcat.util.net.NioEndpoint.unbind(NioEndpoint.java:491)
	at org.apache.tomcat.util.net.AbstractEndpoint.destroy(AbstractEndpoint.java:883)
  :
  :

4 29, 2017 2:28:23 午後 org.apache.coyote.AbstractProtocol destroy
情報: Destroying ProtocolHandler ["ajp-nio-8009"]
4 29, 2017 2:28:23 午後 org.apache.coyote.AbstractProtocol destroy
重大: Failed to destroy end point associated with ProtocolHandler ["ajp-nio-8009"]
java.lang.NullPointerException
	at org.apache.tomcat.util.net.NioEndpoint.releaseCaches(NioEndpoint.java:315)
	at org.apache.tomcat.util.net.NioEndpoint.unbind(NioEndpoint.java:491)
	at org.apache.tomcat.util.net.AbstractEndpoint.destroy(AbstractEndpoint.java:883)

ClassNotFoundException: org.apache.coyote.http11.upgrade.UpgradeInbound

だから、7系の Tomcat coyote を持ってくる。

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-coyote</artifactId>
    <version>7.0.73</version>
</dependency>

それでも、まだ次のエラーになる。

重大: フィルタ WebSocketFilter の起動中の例外です
java.lang.NoSuchFieldError: ISO_8859_1
	at org.apache.wicket.protocol.ws.tomcat7.Tomcat7WebSocketFilter.<clinit>(Tomcat7WebSocketFilter.java:43)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:119)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:258)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4700)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5340)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

Tomcat7WebSocketFilter が、エンコードの文字セット定義を org.apache.tomcat.util.buf.B2CConverter から持ってきて
初期化しようとして失敗している。

Tomcat8 に、無理やり、7系で用意されたライブラリを組み合わせて起動しようとしていること自体がアホだと
思いつつ、なんとか手を掛けないで、、、と甘い考えがだめだった。

ならば、Wicket が配布した Tomcat7WebSocketFilter を参考に、Tomcat8 用の WebSocketFilter を作ろう!!

B2CConverterも自分で用意して、

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>7.0.77</version>
</dependency>

文字コード系は、対応をする。これで起動はするのだが、実際の Websocket エンドポイントを割り当てがうまくいくかと
いうと、そうはいかない!!

org.apache.catalina.connector.RequestFacade の doUpgrade をなんとかしなくてはならない!!

まだまだ、苦戦しそう。。

input テキストフィールドでカーソルの位置を指定する。

HTML  input テキストフィールドで任意の範囲を選択するには、

<input type="text" value="1234567890">

jQuery で、focus して、setSelectionRange( 開始位置、終了位置 );

    $('input').focus().get(0).setSelectionRange(3, 6);

f:id:posturan:20170425223953j:plain

setSelectionRange で指定する値は、0始まりで数える。

この setSelectionRange を使って、カーソルの位置を任意の位置に指定することができる。
→ 開始位置 と 終了位置を同じにすれば、その位置にカーソルを持ってくることができる。

    $('input').focus().get(0).setSelectionRange(3, 3);

これは、上の input であれば、3と4の間にカーソルがくる。
以下でも同じくカーソルが3と4の間にくるが、

$('input').get(0).selectionStart = 3;
$('input').get(0).selectionEnd = 3;

selectionEnd を 6 で指定して

$('input').get(0).selectionStart = 3;
$('input').get(0).selectionEnd = 6;

これで、範囲選択になるのかというとそうではない。setSelectionRange( 開始位置、終了位置 ); で同じ値をセット
するというので、カーソルの位置を任意の位置に指定すると覚えた方が良い気がする。

現在のカーソル位置に、任意の文字を挿入したいなら、

var pos =  $('input').get(0).selectionStart;
$('input').val( $('input').val().substr(0, pos) + '-' + $('input').val().substr(pos));

3の後にカーソルを充てて、
f:id:posturan:20170425230604j:plain