jQuery UI の datepicker trigger を画像でなくてフォントアイコンで指定

jQuery UI の datepicker を使ってるWebサイトで、わざわざアイコンのボタンによる picker 呼出しをするデザインがなんか釈然としない。

https://jqueryui.com/datepicker/#icon-trigger

にあるようなカレンダーアイコンをクリックで呼び出すもの。これより入力フィールドをクリック、focusされた時に呼び出すのでわざわざアイコンがあるのが
釈然としない。

jqueryui.com サイトにあるサンプルは、アイコン画像も gif でありこのように画像サイズを気にしながら準備するのも煩わしい。

このアイコンをGIFでなくて、フォントアイコンで描画させてサイズ調整しても描画が乱れないようにできないだろうかと考えて試してみる。

まず。jQuery UI datepicker のデモページに書いてあるコードは

$( "#datepicker" ).datepicker({
      showOn: "button",
      buttonImage: "images/calendar.gif",
      buttonImageOnly: true,
      buttonText: "Select date"
});

と書いてあって、これで input タグの後ろに自動的に次の img タグが描画される。

<img class="ui-datepicker-trigger" src="images/calendar.gif" alt="Select date" title="Select date">

この img タグ生成させる代わりに、buttonタグ生成にさせたい。そこで、buttonImage と buttonImageOnly を指定しないようにする。

$( "#datepicker" ).datepicker({
      prevText:"前月", nextText:"翌月",
      changeMonth: true, monthNamesShort: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],
      showOn: "button",
      buttonText: "Select date"
});

この段階で、
f:id:posturan:20170415183235j:plain
ということになる。

フォントアイコンとして、Fontello - icon fonts generator から必要なフォントファイルをダウンロードして
次のように CSS を用意する。

@font-face{
	font-family: 'fontello';
	src: url('../../fontello/font/fontello.eot');
	src: url('../../fontello/font/fontello.eot#iefix') format('embedded-opentype'),
	     url('../../fontello/font/fontello.woff') format('woff'),
	     url('../../fontello/font/fontello.ttf') format('truetype'),
	     url('../../fontello/font/fontello.svg#fontello') format('svg');
	font-weight: normal;
	font-style: normal;
}
.ui-datepicker-trigger{
	font-family: "fontello";
	font-style: normal;
	font-weight: normal;
	font-size: 16[f:id:posturan:20170415184856j:plain]px;
	display: inline-block;
	text-decoration: inherit;
	cursor: pointer;
	color: #3456ff;
}

そして、datepicker設定の buttonText は、fontello の約束ではタグBODYに書くコードでアイコンを指定するので、

$(function(){
   $("#date").datepicker({
      prevText:"前月", nextText:"翌月",
      changeMonth: true, monthNamesShort: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],
      showOn: "button",
      buttonText: "&#xe860;"
   }).datepicker("setDate", moment().format('YYYY/MM/DD'));
});

すると buttonタグとしてフォントアイコン埋め込みのボタンになる。 ( HTML-BODY に背景色指定 )

f:id:posturan:20170415184320j:plain

このままでもいいけど、どうせならボタンとしての形状でなくて、アイコン画像としてフラットな描画にしたいので、CSSで以下のように追加する

.ui-datepicker-trigger{
   font-family: "fontello";
   font-style: normal;
   font-weight: normal;
   font-size: 16px;
   display: inline-block;
   text-decoration: inherit;
   cursor: pointer;
   color: #3456ff;
   /* 追加 */
   background-color: rgba(0,0,0,0);
   border: none;
}

background-color と border を指定しなおしてしまう。透過させたいので、rgba で指定する。

f:id:posturan:20170415184856j:plain

このようになる。

moment.js でリアルタイムに日付時刻を表示

moment.js でリアルタイムに日付時刻を表示する。

jQuery と moment-with-locales.js を使う。

<script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="js/moment-with-locales.js"></script>
<div>
   <h1 id="date"></h1>
   <h2 id="hour_min_sec"></h2>
</div>

自分で clock関数、1秒間隔実行を用意して実行する。

$(function(){
   moment.updateLocale("ja",
         { weekdays: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
            weekdaysShort: ["日","月","火","水","木","金","土"], }
   );

   var clock = function(){
      var m = moment();
      setTimeout(clock, 1000);
      /* 表示。極力他の処理をやらない */
      $('#date').html(m.format("YYYY年 M月 D日 (ddd)")),
      $('#hour_min_sec').html(m.format("HH:mm:ss"));
   }
   clock();
});

ミリ秒、マイクロ秒の単位まで精度を求めないならこれで充分。

moment.js で曜日出力に注意

2年近く前に知ってから愛用している moment.js 曜日を出力しようと思って、
各国語対応の moment-with-locales.js を使ったら フォーマット dddd  または、ddd を使ったら曜日が日本語で出力されない。
あれ、そうだっけ?!

しかたなく、moment-with-locales.js 利用のまま、、moment.js の locale 関数を呼ぶことにしたら、ちゃんと曜日が出るものの、
chrome のコンソールをチェックすると、

Deprecation warning: use moment.updateLocale(localeName, config) to change an existing locale.
 moment.defineLocale(localeName, config) should only be used for creating a new locale
 See http://momentjs.com/guides/#/warnings/define-locale/ for more info.

ネットで検索してたら、、
github.com

なんだと! locale 関数じゃなくて、結局、updateLocale 関数を呼ぶのか!!

moment-with-locales.js 利用では、

moment.locale("ja",
   { weekdays: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
    weekdaysShort: ["日","月","火","水","木","金","土"], }
);

でなくて、、

moment.updateLocale("ja",
   { weekdays: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
    weekdaysShort: ["日","月","火","水","木","金","土"], }
);

moment.min.js を利用するなら、locale関数、

もっとも、moment-with-locales.js を使わずに、moment.min.js と、

https://github.com/moment/moment

ここから、locale にある ja.js を使用することにすれば、locale 関数も updatelocale関数も呼ばなくて済む。
CDNからの取得で書くと

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/locale/ja.js"></script>

だけどダウンロードして自分ところで抱えて使う。

(1) moment-with-locales.js を使う場合
  自分のコードで moment updateLocale関数を実行
(2) moment.min.js を使う場合
  自分のコードで moment locale関数を実行
(3) moment.min.js と ja.js を使う場合
   locale 関数等は呼ばない。

(1) のmoment-with-locales.js をよく使ってたから、updateLocale関数呼出しが面倒でも
これが良いのか?

たった曜日のために。。悩ましい。

jQuery ui の アイコンフォント

jQuery ui  の アイコンフォント見つけた。

 

mkkeck.github.io

 

jQuery UI のアイコンはサイズが決まったものしか使えずなにかと不便だったけど

これなら、

<link rel="stylesheet" type="text/css"  href="jquery-ui-1.12.icon-font.min.css" />

のように使用宣言して

<span style="font-size: 32px;color:#009000" class="ui-icon ui-icon-jquery">icon</span>

でいける。

 

 

 

 

 

MAVEN2_CLASSPATH_CONTAINER は、エクスポートまたは公開されません。の警告

時々、Eclipse MAVEN プロジェクトを作成していると、

クラスパス・エントリー org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER は、エクスポートまたは公開されません。実行時に ClassNotFoundExceptions が発生する可能性があります。

なる警告が発生する。

この警告が出ないようにする方法を調べていたら、.classpath に 以下を追記する方法があった。

<attributes>
   <attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>

リストの順序を保持したグルーピング

リストをグルーピング、しかしあくまでも順序付けされた並びの中でのグルーピングで同じキーのグループが複数あっても
まとめない。
という要求があった時、少し悩んだ。

サンプルとなるお題、、、要素のキーが以下のようにならんでいる場合、

A , A , A , B , B , A , A , D , C , C , E , E

求めたい結果は、順序どおりのグルーピングで、リストの INDEX とカウントで以下のような結果が欲しいのが
今回のお題。

index = 0   count = 3  → A , A , A の3個をカウント
index = 3   count = 2  → B , B     の2個をカウント
index = 5   count = 2  → A , A     の2個をカウント
index = 7   count = 1  → D         の1個をカウント
index = 2   count = 2  → C , C     の2個をカウント
index = 2   count = 2  → E , E     の2個をカウント

このように、A のキーをグルーピングといっても隣接だけのグルーピングでカウントする、つまりリストの並びに沿う。

何の目的で、このような結果を求めたいかというと、Excel や HTMLで表現するテーブル表にこのカウント方法に従った結果が
欲しいことがあるからだ。

Javaストリームの java.util.stream.Collectors#groupingBy を使ってしまうと、この上のサンプルで、A は 5個の
グルーピングになってしまう。
さらに、リストの 開始INDEXを求めたい。
このような課題が出現する箇所でループ文をいつもコーディングするのは、毎回コーディングに気をつけなくてはならない。
のでバグを書きやすい。

リストの要素からキーを求める java.util.function.Function を引数にした static メソッドを用意した。

/**
 * リスト→グループ開始index:カウントのマップ生成.
 * @param list リスト
 * @param getKey 要素からグルーピングするキー文字列を取得する Function
 * @return key=グループ開始index , value=グルーピングしたカウント
 */
public static <E> Map<Integer, Integer> groupingCountIndexMap(List<E> list, Function<E, String> getKey){
   Map<Integer, Integer> map = new HashMap<>();
   if (list.size()==0) return map;
   int index = 0;
   int count = 1;
   int row = 0;
   ListIterator<E> it = list.listIterator();
   while(it.hasNext()){
      String s = getKey.apply(it.next());
      if (it.hasNext()){
         if (s.equals(getKey.apply(it.next()))){
            count++;
         }else{
            map.put(row, count);
            count = 1;
            row = index + 1;
         }
         it.previous();
      }
      index++;
   }
   map.put(row, count);
   return map;
}

テスト例、、、
文字列リストでも試せるが、それではあまりにも芸がないので、Item というクラスが、public属性文字列 name を
持っているとする。

public class Item{
   public String name;
}

A , A , A , B , B , A , A , D , C , C , E , E の並びで、List を用意する。

List<Item> list;

/* 省略   */

Map<Integer, Integer> map = groupingCountIndexMap(list, e->e.name);

System.out.println(map);

標準出力として次の結果が得られる。

{0=3, 3=2, 5=2, 7=1, 8=2, 10=2}


以前、groupingBy は、

groupingBy - Oboe吹きプログラマの黙示録


Java8 StreamでWicket ListViewセル結合 - Oboe吹きプログラマの黙示録


とメモを書いたことがあったけど、改めて考えると面白い。

POI で セル書込み時に Optional を使う

Apache POI メモリ消費量が増えやすいし、今となっては使いにくい。
Excel の場合、セルのスタイル設定は今のメソッドは、まあ許すとして
セルの値セットや、スタイル適用のメソッドが実行後のセルを返してくれれば、数珠つなぎにメソッド呼べるのに。。

そこで思いついたのは、Java8 からの java.util.Optional で括って ifPresent の Consumer を使う方法
邪道かもしれないけど。

こんな風に。。。

try(InputStream is = new FileInputStream("sample.xlsx");
FileOutputStream out = new FileOutputStream(new File("test.xlsx"));){
   XSSFWorkbook book = new XSSFWorkbook(is);
   XSSFSheet sheet = book.getSheetAt(0);
   XSSFCellStyle style = book.createCellStyle();
   style.setBorderTop(BorderStyle.THIN);
   style.setTopBorderColor(IndexedColors.BLACK.index);
   style.setBorderBottom(BorderStyle.THIN);
   style.setBottomBorderColor(IndexedColors.BLACK.index);
   style.setBorderRight(BorderStyle.THIN);
   style.setRightBorderColor(IndexedColors.BLACK.index);
   style.setBorderLeft(BorderStyle.THIN);
   style.setLeftBorderColor(IndexedColors.BLACK.index);
   style.setAlignment(CellStyle.ALIGN_CENTER);
   style.setVerticalAlignment(CellStyle.VERTICAL_CENTER );

   IntStream.rangeClosed(0, 8).boxed().forEach(rownum->{
      XSSFRow row = sheet.createRow(rownum);
      IntStream.rangeClosed(0, 4).boxed().forEach(columnIndex->{

         Optional.of(row.createCell(columnIndex)).ifPresent(cell->{
            cell.setCellValue( rownum + "-" + columnIndex );
            cell.setCellStyle(style);
         });

      });
   });
   book.write(out);
}catch(Exception e){
   e.printStackTrace();
}