Web Applicaation」カテゴリーアーカイブ

HTML5 Dynamic Select

HTML5 で SeeMe(Opera serch.ini 編集アプリ) を作りたい。

Opera 使いは全員最新版を使うのでバージョンを気にする必要が無い。
ぶっちゃけ Opera にだけ対応させればいいので面倒が無い、素晴らしい。
まさに HTML5 で作るにはうってつけではないか!

というのは建前で…
Windows をまったく使っていないので Windows 版を作りたくないから。
HTML5 なら Linux で作ってツジツマを合わせればいいだけだもの。

後々で更新が面倒くさいからセクション丸ごと textarea に書き出すだけにでも…
それはどうでもよくて。

とりあえず ListBox みたいなのを作るには <select> タグでいいようだ。
コレを動的に作成して順番の入れ替えなんかの処理を入れればイケる。

Select in HTML 5
Dynamic Select in HTML with Ajax

何故か動的な JavaScript 編集コードはフランスで見つける。
日本の HTML5 解説サイトって何故かみんな似たようなのばかりでこういうのが見つからない、探し方が悪いのだろうけど英語で探したほうが早いのはたしか。
どうでもいいがドイツからコメントスパムが来るようになったぞ。

とにかく SeeMe に必要な新規作成、上下移動、削除のテストコード。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SeeMe for HTML5</title>

<style>
#id_name { float: left; }
#id_edit { float: left; }
</style>

<script>
function on_up(listbox) {
    var i = listbox.selectedIndex;
    if (i > 0) {
        var str = listbox.options[i].text;
        listbox.options[i].text = listbox.options[i-1].text;
        listbox.options[i-1].text = str;
        listbox.selectedIndex = listbox.selectedIndex - 1;
    }
}
function on_down(listbox) {
    var i = listbox.selectedIndex;
    var len = listbox.length;
    if (i < len-1) {
        var str = listbox.options[i].text;
        listbox.options[i].text = listbox.options[i+1].text;
        listbox.options[i+1].text = str;
        listbox.selectedIndex = listbox.selectedIndex + 1;
    }
}
function on_new(listbox) {
    var len = listbox.length;
    listbox[len] = new Option("new!");
    listbox.size = len + 1;
    listbox.selectedIndex = len;
}
function on_delete(listbox) {
    var i = listbox.selectedIndex;
    if (i == -1) return;
    listbox.options[i] = null;
    listbox.size = listbox.size - 1;
    var len = listbox.length;
    if (len == 0) {
        return;
    }
    else if (i == len) {
        listbox.selectedIndex = i-1;
    }
    else {
        listbox.selectedIndex = i;
    }
}
function on_select(form) {
    var i = form.listbox.selectedIndex;
    form.edit1.value = form.listbox.options[i].text;
    form.message1.value = form.listbox.options[i].text;
}
function init() {
    var listbox = document.getElementById("id_select");
    for (var i=0; i<10; i++) {
        listbox[i] = new Option("Item" + i);
    }
    listbox.size = 10;
}
</script>

</head>

<body onLoad="init()">


<form>
<div>
<input type="button" value="up" onclick="on_up(this.form.listbox)">
<input type="button" value="down" onclick="on_down(this.form.listbox)">
<input type="button" value="new item" onclick="on_new(this.form.listbox)">
<input type="button" value="delete item" onclick="on_delete(this.form.listbox)">
</div>
<div id="id_name">
<select id="id_select" name="listbox" onchange="on_select(this.form)"></select>
</div>
<div id="id_edit">
<input type="text" name="edit1" size=20><br />
<textarea name="message1" rows="6" cols="60px"></textarea>
</div>
</form>

</body>
</html>

問題なく移動な削除ができるようだ。
ということで早速こんな感じにしようと作っていた。
ユーザー名と OS さえ解れば ini のパスは解るからと思ったけど…

File オブジェクトはパスや URI の文字列からは作成できないんだね。
間に PHP あたりを噛ませてなんとかするしか無いかな…
挫折したらごめん、多分もう Windows 版は更新しない。

HTML5 Local File Drop and Input File

HTML5 は Local ファイルの編集もできる。
一番利用されるだろうと思われるのはやはりテキストファイルの編集。
ということで今回はファイルの読み込みを勉強する。
<imput> を利用するかドラッグアンドドロップで読み取る方法を。

これは興味がある人が多いようで検索するとワラワラ見つかるね。
でも手段が結構バラバラだったりするので一番最適と思われる方法を探す。
手段は File object を得て FileReader で読み込めばいいようだ。

残念ながら Opera 11.51 はドラッグアンドドロップ未対応だ…
HTML5 の仕様に含まれているのだから今後は対応してくれるだろう。
IE はどうでもいい。

とにかく Firefox, WebKit で上手くいったコード。
Opera も Input だけなら読み込みできる。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Drop and Input</title>

<script>
function writeText(f) {
    var reader = new FileReader();
    reader.readAsText(f, "utf-8");
    var text = document.getElementById("IDTEXT");
    reader.onload = function(e) {
        text.innerHTML = e.target.result;
    }
    reader.onerror = function(e) {
        switch (e.target.error.code) {
        case 1:
            text.innerHTML = "NOT_FOUND_ERROR!";
            break;
        case 2:
            text.innerHTML = "SECURITY_ERROR!";
            break;
        case 3:
            text.innerHTML = "ABORT_ERROR!";
            break;
        case 4:
            text.innerHTML = "NOT_READABLE_ERROR!";
            break;
        case 5:
            text.innerHTML = "ENCODING_ERROR!";
            break;
        default:
            text.innerHTML = "Unknown ERROR!";
        }
    }
}
function changeInputValue(e) {
    var f = e.target.files[0];
    writeText(f);
}
function init() {
    document.addEventListener("dragover", function(e) {
        e.preventDefault();
    }, false);
    document.addEventListener("drop", function(e) {
        e.preventDefault();
        var f = e.dataTransfer.files[0];
        writeText(f);
    }, false);
}
</script>

</head>

<body onLoad="init()">
<p>Drop here</p>

<form>
<input type="file" id="IDURI" onchange="changeInputValue(event);">
</form>

<p id="IDTEXT">URI</p>

</body>
</html>

コンストラクタ(という表現は正しいのだろうか?)
init でこう書けば event object が得られるようだ。
preventDefault メソッドを呼んでブラウザのデフォルト動作を無効にする。
dataTransfer.files メソッドで File object の List が得られる。
その List から添字を使って取り出す、複数ファイルなら for 文を使う。

input は onchange でこう書けば event object 付きで関数が呼べるようだ。
target.files メソッドで File object の List が同様に得られる。

肝心なファイルを読み込んで書き出す処理は少し面倒。
C の fopen や Python の open, read みたいにはいかないようだ。
FileReader の readAsText 関数で読み込んでコールバックで処理する。
読み込みが正常終了すると onload が呼ばれるので event object の target.result プロパティからテキストを得る。

どうでもいいけど Python ばかりやっているとこういう書き方が不自然で…
IronPython の時も思ったけどイコールでの代入時に括弧が無いと変に感じる。

ところで onerror の処理をやたら丁寧に書いていますが…
Original Webkit Browser @ Fedora 15 | PaePoi
で表示できなかったから原因を調べるためである。

WebKitWebSettings

# setting
setting = self.webview.get_settings()
setting.set_property("enable-file-access-from-file-uris", True)

を __init__() のどこかに入れれば表示できるようになります。
Local のファイルアクセスは WebKit デフォルト状態では弾かれるようです。
Chrome では読み込めるようなのにとコレだけで一日悩んでしまったぞと。

書き込みは FileWriter を使う、後日。
その前にリストボックス作成と JavaSclipt で ini ファイル読み書きをやりたい。
何を作ろうとしているかはわかる人には解る。
現実として作りたいアプリが無いとプログラミングの勉強は絶対に続かないよ。

HTML5 Keyboard and Mouse Event

HTML5 を勉強しているけど、多岐に渡りすぎてポイントが掴めない人が多いかも。
とにかく解ったことで普通に利用しそうなもの。

innerHTML 等でリロードせずとも動的にページ内容を変更可能
canvas で図形描写の動的変更が可能
css3 アニメーション等で見栄えのよい UI を構築できる
マウスイベントやキーボードイベントを利用できる
ローカルファイルの編集にも使える

つまり今までは実行ファイル形式で作っていたアプリケーションを Web ブラウザ上で動くアプリケーションにて実現できる技術ということなんだね。
JAVA や Flash 等の特定企業提供に頼らず標準仕様として確立させたわけだ。

ということで。
キーボードとマウスのイベントを捕まえて処理するコードを試す。

書くまでもなく IE はガン無視、Fedora Linux だもん私は。
少なくとも IE9 が使えない Windows XP のサポートが終了するまでは IE なんて意図的に無視したほうが賢明なくらいだ。
アクセスログを見ると IE6 がまだ沢山いて呆れるよ…

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Keyboard and Mouse Event</title>

<script>
function on_keypress(e) {
    var num = e.keyCode || e.charCode;
    var text = document.getElementById("IDTEXT");
    text.innerHTML += String.fromCharCode(num);
}
function on_mousemove(e) {
    var text = document.getElementById("IDMOVE");
    text.innerHTML = "x=" + e.clientX + " y=" + e.clientY;
}
function init() {
    document.addEventListener("keypress", on_keypress, false);
    document.addEventListener("mousemove", on_mousemove, false);
}
</script>

</head>

<body onLoad="init()">
<p id="IDMOVE">x= , y=</p>
<p id="IDTEXT">Press Keyboard Charactor.</br /></p>
</body>
</html>

addEventListener は document に指定すればフォーカスを気にする必要は無くなる。
逆にフォーカスがある時だけハンドリングしたい場合は getElementById で指定。

イベントハンドラ引数の e から詳細が得られる。
e.keyCode は Opera と WebKit のみ
e.charCode は Firefox と WebKit のみ
しかたがないからこうすることに。
mouse の e.offsetX は Opera と WebKit
e.clientX なら全部でまかなえた。

流石はアホみたく更新しまくっている WebKit が一番柔軟だ。
今後の更新でどうなるか解らないけど現時点なら上記でハンドリングできる。

ただキーボードはブラウザの割り当てというものが…
主にマウスやタッチパネルで扱うアプリが主流になるのだろう。
だからタブレットはやたら HTML5 を押しているのか、と今更な発見であった。

HTML5 Canvas API

HTML5 の勉強。
canvas というのを試してみた。

<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8>
<title>Canvas API</title>

<!-- StyleSeet -->
<style>
body {
    background-color:#c0c0c0;
}
#cvs {
    background-color:#ffffff;
    border:#00ffff 2px solid;
}
</style>

<script>
function draw(num) {
    /* GetDC */
    var ctx = document.getElementById("cvs").getContext("2d");
    /* Clear */
    //ctx.clearRect(0, 0, 400, 200);
    /* Save the Default Setting */
    var globalAlpha = ctx.globalAlpha;
    var fillStyle = ctx.fillStyle;
    /* Branch */
    switch(num) {
    case 0:
        break;
    case 1:
        /* Rectangle */
        var x = 200;
        var y = 20;
        ctx.globalAlpha = 0.3;
        for (var i=0; i<3; i++) {
            ctx.fillRect(x, y, 150, 100);
            x += 30;
            y += 5;
        }
        break;
    case 2:
        /* Circle */
        ctx.globalAlpha = 0.3;
        /* #1 Red */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(255, 0, 0)';
        ctx.arc(70, 45, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #2 Green */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 255, 0)';
        ctx.arc(45, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        /* #3 Blue */
        ctx.beginPath();
        ctx.fillStyle = 'rgb(0, 0, 255)';
        ctx.arc(95, 95, 35, 0, Math.PI*2, false);
        ctx.fill();
        break;
    case 3:
        /* Drop Shadow */
        var text = "homuhomu";
        ctx.font = "82px 'sans'";
        ctx.globalAlpha = 0.3;
        ctx.fillText(text, 5, 105);
        ctx.globalAlpha = 1.0;
        ctx.fillText(text, 0, 100);
        break;
    default:
        alert("Error!");
    }
    /* Write back */
    ctx.globalAlpha = globalAlpha;
    ctx.fillStyle = fillStyle;
}
</script>

</head>

<body onLoad="draw(0)">
<canvas id="cvs" width="400" height="200">canvas</canvas><br />
<input type="button" onclick="draw(1)" value="Rectangle">
<input type="button" onclick="draw(2)" value="Circle">
<input type="button" onclick="draw(3)" value="Drop Shadow">
</body>
</html>

なんだよコレ、デバイスコンテキストとほとんど変わらない。
いやオブジェクト化されているから GDI+ なのか、RGBA も利用できるし。

canvas のサンプルコードは検索で沢山見つかるけどグローバル設定を書き戻す処理を入れていない人が多すぎて唖然。
globalAlpha や fillStyle を変更したら元に戻さなければ後々まで引き継がれてしまうんですけど。
デバイスコンテキストではペンやブラシを使ったら元に戻すなんて Windows API をやった人なら常識だよね。
GDI とか全然知らない人ばかりなのだろうか。

てか WM_PAINT と InvalidateRect 関数のようなものはいらないのかな?
ちなみに GnomeShell や Aero では 3D になるからウインドウを重ねても消滅しない。
2D 状態を試すため VirtualBox 仮想マシンの Ubuntu で動かしてみる。

ウインドウを重ねても最小化しても描写が消えない、ココは GDI と少し違う。
どうやって描写状態を記憶しているかは解らないけどそういうこと。

てゆーかフォントのせいではみ出す、絶対値描写はコレが最大の欠点なんだよな…
私が WindowsForm や GtkFixed をバカにしているのは絶対値配置だからですし。
レイアウタ方式なら絶対にはみ出さない、HTML さえもレイアウタ方式だ。

上記コードは重ねるために FillRect していない。
この状態で Circle ボタンを複数回押してみる。

Alpha 値で薄くしても重ねてしまえば当然のように濃い色になる。
やはりボタンやイベントで描写する場合は clearRect 等で一度全体を塗りつぶす必要があるね。
上記コードの Clear 部コメントアウトを外せば一つづつ描写されるようになる。

つまり canvas 2d は GDI のようなものだと。
しかも JavaScript コードも GDI, GDI+ を勉強した人ならすぐ理解できる。
Windows SDK で何かを作れる人は色々試すと面白いかも。

html5 Test

いいかげんに HTML5 の勉強をやろうとこんなムックを買ってきた。

月刊誌である日経ソフトウエアでの記事をまとめたものらしい。
ココの月刊誌自体は未だに WindowsForm だとか寒い記事ばかりだがムックはあなどれない。
私が普通にアプリを作れるようになったキッカケも以下のムックのおかげだ。
Windows徹底理解 | PaePoi
ヘタにぶ厚い解説本を買うよりムックのほうが不要な解説が少ない所がいいね。

記事のコードも以下から落として利用できるから楽チン。
ダウンロード – 日経ソフトウエア ダウンロード:ITpro

とりあえずイントロダクションを試す。
コードのダウンロードは 2011/01 なのね、最後のページに書いていた。
もう LHA 配布は消した方が…とにかく tr1101.zip を落として展開。

meta charset=”utf-8″ を推しておいて readme.txt は Shift-JIS とかヤメてくれ!
Linux では普通に開くと文字化けするっつーの、UTF-8 に BOM を付けていないのは評価する。
画像は自分で用意しなきゃダメか、まどかばかりじゃアレだからあずにゃんを用意した。

Opera で試したけどアニメーションしないんだが…
ってよく見たらこの CSS の -webkit-transition って WebKit 専用じゃんかよ。
何故か mozilla のページで見つかった。

CSS transitions – MDN

Opera は -o- Firefox は -moz- のプリフィクスが必要、IE はまだ無い。
Linux てか Fedora 上で試すから IE が使えないのでどうでもいいけど。

とにかく style.css に以下の感じで適所に追記する。

-webkit-transition: 0.2s linear;
-o-transition: 0.2s linear;
-moz-transition: 0.2s linear;

WebKit のブラウザは入れていないけどライブラリはあるから PyGI で作る。
PyGtk で作るのとほぼ同じでイケた、Gtk.PolicyType に気おつけて。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import WebKit, Gtk, Gio

# Rewrite Your HTML5 File URI
HTML_URI = "file:///home/sasakima-nao/html5/tr1101/index.html"

class WebKitWindow(Gtk.Window):
    """
        WebKit PyGi Version
        from Fedora 15 x86_64
    """
    def __init__(self):
        # Window
        Gtk.Window.__init__(self)
        self.resize(800, 480)
        self.set_title("My WebKit Window")
        # WebKit
        w = WebKit.WebView()
        w.load_uri(HTML_URI)
        # ScrollWindow
        sw = Gtk.ScrolledWindow()
        sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
        # add
        sw.add(w)
        self.add(sw)
        self.show_all()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(
                self,
                application_id="apps.test.webkit",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
        self.connect("activate", self.on_activate)
        
    def on_activate(self, data=None):
        l = self.get_windows()
        if l:
            return
        w = WebKitWindow()
        w.set_application(self)
    
if __name__ == "__main__":
    app = App()
    app.run(sys.argv)

上記と Firefox 6.0 と Opera 11.51 で index.html を表示

よしよし、ドレでもアニメーションするようになった。
Linux でも全然イケるようです。