flex による均等な3分割レイアウト

他にも応用がきくので、コピペの為にメモ。

<div class="container-parent">
   <div class="container"></div>
   <div class="container"></div>
   <div class="container"></div>
</div>

<ul class="container-parent">
   <li class="container"></li>
   <li class="container"></li>
   <li class="container"></li>
</ul>

calc で計算して width を指定する。(レスポンシブも例として書いてる)

.container-parent{
   display: flex;
   display: -webkit-flex;
   flex-wrap: wrap;
}
.container{
   width: calc(100% / 3);
   width: -webkit-calc(100% / 3);
   text-align: center;
}
@media (max-width: 800px){
   .container{
      flex: 100%;
      max-width: 100%;
   }
}

width: 33.33333% と指定するのをネット検索してよく見かけるが、
calc対応ブラウザなら、calcを使うべきだ。
https://caniuse.com/#search=calc
で確認すると良いだろう。
ベースとしてのサンプル用CSS

body{  margin: 0; padding: 0; }
ul{ list-style: none; margin: 0; padding: 0; }
.container-parent div:nth-child(1), .container-parent li:nth-child(1){ background-color: #cefff5; }
.container-parent div:nth-child(2), .container-parent li:nth-child(2){ background-color: #abde89; }
.container-parent div:nth-child(3), .container-parent li:nth-child(3){ background-color: #f2eab5; }

例)
f:id:posturan:20190414110334j:plain
幅 800px 以下にブラウザを縮めた時、
f:id:posturan:20190414110422j:plain
境界線を付ける場合は、margin で描画させて、calc()の中でその分調整する。

.container-parent{
   display: flex;
   flex-wrap: wrap;
   padding: 1px;
   background-color: #909090;
}
.container{
   width: calc(100% / 3 - 5px);
   width: -webkit-calc(100% / 3 - 5px);
   margin: 2px;
   text-align: center;
}

更にコンテンツを中央にする場合は、
コンテンツでも、display: flex;
そして、flex-direction: column; として
justify-content 属性を指定する

.container-parent{
   display: flex;
   display: -webkit-flex;
   flex-wrap: wrap;
}
.container{
   width: calc(100% / 3);
   width: -webkit-calc(100% / 3);
   height: 100px;
   display: flex;
   display: -webkit-flex;
   text-align: center;
   flex-direction: column;
   -webkit-flex-direction: column;
   justify-content: space-around;
   -webkit-justify-content: space-around;
}

float 属性を指定しない横並び配置のデザイン - Oboe吹きプログラマの黙示録

jsTreeノード選択イベントのdata引数

以前、
oboe2uran.hatenablog.com

を書きましたが、
この時、選択配下のノードツリーを配列JSONで取得する処理
on メソッドで、select_node.jstree でイベントと結合して

$('#tree').jstree({
'core':{
   data':{
         "url":"./tree.json",
         "dataType":"json"
      },
}).on('select_node.jstree', function(e, data){
    var selectedAry = $('#tree').jstree(true).get_json(data.node.id, {flat:true});
   
});

と書いて、

    var selectedAry = $('#tree').jstree(true).get_json(data.node.id, {flat:true});

$('#tree')と書くのがあまりよくないと思ってました。

jsTreeノード選択イベントの data 引数のinstance 属性が、
jsTreeオブジェクトそのもののはずです。
よって、以下のように書けるはずです。

}).on('select_node.jstree', function(e, data){
   var ary = data.instance.get_json(data.node.id, {flat:true});
   
   $.each(ary, function(i, e){
      console.log("id="+e.id+" icon="+e.icon+" text="+e.text+" parent="+e.parent);
   });
});

このように、HTML ID識別子による jstree(true) から get_json するのではなく
jsTree イベントの data からインスタンスオブジェクトを参照すべきです。

pdfkit ページヘッダを付ける

Python pdfkit で、ページ番号などページヘッダを付ける方法のメモ
wkhtmltopdf のオプション説明 Help を読めばいいのですが、
https://wkhtmltopdf.org/usage/wkhtmltopdf.txt

オプションに、header-left で、ヘッダ左端に付与する文字列、
header-right でヘッダ右端に付与する文字列を
header-center でヘッダ中央に付与する文字列を
指定することになっており、

'header-left': '[webpage]',
'header-right': 'Page  [page]  of  [toPage]'

で、
[webpage] → URL参照のパス
[page] → ページ番号
[toPage] → 総ページ数

に置き換わります。

# -*- coding: UTF-8 -*-
import pdfkit

options = {
    'page-size': 'A4',
    'orientation': 'Portrait',
    'margin-top': '0.4in',
    'margin-right': '0.4in',
    'margin-bottom': '0.4in',
    'margin-left': '0.4in',
    'encoding': "UTF-8",
    'no-outline': None,
    'header-left': '[webpage]',
    'header-right': 'Page  [page]  of  [toPage]'
}
pdfkit.from_file("sample.html", "out.pdf", options=options)

このように Python スクリプトを書くことになります。

フッタを付与する場合も、単純に、"header" → "footer" に置き換わった指定をするだけです。
footer-left :フッタ左端
footer-right :フッタ右端
footer-center :フッタ中央

また、ヘッダ部分を別のHTML で用意するカスタムヘッダの方法もあり、
その場合は、--header-html で、ヘッダHTMLを指定します。

options = {
    'page-size': 'A4',
    'orientation': 'Portrait',
    'margin-top': '0.4in',
    'margin-right': '0.4in',
    'margin-bottom': '0.4in',
    'margin-left': '0.4in',
    'encoding': "UTF-8",
    'no-outline': None,
    '--header-html': 'header.html'
}

のように option を指定してます。

Wicket 8.4.0 がリリース

Wicket 8.4.0 がリリースされた。

やっと修正されたバグ
[WICKET-6639] - PageStoreManager$SessionEntry.clear produces NullPointerException

https://issues.apache.org/jira/projects/WICKET/issues/WICKET-6639?filter=allissues

監視プロセスからの PageStoreManager のページエントリキャッシュのクリアのバグで
緊急性は低く、害は無かったものの、ログにこの NullPointerException が出ると
後味が悪かった。。

過去見つけた、これが解決するのだ。
http://oboe2uran.hatenablog.com/entry/2018/10/28/152613

Java→Python Pdfkit実行→PDF受け取る

Wicket で、Python Pdfkit実行してPDFダウンロードさせる方法を考えました。
このメリットは、
・作成するPDFが、PdfkitがHTMLからPDFへの変換であることから
 WicketでブラウザにWeb Page 表示してPDF作成イメージを確認できること。
・HTMLでPDFのテンプレートを構成できることです。

実行する Pytyon スクリプトは標準入力で、URL、ページ種別(A4 等)、縦横の向きを
認識して、標準出力でPDFを出力します。
呼出し元のJava 側では、プロセス起動で Pythonスクリプト実行して、
 標準出力ストリーム → Pytyon スクリプト標準入力
 標準入力ストリーム ← Pytyon スクリプト標準出力
になるようにします。
これは、yipuran-core にある ScriptExecutor.runStream を使用します。
↓↓↓
https://github.com/yipuran/yipuran-core/wiki/Script_exec

URL,ページ種別, 縦横の向き(Portrait or Landscape)を受信してPDFを標準出力するスクリプト
WebPageToPdf.py

# -*- coding: UTF-8 -*-
import sys
import pdfkit

def pageToPdf(url, pagesize='A4', orientation='Portrait'):
    options = {
        'page-size': pagesize,
        'orientation': orientation,
        'margin-top': '0.4in',
        'margin-right': '0.4in',
        'margin-bottom': '0.4in',
        'margin-left': '0.4in',
        'encoding': "UTF-8",
        'no-outline': None
    }
    pdf = pdfkit.from_url("%s" % url, False, options=options)
    sys.stdout.buffer.write(pdf)

inlist = []
try:
    while True:
        inp = input('')
        if inp == '': break
        inlist.append(inp)
except EOFError:
    sys.stdout.buffer.write("ERROR")
    pass
if inlist.__len__()==2:
    pageToPdf(inlist[0], inlist[1])
elif inlist.__len__()==3:
    pageToPdf(inlist[0], inlist[1], inlist[2])
else:
    pageToPdf(inlist[0])


WicketPage AJAX Dowanload Behavior として、記述するコード例

この中の AJAXDownload は、以下を参照
https://github.com/yipuran/yipuran-wicketcustom/wiki

ボタンクリックで実行する SerialThrowableConsumer は、以下を参照
https://github.com/yipuran/yipuran-wicketcustom/blob/master/src/main/java/org/yipuran/wicketcustom/function/SerialThrowableConsumer.javayipuran-wicketcustom/SerialThrowableConsumer.java at master · yipuran/yipuran-wicketcustom · GitHub

final AJAXDownload sampleDownload = AJAXDownload.of(out->{
   // Python スクリプト
   String script = "python " + dirctorypath + "/WebPageToPdf.py";
   // URL セット
   list.add( urlstring );
   list.add("\n");
   list.add("A4");
   list.add("\n");
   list.add("Portrait");
   list.add("\n");
   list.add("\n");
   int sts = ScriptExecutor.runStream(()->script, ()->list, inst->{
      try{
         inst.transferTo(out);
         out.flush();
         out.close();
      }catch(Exception ex){
         throw new RuntimeException(ex);
      }
   }, (e, x)->{
      logger.error(x.getMessage(), x);
   });
}, ()->"application/pdf", ()->"test.pdf");

queue(new Button("pdfdownload").add(AjaxFormSubmitBehavior.onSubmit("click"
, SerialThrowableConsumer.of(t->{
   // callback!!
   sampleDownload.callBackDownload(t);
}, (u, x)->{
   logger.error(x.getMessage(), x);
}))).add(sampleDownload) );

Python スクリプトが、PDF変換前のURL、ページ種別、向きだけを受信するように
書いていますが、動的に変化するPDF作成なら、
Java からのPython スクリプト実行の入力リストにパラメータを追加して、
Python スクリプトで、PDF変換前のURL受信したパラメータをURLパラメータに
追加すれば、動的なWebPage→ 動的に変化するPDF作成
になるはずです。

PDFの改ページを自由に配置するには、
PDF に変換される WebPage のHTML で

<div style="page-break-after:always;"></div>

を差し込みます。
つまり、CSSで、

     page-break-after : always;

を効かせてあげれば良いわけです。
pdfkit が内部で、wkhtmltopdf を実行するからです。
wkhtmltopdf もインストールして置く必要あります。

pdfkit の from_url

pdfkit.from_file( HTMLファイルPATH , 出力PDFファイルPATH , options=options)
pdfkit の from_file だけでなく憶えときたいもの。。

pdfkit.from_url( url , 出力PDFファイルPATH , options=options)

変数に出力 : False を付ける
pdf = pdfkit.from_url( url , False , options=options)

pdf = pdfkit.from_file( HTMLファイルPATH , False , options=options)

変数に出力したものを、import sys で、sys.stdout.buffer.write で書き出せば標準出力