6月は誕生月です、昨日の自分からの今日の自分への誕生日プレゼントをお披露目します。
考える人
考えすぎた人
走りながら考える人?
ほんとに考えているの?...な人
いろいろなポーズ、しばらく楽しめそうです。
昨日なんてもうあらへん
明日なんてまだあらへん
あるのんは今日だけどす
キモサベ!!
--- zul ---
<window title="動的に追加した最後の行を必ず見えるようにする方法" border="normal"
apply="ctrl.MyCtrl" width="350px">
<grid height="50px">
<rows id="rows" />
</grid>
<button label="行を追加" id="addBtn" />
</window>
--- java ---
public class MyCtrl extends GenericForwardComposer {
private Rows rows;
private static int count=0;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
}
public void onClick$addBtn(){
count++;
Row row =new Row();
row.appendChild(new Label("new"+count));
row.setParent(rows);
Clients.scrollIntoView(row);
}
}
JavaのコントローラからJavaScriptのコードを実行させることが必要に なるケースがあるかもしれません。 例えばサーバ・プッシュを使い下記の様な処理をする場合が考えられます。サーバ・サイドでイベントを発行する そのイベントは専用のスレッドで操作される そのスレッドの中からなにがしかのJava Script関数をコールしたい こんな時はこんな風に!! Clients.evalJavaScript("alert('Hello World!')); 簡単でしょ?
--- zul --
<window title="JavaコントローラからJavaScript関数をコールする"
apply="zkexamples.ViewController2" border="normal" width="350px">
<button id="btn" label="click" />
</window>
--- java ---
public class ViewController2 extends GenericForwardComposer {
public void onClick$btn(Event event){
Clients.evalJavaScript("alert('Hello world!');");
}
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
}
}
function callJavaMethod(){
zAu.send(new zk.Event(zk.Widget.$(this), 'onLinkClicked', 'Parameter'));
}
zk.Widget.$(this) => 親コンポーネント(この場合は "rootwindow"を指す)
'onLinkClicked' => 送出するイベントを処理するコントローラのイベントハンドラメソッド名
'Parameter' => イベントハンドラへ渡すパラメータ。(オプション)
※イベントハンドラ内で Event event を ForwardEventにキャストし
getOrigin().getData()でパラメータの値を取得できる。
public void onLinkClicked$rootwindow(Event event){
someJavaMethod();
}
--- zul ---
<window id="rootwindow"
title="JavaScriptからJavaコントローラのメソッドをコールする" border="normal"
apply="zkexamples.calljavafromjavascript.ViewController">
<html><![CDATA[
<script type="text/javascript">
function callJavaMethod(){
zAu.send(new zk.Event(zk.Widget.$(this), 'onLinkClicked', 'Parameter'));
}
</script>
<a href="#" onClick="callJavaMethod();">Click me</a>
]]></html>
</window>
--- java ---
public class ViewController extends GenericForwardComposer {
// JavaScriptからイベントハンドラを経由してコールされるコントローラのメソッド
private void callMe() {
alert("Hello JavaScript, this is Java!");
}
// コントローラのイベントハンドラ名の最後に親コンポーネント名をつけること忘れないこと!!
public void onLinkClicked$rootwindow(Event event){
ForwardEvent fevent = (ForwardEvent)event;
System.out.println(fevent.getOrigin().getData());
callMe();
}
}
簡単な使い方:
--- zul ---
<button id="uploadBtn" label="Upload file" upload="true,maxsize=300"/>
--- java ---
public void onUpload$uploadBtn(UploadEvent event) throws InterruptedException {
org.zkoss.util.media.Media media = event.getMedia();
Medias.saveToFile(media, "/path/to/save");;
}
ヘルパークラス
--- Medias.java ---
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import org.apache.commons.io.IOUtils;
import org.zkoss.util.media.Media;
public class Medias {
public static File saveToFile(Media media, String path) {
try {
File file = new File(path + File.separator + media.getName());
OutputStream output = new FileOutputStream(file);
if (media.isBinary()) {
InputStream input = Medias.asStream(media);
IOUtils.copy(input, output);
input.close();
} else {
Reader input = Medias.asReader(media);
IOUtils.copy(input, output);
input.close();
}
output.close();
return file;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String asString(Media media) {
try {
String result = null;
if (media.isBinary()) {
InputStream input = Medias.asStream(media);
result = IOUtils.toString(input);
input.close();
} else {
Reader reader = Medias.asReader(media);
result = IOUtils.toString(reader);
reader.close();
}
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static InputStream asStream(Media media) {
return new BufferedInputStream(
media.inMemory() ?
new ByteArrayInputStream(media.getByteData()): media.getStreamData());
}
private static Reader asReader(Media media) {
return new BufferedReader(media.inMemory() ?
new StringReader(media.getStringData()) : media.getReaderData());
}
}
ビュー
--- fileupload.zul ----
<?page title="ファイルアップロード" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="ファイルアップロード" border="normal" apply="sample.ctrl.UploadCtrl ">
<button id="uploadBtn" label="Upload file" upload="true,maxsize=300" />
<separator />
<image id="img" />
<separator />
<label id="msgLbl" />
</window>
</zk>
コントローラ
--- FileUploadCtrl.java ---
public class FileUploadCtrl extends GenericForwardComposer {
private Label msgLbl;
private Image img;
public void onUpload$uploadBtn(UploadEvent event) throws InterruptedException {
msgLbl.setValue("");
org.zkoss.util.media.Media media = event.getMedia();
if(media == null){
msgLbl.setValue("ファイルを選択してください。");
return;
}
if (media instanceof org.zkoss.image.Image) {
org.zkoss.zul.Image image = new org.zkoss.zul.Image();
image.setContent((org.zkoss.image.Image)media);
image.setParent(img);
}
Medias.saveToFile(media, "/path/to/save");;
}
}
import nl.captcha.Captcha;
import nl.captcha.backgrounds.GradiatedBackgroundProducer;
import nl.captcha.text.renderer.ColoredEdgesWordRenderer;
/**
* CAPTCHAを作成するユーティリティクラス <br>
* Captchaは直接 org.zkoss.zul.Imageにロード可能 <br>
*
* <pre>
* Image img = new org.zkoss.zul.Image();
* img.setContent(CaptchaUtils.getCaptcha());
*
* String verifyStr = captcha.getAnswer();
* </pre>
*
* @author Stephan Gerth
*/
public class CaptchaUtils
public CaptchaUtils(){
}
/**
* 5桁のキャプチャを作成する
*/
public static Captcha getCaptcha() {
Captcha captcha = new Captcha.Builder(140, 50)
.addText(new ColoredEdgesWordRenderer()).addNoise()
.addBackground(new GradiatedBackgroundProducer())
.addBorder()
.build();
return captcha;
}
}
public class CaptchaCtrl extends GenericForwardComposer {
private static final long serialVersionUID = -804655396850565215L;
private Image img_captcha;
private Textbox txt_captcha;
private Captcha captcha;
public void onCreate$win(Event event){
doReCaptcha();
}
public void onClick$btn1(Event event){
if (txt_captcha.getValue().equals(captcha.getAnswer())){
alert("正しいキャプチャです。");
} else {
alert("間違っています!!");
}
}
public void onClick$btn2(Event event){
doReCaptcha();
}
/**
* キャプチャを再表示する<br>
*
*/
private void doReCaptcha() {
captcha = CaptchaUtils.getCaptcha();
img_captcha.setContent(captcha.getImage());
}
}
<window id="win" border="normal" width="350px"
title="コミュニティ・エディションでもキャプチャが使えます" apply="ctrl.CaptchaCtrl" >
<vlayout id="input" width="100%" >
<hbox>
<image id="img_captcha" />
<button label="再表示" id="btn2"/>
</hbox>
キャプチャを入力してください。
<textbox id="txt_captcha" hflex="1" width="250px"/>
<button label="確認" id="btn1"/>
</vlayout>
</window>
システム>システム管理> ソフトウェア・ソースを選択
ソフトウェア・ソース画面の[他のソフトウェア]タブを選択
[追加]をクリック
APTライン: ppa:eee-control/eee-controlを入力
[ソースを追加]をクリック
$ sudo apt-get install eee-control
$ sudo vi /etc/default/grub
#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi_osi=Linux"
$ sudo update-grub
$ sudo shutdown -r now
[Fri Dec 04 08:44:47 2009] [error] [client 127.0.0.1] Premature end of script headers: hogehoge.cgi
env.c:257:in oci8lib.so: Error while trying to retrieve text for error ORA-12705 (OCIError)
from /usr/local/lib/site_ruby/1.8/oci8.rb:229:in `initialize'
from /usr/local/lib/site_ruby/1.8/hoge/hogehoge.rb:309:in `new'
from /usr/local/lib/site_ruby/1.8/hoge/hogehoge.rb:309:in `initialize'
from /var/www/hogehoge.cgi:4:in `new'
from /var/www/hogehoge.cgi:4
...
SetEnv LD_LIBRARY_PATH /opt/oracle/instantclient_11_2
SetEnv NLS_LANG Japanese_JAPAN.UTF8
...
[ticket-workflow]
revise = new,revised -> revised
revise.name = 課題を修正する
revise.permissions = TICKET_MODIFY
accept = new,revised,reopened -> accepted
accept.name = 着手する
accept.operations = set_owner_to_self
accept.permissions = TICKET_MODIFY
reopen = resolved,closed -> reopened
reopen.operation = del_resolution
reopen.permissions = TICKET_CREATE
reopen.name = 差し戻す
resolve = accepted -> resolved
resolve.name = 解決にする
resolve.operations = set_resolution
resolve.permissions = TICKET_MODIFY
close = resolved -> closed
close.name = 終了にする
close.permissions = TICKET_MODIFY
カスタマイズしたワークフローを画像で確認する。
Trac-0.11.2.1.ja1/contrib/workflow/workflow_parser.py trac.ini
...
UnicodeEncodeError: 'ascii' codec can't encode ...
import locale, codecs を追加し
sys.stdout.write(''.join(digraph_lines))
を
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout);
sys.stdout.write(''.join(digraph_lines))
に修正してから動作確認。
$ workfloe_parser.py trac.ini > trac.dot
$ dot -T png < trac.dot > trac.png

public class DateUserWAREKI implements TypeConverter {
@Override
public Object coerceToBean(Object arg0, Component arg1) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object coerceToUi(Object arg0, Component arg1) {
if (arg0 == null) {
return null;
}
Locale locale = Locale("ja","JP","JP");
SimpleDateFormat sdf = new SimpleDateFormat("GGGGyy年M月d日", locale);
Date date = (Date) arg0;
return sdf.format(date);
}
}
<listcell label="@{employee.hireDate, converter='org.zkforge.converters.DateUserWAREKI'}"/>
<listcell label="@{employee.hireDate, converter='org.zkforge.converters.DateUser'}"/>
public void onClick$selectedBtn(Event e) throws Exception{
Employee selected =(Employee)win.getVariable("selected", true);
if (selected != null){
alert(selected.firstName);
}
}
public void onClick$clearBtn(Event e) throws Exception{
empData = null;
empListbox.unsetVariable("selected", true);
binder = (AnnotateDataBinder)page.getVariable("binder");
binder.loadAll();
}
public void onClick$clearSelBtn(Event e) throws Exception{
empListbox.unsetVariable("selected", true);
binder = (AnnotateDataBinder)page.getVariable("binder");
binder.loadAll();
}
<window id="win" title="MVCサンプル" border="normal" width="300px" apply="Controler1">
<hbox>
<intbox id="arg1"/> + <intbox id="arg2"/> <button label=" = " id="addBtn" /> <label id = "ans"/>
</hbox>
</window>
public class Controler1 extends GenericForwardComposer {
private Intbox arg1; //ビューの<intbox id="arg1"/>コンポーネントと自動的に紐付けされる
private Intbox arg2; //ビューの<intbox id="arg2"/>コンポーネントと自動的に紐付けされる
private Label ans; //ビューの<label id="and"/>コンポーネントと自動的に紐付けされる
// addBtnボタンの onClickイベント・リスナー
public void onClick$addBtn(Event e) throws Exception{
ans.setValue(String.valueOf(arg1.getValue() + arg2.getValue()));
}
}

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<?variable-resolver class="org.zkoss.zkplus.seasar.DelegatingVariableResolver"?>
<window id="win" title="Employee" border="normal" width="300px" apply="MyControler">
<listbox id="empListbox" width="200px" rows="10" multiple="true" height="100%"
checkmark="true" model="@{controler.empData}" selectedItem="@{selected}">
<!--
controlerはMyControlerのdoAfterComposeメソッドでWindow変数に追加されている。
aWindow.setVariable("controler", this, true); //aWindowはdoAfterComposeの引数
empDataはcontrolerで定義されているList<Employee>型のプロパティ
-->
<listhead>
<listheader label="姓" />
<listheader label="名" />
</listhead>
<listitem self="@{each=employee}">
<listcell label="@{employee.lastName}"/>
<listcell label="@{employee.firstName}"/>
</listitem>
</listbox>
<vbox>
<hbox>姓: <label value="@{selected.lastName}"/></hbox>
<hbox>名:<label value="@{selected.firstName}"/></hbox>
<hbox>内線番号: <label value="@{selected.phoneExt}"/></hbox>
<hbox>入社日:<label value="@{selected.hireDate}"/></hbox>
</vbox>
</window>
public class MyControler extends GenericForwardComposer {
private List<Employee> empData;
private JdbcManager jdbcManager; //super.doAfterComposeのコール後Seasar変数と自動で紐付けされる
@Override
public void doAfterCompose(Component aWindow) throws Exception {
super.doAfterCompose(aWindow);
// 自分自身をwindowの変数に追加するとビューからアクセス可能なオブジェクトになる。
aWindow.setVariable("controler", this, true);
empData = jdbcManager.from(Employee.class).getResultList();
}
//zulのListboxのmodelプロパティには controler.empData を設定する
public List<Employee> getEmpData() {
return empData;
}
}
<window width="100%">
<zscript>
// コンポーネントのforEach属性を利用して生成するボタンの国名ラベルの配列
String[] countries = {"China", "France", "Germany", "United Kindom", "United States", "Japan"};
</zscript>
<hbox>
<button label="${each}" forEach="${countries}">
<!-- eachの値をcustom-attributesのcountryに保存する -->
<custom-attributes country="${each}"/>
<attribute name="onClick">
{
//countryにアクセスする。
alert(componentScope.get("country"));
}
</attribute>
</button>
</hbox>
</window>
<style>
div.cell-inner{
font-size:xx-small;
//font-size:xx-large;
}
</style>
<textbox style="text-transform:uppercase" id="idx" />