月別アーカイブ: 2014年3月

JavaScript Touch Events

iPhone に変更してからスマホゲームを始めた。
ひたすらポチポチするだけだとバカにしていたがコレが意外に面白い。

こんなのを Web アプリで作ってみたい、ということで。

とりあえず画面をポチると少しずつ一行文字列が流し込まれていく方法を。
エロゲでよく見かけるやつね、凄く古いのしか知らないけど。

ソレっぽいワードで検索すると基本みたいなのは日本語でゴロゴロ出る。
筆者メインの Python for GTK+ じゃ英語しか見つからないので逆に戸惑うよ。

JavaScriptプログラミング講座【タッチスクリーン操作について】

addEventListener で touchend のハンドラを処理すればよさそう。
それだけだとパソコンからは動かないので mouseup も同じハンドラで。
touchstart, mousedown ではないのはオンラインソフトでの経験から。

JavaScriptを解説します

文字列流し込みはこの上書きする手段がよさそう。
しかし clearInterval しなくてもいいのかな?
しかしみんな関数名が、GTK+ を主に使っていると凄く気になる。

結構簡単に作れたけど色々問題があった。
touchend, mouseup 両方を Android Chrome は拾ってしまう。
表示が終る前にポチるとハンドラが多重発生してしまう。
表示が終わるまで何らかの手段で排他制御を行うしかないな。

removeEventListener で一時ハンドラを外す方法が沢山見付かる。
でも筆者の実装手段が悪いのかうまくいかない。
最適ではないかもだけど下記がうまくいった方法。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- for Smart Phone -->
<meta name="viewport" content="
    width=device-width,
    initial-scale=1.0,
    minimum-scale=1.0,
    maximum-scale=1.0,
    user-scalable=no" />
<title>test</title>
<script type="text/javascript"><!--

    var count = 0;
    var lock = false;
    var lines = [
        "JavaScript で一文字ずつ表示する。",
        "日本語(Japanese)も一文字として扱ってくれるよ。",
        "end." ];

    // Text Out Function
    var writeLine = function(line) {
        lock = true;
        var i = 0;
        var id = null;
        var setText = function() {
            if (i <= line.length) {
                document.getElementById("text_area").innerHTML = line.substring(0, i);
                i++;
            } else {
                clearInterval(id);
                lock = false;
            }
        }
        id = setInterval(setText, 50);
    }
    // Event Handler
    var onTouchEnd = function() {
        if (lock == false) {
            if (count < lines.length) {
                writeLine(lines[count]);
                count++;
            }
        }
    }
    // Connect
    var init = function() {
        if (window.TouchEvent) {
            document.getElementById("event_check_area").innerHTML = "Support the Touch Events.";
            document.addEventListener("touchend",onTouchEnd);
        }
        document.addEventListener("mouseup",onTouchEnd);
    }
    //-->
</script>
</head>
<body onLoad="init()">
<p id="event_check_area">Don't Support the Touch Events.</p>
<p id="text_area"></p>
</body>
</html>

touch_event

iPhone, Android でもうまくいった、IE はしらない。
しかし Google Chrome は Linux デスクトップ版もタッチ対応なのか。
意味があるのかな?

あとはエレメントを特定 canvas にして美少女画像を別に表示すれば
くるぉおえるめぇぇるですおおお^q^
みたいなのが作れるかも、まだ先は長いけど。

Android and iPhone word-break

前回 table タグを使わない方向にすると書いたけど
iPhone で table タグ内の英文を強制改行させる方法をみつけた。

長い英単語を途中で折り返したいときの CSS の指定方法: Days on the Moon

手持ちで実験した結果こうなった。
word-break: break-all で iPhone 強制改行。
word-wrap: break-word で Android 強制改行。

body {
	-webkit-text-size-adjust: 100%;
	word-break: break-all; /* iPhone */
	word-wrap: break-word; /* Android */
}

しかしこんなのは使うなということらしい。
だがそれは英文での話、コマンドやソースコードは強制改行してほしい。

IMG_0053

すべては .NET Framework の長すぎるメソッド名が悪い。
Linux 屋なら端末で長いコマンドが折り返されることに慣れているしね。

更に viewport は

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0" />

これで iPhone でも拡大は可能で横向き時に文字拡大されなくなる。
-webkit-text-size-adjust: 100%; という上記の CSS 指定も必要だけど。

maximum-scale=1.0,user-scalable=no

とよく見つかる、これを指定すると拡大できなくなるので場合による。
スマホ重視なサイトなら拡大しなくても使い易いレイアウトにすればいい。

ついでに、これは以前から指定していたけど

img {
	max-width: 100%;
	height: auto;
}

としておくと縮小画像を用意しなくても自動で縮小表示される。
大半を縮小画像に入れ替えた後に知ってションボリした思い出。

とにかく iPhone 対応は一段落。
IE つか Windows で表示確認していないけど多分大丈夫だろう。

Safari CSS

先月スマホを iPhone 5S に乗り換えた。
Safari だと自分の本サイトが滅茶苦茶に表示されると気が付いた。

そろそろ CSS に手をつけないと。
このブログ側は問題ないのでこの CSS を参考に。

まず全体の英字フォントが selif になる。
table 部の折り返しができず縮小表示になる。
pre で文字列が折り返さずトンデモ状態に。
chrome や firefox で問題なかった margin 指定で酷い表示状態に。

特に SyntaxHighlighter は深刻だ。
何がどうなったらこんな酷いことになるんだよと。

IMG_0052

英字フォントは全体に font-family: sans-serif; 指定で普通にいける。
SyntaxHighlighter には適用されないので shCore.css に指定。
でも滅茶苦茶なフォントサイズなのは変わらない。

SyntaxHighlighter 2.1.364 を使い続けていたけど 3.0.83 に変更。
配布元にいったけどよくわからなかったのでバックアップを探して適用。
旧版では swf だしタッチパネルじゃ選択し辛いのでコレのほうがいいね。

ちょっぴり良くなったけどフォントズレは変わらない。
CSS を色々弄ってみたけどどうにもならない。

Blogger:SyntaxHighlighter(3)iOS Safariで行番号がずれる問題を解決

検索したら、筆者の設定が悪いのではなかったのか!
-webkit-text-size-adjust: 100%; を入れただけで普通になった。

おまけで shBrushJScript.js の内容を変更。
print, prototype, imports を色分けするように、そう Gjs 用。

shCore.css は overflow: auto !important; でスクロールに。
通常の pre は折り返すというように CSS を指定。

pre {
	border: 1px solid #7c93b2;
	font-family: monospace;
	white-space: pre-wrap;
	word-wrap: break-word;
}

margin は pt 指定していたけど px 指定に変更。
Retina ディスプレイなのが関係あるのかな。
他チマチマと CSS の微調節。

css – Word-wrap in an HTML table – Stack Overflow

これで iPhone でもテーブルからハミ出さなくなった。
と思ったらパソコンで見ると横幅一杯に広がってカッコワルイ。
これは元通りにして今後の課題ということにしておこう。
とはいえ、ぶっちゃけ table タグを使わない方向にするしかなさそう。

他に何をやったかな?覚えていないや。
とにかく iPhone Safari でもゲンナリしない程度にはできたぞと。

Internet Explorer のみ表示確認すればいい時代があったのだけどな。
新たに Web ページ作成を勉強し始める若い人は大変だ。

JavaScript tuple

Gjs では関数の戻り値を配列で2つ以上受け取ることができる。
Python 等の言語仕様に tuple がある言語では常識なのだが。
というか、JavaScript の配列って型が違っても問題ないのね。

Python

#!/usr/bin/env python3

def get_tuple():
    return "CBR", 1000, "RR"

name, cc, ext = get_tuple()
print("{}{}{}".format(name, cc, ext))

Gjs

#!/usr/bin/env gjs

let get_tuple = function() {
    return ["CBR", 1000, "RR"];
}

let [name, cc, ext] = get_tuple();
print(name + cc + ext)

これって Web ページにも使えるのかな?
実験、2014.03.15 現在の最新環境にて。

Google Chrome 33
iPhone 5S Safari
iPhone 5S Google Chrome
FireFox 27
Internet Explorer 11

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tuple Test</title>
<script type="application/javascript"><!--
var get_tuple = function() {
    var name = "iPhone";
    var num  = 6;
    return [true, name, num];
}
function init() {
    var arr = get_tuple();
    if (arr[0]) {
        document.write(arr[1] + arr[2]);
    }
}
//-->
</script>
</head>

<body onLoad="init()">
</body>
</html>

上記ブラウザ全部で関数の戻り値に配列を指定することができた。
しかし tuple のように戻り値を受け入れてくれるのは FireFox のみ。
Gjs は Firefox のエンジンを使っているので同様のようです。

しかし現在のトレンドは書くまでもなくスマートフォン。
Google Chrome, Safari で利用できないのでは使えない。
配列として受け入れるしか選べない。

JavaScript の Array は型が違ってもいいし関数の戻り値にできる。
それを利用すれば構造体を戻す関数やタプルのように扱える、ということで。
今後は解らないけど2つ以上の戻り値が必要な場合はこんな感じにすると便利。

ついでに let について。
FireFox で let 等の JavaScript 1.7 の機能を使うには 1.7 宣言が現時点では必須。
JavaScript 1.7 の新機能 – JavaScript | MDN

<script type="application/javascript;version=1.7"><!--
let get_tuple = function() {
    return ["FireFox", "JavaScript", 1.7];
}
function init() {
    let [name, js, version] = get_tuple();
    document.write(name + js + version)
}
//-->
</script>

Internet Explorer 11 はなんと let 等もそのまま利用可能。
ただしコチラは version=1.7 を書くと動作しない。

<script type="application/javascript"><!--
let get_tuple = function() {
    return ["Internet", "Explorer", 11];
}
function init() {
    let arr = get_tuple();
    document.write(arr.join(" "));
}
//-->
</script>

統一されるまで使い物にならないや。

Gjs I/O Stream

以前下記で Seed, Python で Gio による読み書きをやったのを Gjs にしてみた。
Gio Streaming I/O @ Seed and PyGI | PaePoi

GCancellable 等を指定(null でいい)しないといけなかった。
他色々と Seed より Python に似ていて困惑。

/*
    Gjs Streaming I/O File Read and Write Sample
*/

const Gio = imports.gi.Gio;
const Format = imports.format;

String.prototype.format = Format.format;

let filename = "test_gjs.txt";
const lines = "Japan\n\n日本語";

// Write
let f = Gio.file_new_for_path(filename);
let fstream = f.replace(null, false, Gio.FileCreateFlags.NONE, null);
try {
    // Error, This is no Exception.
    // let dstream = new Gio.DataOutputStream(fstream);
    // g_output_stream_write: assertion 'G_IS_OUTPUT_STREAM (stream)' failed
    let dstream = new Gio.DataOutputStream({base_stream:fstream});
    dstream.put_string(lines, null);
} catch (e) {
    // Without meaning
    log("*** ERROR WRITE: " + e.message);
}
fstream.close(null);

// Read
f = Gio.file_new_for_path(filename);
fstream = f.read(null);
// Same as above
let dstream = new Gio.DataInputStream({base_stream:fstream});
while (1) {
    let [text, len] = dstream.read_line_utf8(null);
    if (text == null) break;
    print("%s(%d)".format(text, len));
    // or print(text + "(" + len + ")");
}
fstream.close(null);

/* output
Japan(5)
(0)
日本語(9)
*/

DataOutputStream 等の引数は json で指定しないと認識してくれない。
現時点では理由が解らない、GOutputStream のサブクラスと認識できないのか?
とにかく Error で困ったら json 指定にすればなんとかなるっぽい。

しかも GError 引数なのに例外にならず普通にエラー。
try ブロックを書いたけど無意味だった、これはちと困る。

おまけで let 変数のスコープは try ブロック内でも有効だと解った。
Python と同様にするには var を利用、注意しよう。

// var is OK
let f = Gio.file_new_for_path("a.txt");
try {
    // var fstream = f.replace(null, false, Gio.FileCreateFlags.NONE, null);
    let fstream = f.replace(null, false, Gio.FileCreateFlags.NONE, null);
} catch (e) {
    //
}
fstream.close(null); // ReferenceError
# Python is OK
f = Gio.file_new_for_path(filename)
try:
    fstream = f.replace("", False, Gio.FileCreateFlags.NONE, None)
except Exception as e:
    pass
fstream.close(None)

Seed にある c_new という意味不明な指定が無いのはちょっぴり嬉しいね。
それ以外は全部 Gjs のほうが面倒臭いけど。

戻り値が Python 同様に 2 つ以上である場合がある。
Python はタプルなんだけど、タプルが無い言語でもこの手があったか。
まあどちらも引数に渡された変数の値を変更できない言語だし。

どうも PyGObject の手段を参考に作っているような気がする。
いや逆かも、というか GLib 側の意向でこうなったのかな?

とにかく Python 屋なら Seed より Gjs のほうがなじみやすいという結論で。