Home > 技術

技術 Archive

space - HTML5 & CSS3 DEMO

space.jpg

画像やFlashはいっさい使わずに何か中心に向かってアニメーションするものを作りたいと思って制作してみました。
今回もjsDeferrd.jsを使用。

cho45's jsdeferred at master - GitHub

中心に向かって行くということで、何かが中心にないと面白くありません。
なので、疑似的な太陽をCSS3で作り、そこにHTML5のcanvasが向かって行くという感じになりました。

サンプルコード - CSS3

実はまだこのgradientというCSSプロパティが良くわかっていなくて、Firefoxで出来るけど、Safariでどうやるのかな〜という部分を検証中です。
-moz-radial-gradientというプロパティを使って太陽を描いているんですが、これをWebkitでどう指定するのかが分からない!

なので、mozとwebkitでは別々の背景にしています。

またbodyタグに-moz-radial-gradientを指定するとなぜかうまく円が描かれなかったです。
divを画面のheight、widthに広げてそこにスタイルを当てるようにして回避しました。

あとHTML5のvideoタグも使って音楽を出しています。
使っている曲は、HoldenのA Break in The Clouds - Main Mixです。(怒られたら使用するのやめますw)
宇宙っぽさが演出できる名曲です。


Firefoxで見ていただくのが一番いいです。
Chrome、Safariの場合は円ではなくグラデーションになってます。
以下からどうぞ。
space - HTML5 & CSS3 DEMO

プログラムコード

gist: 331165 - GitHub

squareDeferred

squareDeferred.jpg

なんとなく思い立って、jsDeferred.jsでアニメーションのループがしてみたいってなったので作ってみた。
この手のアニメーションを考えるときは、どちらかというと間違ったコードが面白さを生み出す。
つまり、不意に間違って2回ループしたら面白いや、ストーリーの組み直しなどで型にハマらない動きができたりする。

ここ最近は拙作のaddCommand - jQuery Pluginでアニメーションを書いていたんですが、jsDeferredも便利ですね〜。

処理の割り込みや、setTimeoutで待たせるときに使ったりしてましたが、アニメーションでも十分に使いやすい。

cho45's jsdeferred at master - GitHub

サンプルコード - jsDeferred.js

ストーリーのループは以下のようにfunctionのcalleeを最後のnextで呼ぶようにしてあげてます。
これで疑似無限ループの完成。


あとjQuery1.4以降の機能でeasingをCSSプロパティ毎に指定できるので、それで少し気持ち悪い動きをくわえてみたりしてます。

Firefoxでも頑張って動いてくれますが、ChromeかSafariのほうが軽快に動作します。
以下からどうぞ。
squareDeferred

プログラムコード

gist: 331150 - GitHub

flickrダラ見サイト - flickrer作ってみた

Flickrer-1.jpg

自分がflickrをダラ見することが多いので、それっぽい感じのサイトを自分用に作ってみた。
特に難しいことはしてなくて、

  • $.jOpening
  • $.flickr
  • $.fn.jCurtain

という3つのプラグインを作って制作してます。
あと、miyagawaさんのmiyagawa's jquery-fitimage at master - GitHubを使って拡大画像の調整をしています。

実は単にカーテンのようなスライドを作ってみたくて、何か面白いことできないかな〜と思っていたらflickrでやったらいいかもと思って試しに作ったのがこのサイトになります。
初めのオープニング部分では、左右からラインが伸びてくるのですが、この当たりはFlashを意識して作っています。

今後もうちょい機能増やして、ダラ見しやすくする予定。
autoでスライドしていくとか。

対応ブラウザは以下(試したのが以下w)

  • IE7
  • Safari4
  • Firefox3.6
  • Chrome5


もしよかったら使ってみてくださいな。
flickrer - flickrダラ見サイト

追記:

@hisasann マウスオーバーで画像を読むまでに間が空くのがもったいないので裏で呼んでおいたほうがいいんじゃないかと。


via: Twitter / edvakf

との意見をいただいたので、拡大画像部分の画像を先読みするように修正しました。

Macに複数MySQLをインストールする方法

MacPortsでインストールする方法MacPortsでMySQLをインストール -- BONNOH FRACTION 13や、pkgでインストールする方法素晴らしき哉、人生!: Mac OS 10.5にMySQLインストールを見てみたんですが、どうもこれらの方法では複数のMySQLを同居させるのがむずかしそうだったので、ソースからコンパイルして入れてみた。

そしてうまく複数のMySQLが動いたので、そのときのメモメモ。。。

ソースをダウンロードする

以下のリンクからtar.gzをダウンロードします。

今回僕はmysql-5.0.33をインストールしましたので、適宜自分のバージョンに置き換えて読んでいただけたらと思います。

MySQL :: Download MySQL Community Server

そして適当なディレクトリに解凍する。

tar zxvf mysql-5.0.33.tar.gz

Macだと基本的にmysql-5.0.33.tar.gzをダブルクリックすれば解凍ソフトが起動するので、ターミナルでなくてもOKだと思います。

今回は/usr/local/srcディレクトリに解凍しました。

そしてディレクトリに潜る。

cd mysql-5.0.33

コンパイルする

まずはconfigureを実行します。
このときのコンパイルオプションは結構重要で、とりあえず以下の感じに落ち着きました。

--with-mysqld-user=hogeのところは、Macにユーザ権限でmysqlをソースから(あと、DBD::mysqlも) - Born Neetを参考にして、今ログインしているユーザーを記述してみました。

--prefix=/usr/local/mysql3306は複数のMySQLを/usr/local/に同居させるので、mysqlの後に僕はport番号をサフィックスとして付与しています。

./configure --with-charset=utf8 --with-mysqld-user=hoge --with-unix-socket-path=/usr/local/mysql3306/var/mysql.sock --prefix=/usr/local/mysql3306 --with-blackhole-storage-engine --with-federated-storage-engine

configureがうまくいけば、あとはmakeで終わり。

make
make install

データベースを初期化する

/usr/local/mysql3306/bin/mysql_install_db --user=hoge

もしここで「unknown option '--skip-federated'」のようなエラーが出てしまう場合は、

以下のファイルの

/etc/my.cnf

この部分をコメントアウトしてください。

#skip-federated

[via]
mysql 5.1のmysql_install_dbがこける - うまい棒blog

初期化が終わるとデータディレクトリのvarが作成されます。

/usr/local/mysql3306/var/

そして今回の重要なポイントですが、MySQLを別ポートで複数起動するので、このmy.cnfが1つだとうまくいきません。
my.cnfにportを指定する箇所があるので、別々のMySQLは別々のmy.cnfを見に行って欲しいわけです。

なので、今回は

cp /etc/my.cnf /usr/local/mysql3306/var

を実行してmy.cnfをデータディレクトリにコピーしました。
これで順番的に自分自身のmy.cnfを見に行くようになります。
また、mysql.sockというMySQLが起動したときに作成されるファイルも別々にしたいので、これもデータディレクトリに作ってねっ!と記述しています。
一般的には/tmp/mysql.sockに作成されるようです。

[client]
default-character-set=utf8
#password = your_password
port = 3306
socket = /usr/local/mysql3306/var/mysql.sock

# Here follows entries for some specific programs

# The MySQL server
[mysqld]
default-character-set = utf8
skip-character-set-client-handshake
character-set-server = utf8
collation-server = utf8_general_ci
init-connect = SET NAMES utf8
port = 3306
socket = /usr/local/mysql3306/var/mysql.sock
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M

MySQLを起動する

起動コマンドは以下のとおり。

cd /usr/local/mysql3306/bin
./mysqld_safe &

これでバックグラウンドでMySQLが起動します。

ちょっと教えてもらった操作をメモ。
もし以下のように&を付けずに起動した場合、

./mysqld_safe

Ctrl + zで一旦プロセスを落として、

bg

と叩くと

./mysqld_safe &

をしたときと同じ動作になるみたい。

最後に、プロセスが立ち上がっているかを以下で確認する。

ps ax | grep mysql

MySQLを停止する

以下で止まる。

./mysqladmin shutdown --socket=/usr/local/mysql3306/var/mysql.sock

まとめ

これで、もうひとつmysqlを作りたい場合は、「コンパイルする」の部分から--prefixを変えて実行すればよい。

結構手順としては面倒だが、プロジェクトが複数のMySQLを必要としている場合に、この手順が参考になれば幸いです。

■関連リンク
MySQL :: MySQL 5.1 リファレンスマニュアル :: 2.5 Mac OS X に MySQL をインストールする
「Can't connect to local MySQL server through socket」エラーについて
MySQL :: MySQL 4.1 リファレンスマニュアル :: 4.8.3 mysqld_multi(複数の MySQL サーバを管理するプログラム)
MySQL / Mac OS X
Macにユーザ権限でmysqlをソースから(あと、DBD::mysqlも) - Born Neet
MySQL :: MySQL 4.1 リファレンスマニュアル :: 2.4.1 mysql_install_db の実行に関する問題
1台のサーバに複数のMySQLをインストールしてみた。 | RwJ
MySQL :: MySQL 5.1 リファレンスマニュアル :: 2.9.2 典型的な configure オプション
MySQL :: MySQL 4.1 リファレンスマニュアル :: A.4.5 MySQL ソケットファイル /tmp/mysql.sock の保護または変更方法

MacにImageMagickをインストールする方法

いろいろググッた結果、MacPortsからインストールするのが速そう。
ということでまずはMacPortsのインストールから解説します。

すでに入っているかたは、読み飛ばしてください。

MacPortsをインストールする

まずは、Xcode ToolsをMacに付属しているインストールディスクからインストールします。
終わったら、http://svn.macosforge.org/repository/macports/downloads/からバージョンを選んでダウンロードする。

僕のローカルにはすでに、MacPorts-1.7.1が入っていたので、このバージョンでも問題ないと思います。

次に環境変数にパスを追加しときます。

cd
vim .bash_profile

export PATH=/opt/local/bin:/opt/local/sbin/:$PATH
export MANPATH=/opt/local/man:$MANPATH

一応リフレッシュしとく。

source .bash_profile


あとはMacPortsをアップデートしておわり。

$ sudo port -d selfupdate
$ sudo port -d sync


[via]
MacPortsでステキなUNIXツールをインストール - はこべにっき#

ImageMagickをインストールする

ここまで来るとあとは楽チンで、

$ sudo port install ImageMagick

これで終わり!
いろんなものを一緒にインストールするので、だいたい30分くらいはかかるかも。

すでに、MacPortsでインストールされているものを確認するなら、

$ port installed

と叩けば、ゾロゾロと表示されます。

[via]
[を] Mac に ImageMagick を入れた

■関連リンク
新しいMacbook Proにインストールしたものメモ
MacPortsのコマンド逆引き一覧 -- ディノオープンラボラトリ

JavaScript変態複雑化文法最速マスター

Java変態文法最速マスター - プログラマーの脳みそをリスペクト。
JavaScript変態文法最速マスター - 葉っぱ日記をリスペクト。

特に技法的なことではないんですが、functionをいろんなところで絡めてわかりにくくするポイントをいくつか紹介。

if文にfunctionを絡めてみる

単純なifなはずなのに、条件式に即時実行のfunctionを絡めることによってよりわかりにくくできます。
さらにクロージャをreturnして()で実行し、より複雑にする技法もとりいれてます。

for文にfunctionを絡めてみる

そもそもfor文の回りにfunctionを絡めてわかりにくくし、for文の条件式にもfunctionを絡めます。
さらにクロージャをreturnして()で実行し、より複雑にする技法もとりいれてます。

「ちなみにここでやっていることは引数の[1, 2, 3]という配列を受け取って、新しい配列にコピーしてreturnしているだけです。」

出力結果


[1, 2, 3]

Objectに上記やり方を絡めてみる

aというプロパティはただaを返せば終わりなはずなのに、わざわざfunctionでネストしてわかりにくくしています。
bというプロパティは上記if文複雑化for文複雑化を応用して、解読が困難な状態を実現しています。

出力結果


[1, 2, 3]

複雑化で気を付ける点

iをインクリメントする部分の複雑化で

という部分がありますが、ここで

このように引数で渡してはいけません。
外側のスコープにいるiではなく、このfunctionの関数スコープ内のiをインクリメントすることになるので無限ループになります。

これ以外にもcurry化をうまく使いまくって、複雑にすることができますが、だいたい上記のことが応用できれば特に問題はありません。

※注意 function絡めは節度と必要度合いを見て実装しましょうね!

エラトステネスの篩 - JavaScript版

エラトステネスの篩 - Wikipedia

こんな感じなのかな。。

サンプルコード

出力結果

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

勉強になりました!

JavaScriptライブラリを使っていてIEで余計なリクエストが発生してしまうケース

ここ最近フロントエンドのパフォーマンスチェックでHttpWatchを使っているんですが、これはかなり調子がいい!
特にインストールするとIEとFirefoxに追加され、Firebugのように画面の下のほうに表示されるので違和感なく使えます。

んで、このソフトを使ってサイトのパフォーマンスチェックをしていたら、IEの場合だけ

ERROR_INTERNET_INVALID_URL

httpwatch1.jpg

というRequestの結果が返ってきて、これってなんだろうと調べてみたら、jQueryprototype.jsYUIを使っている場合に
IEでDomContentLoaded(DCL)判定するときに発生しているようです。

これでだいたい3〜6ミリ秒のオーバヘッドがあるよう。
ほんのちょびっとですがねw

jQueryの場合(ver1.2.1)

bindReady関数の中にIEだったらという分岐があり、その中でsrc=//:なscriptタグをdocument.writeしているのが原因。

このscriptがdocument.writeされたタイミングでsrc属性のURLをGETする際に、よくわからんURLじゃ〜と言っているんでしょうね。
jQueryがこの判定方法を使っているのはおそらく1.2.1以前だと思うので、1.2.6や1.3.X、または1.4を使っている場合は問題ありません。

ちなみに1.4のDCLの判定は以下のようになっています。

onreadystatechangeとonload、あとは今までにもあったdoScrollで判定しているようです。

prototype.jsの場合(1.6)

このprototype.jsを使っている場合が、今回のERROR_INTERNET_INVALID_URLなRequestを送信してしまうパターンになります。
実際のコードは以下のとおり。

deferで遅延評価させて、readyStateがcompleteになったらfireしています。
この方法個人的に面白くて好きなんですが、無駄なRequestが発生してしまうのが難点ですね。

■関連記事
Prototypejsのdom:loadedを検証(IEの場合)

YUIの場合

ERROR_INTERNET_INVALID_URL & HttpWatch - HttpWatch BlogにはYUIでも起こると書かれていましたが、YUI2・YUI3の両方でscriptをdeferさせる方法はなかったので大丈夫でしょう。
もっと古い時代に書かれていたと思われます。

以下YUI3のDomContentLoaded判定。

ほとんどjQueryと同じです。

まとめ

今回のERROR_INTERNET_INVALID_URLが発生してしまう可能性があるのは以下、

  • jQueryは1.2.1以前を使っている場合
  • prototype.js1.6以前を使っている場合
  • YUI2よりも前のものを使っている場合

の3点かな。
他のライブラリも含めたらもっとあるでしょうが、とりあえず調べたのはこんだけ。
Firefoxとかだとこの現象は発生しないので、なかなか発見しずらいものではありますが、たまたま発見したのでログとして残しました。

HttpWatch以外に僕が使っているパフォーマンスチェックツールは、

YSlow :: Add-ons for Firefox

page-speed - Project Hosting on Google Code

あと、

Diagnose and Prevent AJAX Performance Issues - dynaTrace AJAX Edition

これIEだけなんですが、CLASS指定の個数とかID指定の個数とかわかるので、どこで遅くなっているかがわかりやすいです。

ではでは。

■関連リンク
ERROR_INTERNET_INVALID_URL & HttpWatch - HttpWatch Blog

JavaScript遅延ロード - jLazyLoader

Gmailチームが明かすHTMLアプリケーション起動の高速化テクニック - TechTalkManiacsを読んでて、こんな方法があるのか〜と関心した。
scriptタグの中をコメントアウトにしているので、初めのJavaScriptが解析されるときは無視されて、あとでevalさせるという面白い方法。

ソースコード

ダウンロード

gist: 270994 - GitHub


コメントアウトにしちゃっているので可読性は低いですが、このテクニックはいつか使って速度の検証をしてみたいところ。

■関連リンク
Google Code Blog: Gmail for Mobile HTML5 Series: Reducing Startup Latency

eclipseの起動画面を変えて楽しむ方法

eclipseたんスプラッシュ画像 - 虎塚を見て、普段使うeclipseの起動画面で遊びたいという欲求が生まれた。

だいたい15秒から30秒くらいしか表示されないeclipseの起動画面ですが、何か自分オリジナルで面白い画像にすると幸せになるかもしれませんね。

以下オリジナルな起動画面いろいろ。

eclipse3.2

splash3.2.jpg

eclipse3.4 - GANYMEDE

eclipse3.5 - GALILEO

splash3.5.jpg


そして、虎塚さんが作った画像が以下。

eclipseたん

splashtan.jpg

eclipseの起動画面を変更する方法

「eclipse/plugins/org.eclipse.platform_X.X.XXX」というディレクトリの中に、splash.bmpファイルがあるので、これを自分の好きな、或いはアレンジした画像に置き換えてあげるだけ。
これで次回の起動のときに表示されます。

かなり簡単ですね。
さぁて、画像作ろう。。。

■関連リンク
世話焼き系IDE:eclipseたん - 虎塚
Eclipse起動時に表示される画像を変更する

Googleのロゴがニュートンになってた。そしてリンゴが落ちてきた

tree.jpg

普段Googleトップをあんまり活用していないのでわからなかったですが、わっきーさんに教えてもらいました。

んで、コード見てたらロゴのimgタグのonloadにリンゴを落とすJavaScriptが書かれててちょっと面白かった。
imgのonload使うときって、あとから読み込んだ画像のwidth・heightを取得するときに使ったりするんですが、こうゆうトリッキーな使い方は面白いですね。

ざっくりですが、コードを抜き出してみたのが以下。

サンプルコード

1個分からないのが、アニメーションのclearIntervalgoogle.reinにpushしているんですが、
これをいったいどこで実行しているんだろう。。。

Googleトップのコードを一通りおってみたんですが、実行してそうな箇所がない。
1つだけあやしい箇所があったんですが、9zPpGAOKyhU.jsの中の以下の部分。(だいぶ端折ってます)

iにはpushという文字が入っているだけで、pushされた分をループしているわけではない。。。

仕方ないので、以下のグリモンでテスト。
タイミングがもしかしたら微妙かもしれないが、リンゴが落ちたあとにclearIntervalされるはずだからonloadでもOKでしょう!

google.rein実行された?グリモン

じっ、実行されない。。。

Firebugのprofileで調査

リンゴが落ちたあとにprofileを開始して、適当なタイミングで止めてみたのが以下の画像。

Google.jpg

undefine()」の部分が、該当のアニメーション処理。
中身を見ると、

とアニメーションのクロージャが入っているので、間違いないでしょう!
profileEndのタイミングをずらせばもっと回数の部分が増えていきます。

結局、よくわからなかったんですが、実行してないでしょ?w
いや〜分からんな〜〜〜。

グーグルのロゴデザインやってる人に
乱歩のやつは最高だったと伝えておいてください

喜ぶと思います。彼はdoodle 作るのにたくさんの資料や本を読んだり、頭があつあつになるくらい考えてますから。
でも手塚治虫先生の時や藤子先生の時など漫画がたくさんおいてあるので遊んでるみたいです。


via: グーグルで働いてるけど何か質問ある? - ブラブラブラウジング

[via]
グーグルで働いてるけど何か質問ある? - ブラブラブラウジング

XCodeでWebkitをデバッグする方法

JavaScriptのDomメソッドがどうやって動いているのか、普段あんまり意識しないですが、気になりだすと調べたくなるものです。

WebkitはSafariやGoogle Chromeに採用されているレンダリングエンジンで、高速でありアニメーションも非常になめらかです。

そんなWebkitをいつでも追えるように、デバッグ環境を作っておくと便利かも?と手順をメモしておきます。
「JavaScripterの参考になればうれしいです。」

XCodeのインストール

XCodeのインストールは、インストールディスクの中にあるOptional Installsフォルダに入っていますので、そちらからインストール可能です。
もしインストールディスクがない場合は、Apple Developer Connection - Mac Dev Centerよりダウンロードが可能です。
ただし、AppleDeveloperConnectionへのログインが必要になります。

[via]
The WebKit Open Source Project - Installing Developer Tools

Webkitのソースコードをダウンロードする

ターミナルを起動して、まずはダウンロード先のフォルダを作成します。

cd ~
mkdir webkit
cd webkit

次に以下を入力するとSVNからダウンロードが開始されます。

svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit

僕は30分以上かかったので、ランチに行くときに実行しておくとよいかもしれません。
また1度目はターミナルが途中で落ちてしまったので、あまり他の作業は行わずソースのダウンロードに専念させてあげたほうがよいかもしれません。

ソースコードのダウンロードが終わりましたら、以下を実行してください。
どうやらこれをしないとビルドがうまくいかないようです。

WebKit/WebKitTools/Scripts/update-webkit

[via]
The WebKit Open Source Project - Getting the Code

Webkitをビルドする

さっそくビルドを開始します。
以下を実行すると、ターミナルが膨大に流れ始めます。

WebKit/WebKitTools/Scripts/set-webkit-configuration --debug
WebKit/WebKitTools/Scripts/build-webkit --debug

ビルドもだいたい30分くらいかかるので、夕飯を食べにいきましょう!

成功すると以下のようにコンソールに表示されます。

Touch /Users/hoge/_/code/webkit/WebKit/WebKitBuild/Debug/WebKit.framework
cd /Users/hoge/_/code/webkit/WebKit/WebKit
/usr/bin/touch -c /Users/hoge/_/code/webkit/WebKit/WebKitBuild/Debug/WebKit.framework
** BUILD SUCCEEDED **

===========================================================
WebKit is now built (32m:39s).
To run Safari with this newly-built code, use the
"WebKit/WebKitTools/Scripts/run-safari" script.
===========================================================

[via]
The WebKit Open Source Project - Building WebKit

Webkitを起動する

WebKit/WebKitTools/Scripts/run-safari --debug

これで今回ビルドした内容でSafariが起動すると思います。
これでテストは完了です。

XCodeを使ってWebkitをデバッグしてみる

ではでは、いよいよWebkitをデバッグしてみます。
今回はdocument.getElementByIdをデバッグしてみようと思いますので、WebCoreあたりを除いてみます。

まずはダウンロードしたWebkitのWebCoreディレクトリをFinderで表示します。
僕の場合は以下のようなパスにダウンロードしました。

/Users/hoge/_/code/webkit/WebKit/WebCore

ここにXCodeのプロジェクトファイル「WebCore.xcodeproj」があると思いますので、実行してみましょう。
起動するとWebCoreプロジェクトが左のペインに表示されます。

ここのWebCoreの部分で右クリックして、「情報を見る」を選択します。

Document.cpp -- WebCore-1.jpg

するとWebCoreの情報が表示されるので、

のように、「カスタムの保存場所」を指定します。
これは実際にビルドされた内容が存在するパスを指定していることになります。

次にアタッチ先となる実行可能ファイルを作成します。

グループとファイル」ペインの真ん中あたりに「実行可能ファイル」という項目があるので、ここを右クリックし「追加」→「新規カスタム実行可能ファイル」を選択します。
以下のようにSafari.appまでのパスを設定します。

これによりデバッグ時にSafariを使う設定が完了しました。

Webkitにアタッチさせる

いよいよデバッグです。
XCodeのメニューにある「実行」から「進行(デバッグ)」を選択し、デバッグモードで起動します。

この作業は少し時間がかかるので、Safariが起動するまで気長に待ちましょう!
ここでどんな作業が行われているかをコンソールから確認することができます。
以下のボタンをクリックしてコンソールを立ち上げてみましょう。

Document.cpp -- WebCore-2.jpg

このように何かしらの作業が進行していると思います。

WebCore -- デバッガコンソール.jpg

Safariが起動したら、ブレークポイントを貼ってみましょう。(ここが今回の穴場です!)

document.getElementByIdにブレークポイントを貼る

左側のペインのWebCoreのdomの下にDocument.cppというファイルがあるので、これをクリック。
すると右側のペインにソースコードが表示されるので、「Cmd + F」でgetElementByIdを検索してみます。
(シンボルを選択するプルダウンからもメソッドを表示することができますが、今回は検索機能を使ってみます。)

すると以下のようなコードにたどり着くと思います。

そうです。これがdocument.getElementByIdの実体です。
普段使いに使いまくってるメソッドを見れるのはうれしいですね〜。

では簡単なHTMLファイルを作ってデバッグしてみましょう!

デバッグを貼るポイントはとりあえず、以下のifのところにしてみましょう。

すると以下のようにブルーのしおりのようなものが表示されるので、これがブレークポイントになります。

Document.cpp -- WebCore-3.jpg

これで先ほどのHTMLファイルをSafariで開いてみますが、まだアラートは表示されません。
document.getElementByIdにブレークポイントを貼っているので、アラートが表示される前にデバッガがWebkitの実行を待ち状態にしています。

デバッガを使ってみる

ここで便利なのがデバッガです。
デバッガは以下のようにボタンになっているのでクリックすれば起動されます

Document.cpp -- WebCore-4.jpg

HTMLファイルを開くとブレークポイントのところでストップします。
あとはステップオーバーしたり、ステップインしたりして遊んでみてください。

変数の監視でelementIdを見ることは出来るのですが、UChar *を16進で表示しているので本当にgetElementByIdで渡した文字列が入っているのかが確認できません。
バイナリから判断することはできるのですが、デバッガウィンドウに直接文字列が表示してほしいところです。
値を他の形式で表示してもうまくいかないので、ここは後で調査します。

Windowsでのデバッグについて

今回はMacのXCodeを使ってWebkitをデバッグしてみましたが、もちろんWindowsのほうでもデバッグは可能です。
手順は以下のリンクに詳細が載っていますが、Mac版とくらべてややこしそうです。

VisualStudioをインストールして、さらにパッチなども当てなくてはいけないので、サクッと試したい場合はMac版のほうが簡単そうです。

WebKitビルドガイド(ドザー用) - 最速チュパカブラ研究会

まとめ

document.getElementByIdを追ってみましたが、何度か実行しているとあることに気がついてきます。
elementIdより該当のidを持つエレメントを探しにいくんですが、m_elementsById.get()を実行してすでにモジュール変数にエレメントがある場合は検索処理をスキップします。
つまりサイトを開いて、Cmd + Rを押すとすでにm_elementsByIdにエレメントが入っているので、高速に動くみたいですね。
こうゆう情報は実際に追ってみないとなかなか分からないものです。

ソースコードも膨大ですが、XCodeでのビルドも結構時間がかかりますが、今後面白い内容が発見できたらブログにアップしていこうと思います。

■参考リンク
[Tips] Xcodeでプログラム実行と同時にコンソールウィンドウを表示させる方法 - Ni chicha, ni limona -平均から抜けられない僕-
Mac OSX Build and Run! Xcodeの入手方法

TumblrからランダムにURLを取得してTwitterにPostするbotを作ってみた

自分のTumblrからランダムに1時間毎にTwitterにPostするbotを作ったので、そのやりかたのメモメモ。

Tumblrから取得してTwitterにPostする手順

Tumblrから取得するのは普通にAPIを見ながらやってみた。
API | Tumblr

ここで困ったのが、http://hoge.tumblr.com/randomという感じでURLの最後にrandomというのを付けるとランダム記事に飛べるという機能があるんですが、
これ相当のAPIがなかったこと。

なので1度、TumblrAPIからtotal数を取得して、その値からランダム値を生成してランダムな記事のURLを再度TumblrAPIから取得しています。

Tumblrから1つの記事を取得するには以下のようなURLを指定すればよい。
typeでphotoを指定して写真を取りにいってます。

http://hoge.tumblr.com/api/read?start=0&num=1&type=photo

最近さくらインターネットを借りたので、せっかくなのでRubyで書いてみた。

ちなみにTwitterにPostするときは、定番そうなtwitter (0.7.0)を使っています。

RandomTumble - ソースコード

■ダウンロード
gist: 245238 - GitHub

使い方

RandomTumbleをnewするときにTumblrのidを渡して、random_post_twitterにTwitterのidとpasswordを渡します。

これでTumblrからランダムに1件抽出して、TwitterにPostされます。
ねっ!、簡単でしょ?

cronを設定する

さくらのコントロールパネルで、以下を設定する。

・実行コマンド

試行錯誤の結果このようになりました。

cd /home/User/code/ruby/; /usr/User/bin/ruby /home/User/code/ruby/twitter_bot.rb

[via]
Orvalで行こう!: さくらインターネット cron設定でRubyを動かす

・環境変数の設定

RUBYLIB - /home/User/lib
GEM_HOME - /home/User/lib/ruby/gem

これしとかないとrubygemsがありませんとエラーになってしまうので、忘れないように。

[via]
さくらサーバのCronでRubyを動かす時のメモ - まめ畑

・日時の設定

月 - *
日 - *
時 - */1
分 - 0

曜日すべてにチェック

初めのうちはテストとして5分ごとにして、動作確認しました。

作ったもの

tbacker (tback_bot) on Twitter

現時点で6500枚からランダムに選んでいますw
好きな人は好きになるはずっ!

■参考リンク
Net::HTTP - Rubyリファレンスマニュアル
twitter 0.7.0

jQuery Plugin - 僕のmakeClass

結構前にJohn Resig氏がJohn Resig - Simple "Class" Instantiationnewしてもしなくてもよいclassを作るmakeClassというメソッドをブログに載せていました。

ここ最近はprototype.jsを使わずにJavaScriptをコーディングする機会が増えてきたので、Class.create()の変わりになるこのmakeClassを重宝しています。

んで、これを自分が使いやすいように、改良して使っているのでそれを紹介してみます。

makeClass - before

なかなかトリッキーで面白いコードですね〜。
このnewしてもしなくても良いという部分がオモロい!

newせずに関数が呼び出された場合は、elseのほうに入って自分自身をnewしてからもう一度同じ関数を呼んでいます。

makeClass - after

では自分用にカスタマイズしたほうです。

対して変わってはいないんですが、

まずprototype.js - 1.6のClass.create()では、引数にprototypeに追加してほしいObjectを渡すことができましたので、
それと同じようにmakeClassにもpropという引数を追加。
それをreturnするfunctionのprototypeに詰めとく。

次にmakeClassをjQueryのPluginにしてしまう。
これでグローバル名前空間を汚さずに済みます。

あとbeforeのほうの以下の部分ですが、この書き方だとクラスをnewする際に引数を渡さないとargsがundefinedになってしまい、そのcalleeを見に行くのでエラーになってしまいます。

なので、ちょっと回りくどいですが、三項演算子でargsがあるかどうかで処理を分岐しています。

使ってみる

initメソッドはあればインスタンス生成時に実行され、なければ実行されません。

結構すっきりした感じで書けたと思います。
jQuery Pluginの制作で、要素ごとに何か情報を持たせようとした場合は、prototypeを使うので、そういった場面でmakeClassが役立ちます。

IE6でセキュリティ情報ダイアログがでるパターン

IE6の対応はまだまだ必要な時代ではありますが、httpsでアクセスする際にセキュリティ情報のダイアログが表示されてしまうパターンを忘れないようにメモしときます。
他にもありましたら、コメント欄で教えていただけたらと思います。

Security Information.jpg
(※画像はIETesterでのセキュリティ情報ダイアログ)

iframeにsrc属性がない場合

SSLで開いている画面にiframeタグがあり、そのsrc属性に何も指定されていない場合にIEがセキュリティ保護されているか判断できないために、発生するようです。

これは例えば、lightbox風のJavaScriptを作っているときに、IEでselectboxが前面に来てしまう問題を回避するために、iframeをoverlayレイヤーとして使用するときに発生します。
jQueryライブラリのthickboxでこの問題が発生していました。

■解決策

のようにダミーなhtmlを表示するようにすれば回避できます。

[via]
[PRB] FRAME/IFRAME を含むページを SSL により参照するとセキュリティ警告メッセージが発生する

httpsな画面でhttpなリクエスト

SSLで開いている画面にhttpでアクセスしている箇所が存在するとセキュリティダイアログが表示されてしまう。
たとえば下記のように画像ファイルをhttp経由で取得場合とかだ。

iframeにsrc属性がないと、URLがabout:blankとなり、

about:とhttps:でのスキーマ違いにより、

セキュリティ警告が出るようだ。


via: SSLなページを開くときにセキュリティ情報というダイアログが出る

■解決策

外部サーバーに直接取りにいかずに、手元のサーバーにアップして

としてアクセスすればhttpsで取得しにいくのでダイアログは表示されなくなる。

■問題点

このようにこちら側でhttpからhttpsのリクエストに変更できる場合は問題がないが、
外部サービスのscriptを読み込んでいる場合はちょっと難しい。

プロキシを作成して、サーバーサイドでscriptを読み込み、str.replaceAll("http", "https")のように書き換える必要がある。
外部サービスにhttps用のscirptが用意されているのが一番良いが、そうでない場合はダイアログが表示されてしまいますね。

jQuery.animateのcompleteでremoveするとダイアログが出る場合がある

たとえば以下のサンプルのように、divタグにcssでbackground画像を指定して、クリック時にanimateしcompleteで要素を削除するなどの場合で
SSL環境だとダイアログが出てしまう場合がある。
というか今の時点だと100%出る。(IE7では出ない)

background、backgroundImageのどちらでも再現するので、画像を指定した場合にcomplete直後だと何かブラウザ側の処理が残っていて、
その前にremoveしちゃうから出るのかな?

■解決策

とりあえずsetTimeoutで処理を後回しにすればダイアログは表示されなくなる。
かなり特殊なパターンなので、トレースが難しいがlightBox風のものを作っている人なら遭遇したことがあるかもしれない。

■追記

IE6のセキュリティダイアログは非表示にすることもできるよう。

Internet Explorer のクロスドメイン セキュリティのダイアログ ボックスが表示されないようにする - Greg Collins

ここを参考にIE6側に設定をすればいいみたいですね。

JavaScript - 右クリックを判定する(Operaもいけた)

以下ようにOperaとIEで判断が必要ですが、jQueryを使っているならOperaだけの判断でOK。

ただし、Opera の右クリックイベント検出 - Higé au laitにも記載されていますが、Opera側の設定をしてやる必要があります。
つまりデフォルトの状態だと右クリックをハンドルすることはできない。

JavaScript オプション

この画像のように、チェックを入れてあげると右クリック時のmousedownをハンドルできるようになる。

また

まだ問題がある。コンテキストメニューを表示させないで処理を実行することができない。 preventDefault() でも駄目。


via: Opera の右クリックイベント検出 - Higé au lait

というふうに書かれていたんですが、Opera10ではpreventDefaultを実行しなくともコンテキストメニューが表示されなかった。
バージョン10からそうなったのかな?

Macでローカルに手軽なSSL環境を構築する

ApacheをゴニョゴニョしてSSLな環境を構築してもよいのですが、サクッと試したいときにはXAMPPを使うと便利です。

インストールは上のリンクからMax OS X用のXAMPPをダウンロードして、dmgファイルをクリックしてアプリケーションディレクトリに放り込むだけ。

SSLモードでXAMPPを起動する

実はこの方法がapache friends - xampp for macos xに書いてある、

/Applications/XAMPP/xamppfiles/xampp startssl

をコンソールから実行しても、

Unknown command or add-on!

と表示されてないっていわれる。。。

しょうがないので、/Applications/XAMPP/xamppfiles/xamppファイルを開いて中身を眺めていたら、

"enablessl")
checkRoot

echo -n "XAMPP: " $($GETTEXT 'XAMPP: Enable SSL...')

if test -f "$lc/startssl"

こんなコードを発見!!
enablessl」じゃないかっ!

ということで、

/Applications/XAMPP/xamppfiles/xampp enablessl
/Applications/XAMPP/xamppfiles/xampp start

ってすればhttpsでアクセスできるローカル環境が作れる。

あとは、「/Applications/XAMPP/xamppfiles/htdocs/」にhtmlファイルでも置けばアクセス可能です。

windows環境で試したい場合は、apache friends - xampp for windowsからやってみてください。

さくらインターネットにRuby on Railsをインストールする方法

結構ハマりポイントがあったので、メモメモ。
ググるといろんな人のインストール方法が発見できるんですが、結構古かったりして今の環境には適さないこともあってハマった。

まずはSSHでログイン。
そしてrubyのバージョンを確認しときます。

% ruby -v
ruby 1.8.7 (2009-04-08 patchlevel 160) [i386-freebsd7]

ruby自体もインストールする手順は多々あったのですが、特にこだわりがなかったので、
標準で入っているruby 1.8.7を使うことにしました。

rubygemsをインストール

railsを入れるために、まずはrubygemsをインストールします。

% mkdir $HOME/src
% cd $HOME/src
% ftp http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz

rubygemsは一応最新バージョンにしてみました。
もしこのバージョンでうまくいかない場合は他のバージョンで試したほうがよいかもしれません。

RubyForge: RubyGems: ファイルリスト

では、解凍してインストールを開始します。

% tar zxf rubygems-1.1.1.tgz
% cd rubygems-1.1.1
% ruby setup.rb --prefix=$HOME

$HOME/bin/gem18という場所にインストールされました。

次に環境変数をセットします。

$HOME/.cshrcのset pathの部分に「$HOME/lib/ruby/gem/bin」を追加し、
環境変数、RUBYLIBGEM_HOMEをセットしときます。

set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/b
in $HOME/lib/ruby/gem/bin)

setenv RUBYLIB $HOME/lib
setenv GEM_HOME $HOME/lib/ruby/gem

そしたらsourceで反映させ、rehashでハッシュテーブルを更新します。

% source $HOME/.cshrc
% rehash
% gem18 -v
1.3.5

これでgemが使えるようになりました。

Ruby on Railsをインストールする

じつはここが今回くせ者で、いろんなサイトに書いてあるような、以下の感じだと最終的にrailsがうまく動きませんでした。

% gem18 install rails --include-dependencies

この方法だと2.3.4が入るのですが、railsを動作させたときに

Application error

Rails application failed to start properly"

というエラーが出て、何をどうしようがこのエラーが解消されなかったです。

[via]
さくらインターネットでRails - azlab 開発Memo

おそらくバージョンの問題だと思うのですが、結局原因は良くわかりませんでした。

なので以下のように2.2.2をインストールします。

% gem18 install rails --version=2.2.2
% rehash
% rails --v
Rails 2.2.2

Railsプロジェクトを作成する

僕は$HOMEにcodeというディレクトリを作ってその中でソースを管理しているので、ここにrailsのディレクトリを作成しました。

% cd $HOME/code/
% mkdir rails
% cd rails

そしてrailsコマンドを実行するのですが、またまたここもハマりポイントで、普通に以下のように

% rails test

としてプロジェクトを作成するんですが、railsのバージョンが2.3.2以降だと、「/test/public/dispatch.cgi」というファイルが作成されないようなのです。
まぁ今回は2.2.2を選んでインストールしているので大丈夫なんですが、初めは最新バージョンでやっていたのでハマりました。

% rails -D test

dispatch.cgiが作成されるようにするには「-D」をオプションで指定するといいみたいです。
実際にこのファイルがないと以下のようなエラーになります。

Ruby on Rails_ Welcome aboard.jpg

[via]
dispatch.cgi not found errorについて - akezoraのはてな日記

次にchmodでパーミッションを変更しときます。

% cd test
% chmod -R o+w log tmp

そして環境ファイルの設定を行います。

% vi config/environment.rb

いろんな人の書き方があったのですが、僕は以下を追記してうまくいきました。

# Be sure to restart your server when you modify this file
$LOAD_PATH.push("/home/hisasann/lib/")
$LOAD_PATH.push("/home/hisasann/lib/ruby")
ENV['GEM_HOME'] ||= '/home/hisasann/lib/ruby/gem'
ENV['RAILS_RELATIVE_URL_ROOT']="/test"

次はpublic/.htaccessです。

% vi public/.htaccess

またこのファイルがあるように手順が書かれていたのですが、僕のところにはなかったです。
なので、test/READMEの中にサンプルがあるので、そこから引っ張ってきました。

余計なコメントは削除しました。
というのも折り返しているように見えて、違う行にコメントの隅っこが移動してウマく動かなかったからです。

# General Apache options
#AddHandler fastcgi-script .fcgi
#AddHandler cgi-script .cgi
#Options +FollowSymLinks +ExecCGI

RewriteEngine On

RewriteBase /test

RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.cgi [QSA,L]

ErrorDocument 500 "

Application error

Rails application failed to start properly"

あと大事なのは一番最後の行に改行を入れることです。
これをしないと.htaccessがうまく読み込まれないためInternal Server Errorになって動きません!

一般公開する

$HOME/wwwが外から見える公開ディレクトリになるので、ここにシンボリックリンクを作成します。

% ln -s $HOME/code/rails/test/public $HOME/www/test

これで「Welcome aboard」画面が表示されればとりあえずうまく行きました!

sqlite3-rubyをインストールする

この時点で「About your application's environment」リンクをクリックすると、
sqliteがないとエラーになるので、最後にsqlite3をインストールします。

% gem18 install sqlite3-ruby

どうやら僕の環境では、最新バージョンがうまくインストールされませんでした。
なので、

% gem18 install sqlite3-ruby --version=1.2.4

とバージョンを指定してインストールしました。

Ruby on Rails_ Welcome aboard-1.jpg

これでエラーもなくRuby on Railsが動く状態にまで持って行けました!


あとはmysql入れて、どうやってデプロイするかを考えないと。。。

■参考リンク
がんちゃんのブログ: さくらのレンタルサーバーにRuby on Rails 2.0.2をインストールする方法
がんちゃんのブログ: さくらのレンタルサーバーにRuby on Railsをインストールする方法 その2
Ruby on Rails入門3 さくらインターネットにRuby on Railsをインストール - nyon2.net
さくらインターネットでRails - azlab 開発Memo
そんな悲しい目をしないで » Redmine
Ruby/Rubygems使い方まとめ - 俺の基地
さくらインターネットでsqlite3 - kajilog
さくらインターネットでRuby on Railsする | JAM☆ぱん

HTML5 - inputタグのrequired属性などなど

required属性

input要素に新しく追加されたrequired属性は、submitボタンが押されたタイミングでもしも値が入力されていない場合にチップを表示してくれます。
これを使うとJavaScriptで必須バリデーションを作る必要がなくなりそうで、ちょっと便利かもと思いました。
(まぁサーバーサイドのエラーチェックは必須ですけどねっ!)

チップは以下のように表示されて、ユーザーに必須であることをお知らせしています。

required

はじめsubmitボタンを押してもエラーチップが出なくてハマったのですが、どうやらname属性が必須のようです。

■対応ブラウザ
現時点ではOperaのみ、バージョンは10で試しました。

■required属性の仕様
4.10.5.2 Common input element attributes -- HTML5

placeholder

こっちはここ最近よく見る、focusがあたると文字が消えてblurすると文字が表示されるアレです。

しかもさりげなく角丸になってますw

placeholder

■対応ブラウザ
現時点ではSafariのみ、バージョンは4で試しました。

■placeholder属性の仕様
4.10.5.2 Common input element attributes -- HTML5

独自のエラーメッセージも表示できたりする(制約バリデーション API)

パスワードを確認するために、2つテキストボックスを用意することは多々ありますが、
1つ目のパスワードと2つ目のパスワードが一致していない場合はsubmitしない、なんてことも出来ちゃいます。

要素にsetCustomValidityというメソッドが追加され、ここにメッセージをセットするとエラーチップを表示してくれます。

独自メッセージ

setCustomValidityにセットしたメッセージとは別に日本語で何かメッセージが出ていますが、これ消せないのかな?

■対応ブラウザ
現時点ではOperaのみ、バージョンは10で試しました。

■制約バリデーション APIの仕様
制約 - フォーム - HTML要素 - HTML5タグリファレンス - HTML5.JP


自分の使っているブラウザでどの程度inputタグの属性がサポートされているかは、以下のサイトを閲覧すると確認できます。
HTML5 input attributes support


■参考リンク
HTML5, きちんと。

(function(){})();をもう少しスマートに書きたい

JavaScriptである程度ボリュームがある関数を書くと、変数名が被って上書きされちゃったりするので、
スコープを小さくしたいから(function(){})();で囲ってたりしたんですが、
なんかこの書き方がしっくりきてなかったので(多分最後の()が面倒なのかも?)、Pという関数を作ってみた。

$.P

使い方

一番シンプルなソース。
これで中のfunctionを呼び出してくれる。

上の感じだけだと面白くないので、実行させたいfunctionに引数を渡すこともできる。
そのときの型がfunctionの場合は実行結果を引数として渡す。

あれ?なんか余計に分かりにくくなっちゃつたかもw
う〜ん。。。

■ダウンロード
gist: 225353 - GitHub


■追記

上記パターンだと以下のようにjQueryプラグイン書くときうまくいかないな。
jQueryはfunction型だから勝手に実行されてしまう。。。

CPANがFetching with LWPの部分で止まるときの対処

cpanで何かモジュールを入れようとするときに、普通ならそんなに待ち時間がないはずなのにやたら重くなる場合がある。

cpan> install Net::Twitter
CPAN: Storable loaded ok
Going to read /Users/hoge/.cpan/Metadata
Database was generated on Sat, 10 Oct 2009 04:27:15 GMT
CPAN: LWP::UserAgent loaded ok
Fetching with LWP:
...

どうやらファイアウォールあたりの設定を強化していると、遮られてタイムアウトが連発するみたい。

Macだと「システム環境設定」の「セキュリティ」内のファイアォールタブにあるんだけど、
僕は以下のように、「必須のサービスのみ許可」にしているせいだろうか。

セキュリティ.jpg

LWPをパッシブモードで接続するようにする

LWPはパッシブモードで接続しにいくようになるので、無駄な待ち時間が無くなる


via: B-Wiki - Tips/Perl/CPANでLWPが遅い * A-tak.com

ということなので、「/User/[User Name]/.bash_profile」に対してさっそく以下を実行。

export FTP_PASSIVE=1
source .bash_profile

これで劇的にcpanモジュールのインストールが速くなった。

はい、最高です!

[via]
B-Wiki - Tips/Perl/CPANでLWPが遅い * A-tak.com

■関連リンク
パッシブモードとは 【passive mode】 - 意味/解説/説明/定義 : IT用語辞典


:追記

cpanのConfig.pmに以下を追加する必要あるのかな?(メモ)

'ftp_passive' => q[1],

VMware fusion内のWindowsにIE6、IE7、IE8を入れる方法

IE6からアップデートせずに、純正のIE6をそのまま使っていたのですが、
IE7で崩れる・IE8で動きがちょっとおかしいなど、やっぱりIE6からIE8までをローカルにインストール必要が出てきたためいろいろと試してみました。

もともとIETesterを使っていて、これで満足していたのですが、
やっぱり純正とは違う動きをしたり、「本当に純正IE6でもこうなるの?」という疑問が残る挙動したりしていたので、ここ最近は純正IE6のままにしていたのです。

まずはその苦労の流れをメモに残しておきます。


Internet Explorer Application Compatibility VPC Imageを使ってみる

初めに結論:この方法はうまくいかない

Virtual PC経由でIE6、IE7、IE8を起動出来るイメージがMicrosoftからダウンロードできるので、
まずはこれからインストールしてみました。

以下からVirtual PCをインストール

・ダウンロード
ダウンロードの詳細 : Virtual PC 2007

続いて、各IEイメージをダウンロード

・ダウンロード
Download details: IE App Compat VHD

こちらを参考に作業を進めてみました。
Windows XP の Virtual PC 環境を無料で作成する

結果的にVMware fusion上で各IE用イメージが起動できなかったです。
XPを仮想的に起動して、その中でIE6とかを起動するのですが、起動しようとした時点でVMware fusionに怒られましたw
それ以降Macを再起動しないとVMware fusion起動しなくなったので、この方法はあきらめました。。。



IE8をインストール、それ以外はスタンドアロン版を入れてみる

初めに結論:この方法はうまくいかない

IE6 と IE7 と IE8 を同じマシンで共存させる方法 - IT戦記

amachangの記事を元にまずはIE8を入れてみます。
IE6から一気にIE8にバージョンアップしてみました。

・ダウンロード
Google に最適化された Internet Explorer 8 のダウンロード

とくに問題なくインストールが完了しました。

続いて、IE7を入れます。

・ダウンロード
Internet Explorer 7 running side by side with IE6. (standalone) | TredoSoft
Download Internet Explorer 7 standalone Installer を入れました。

そして次にIE6を入れます。
Multiple IEのインストール時にIE6だけを選択してインストールしました。

・ダウンロード
Install multiple versions of IE on your PC | TredoSoft

結果的に、IE6、IE7、IE8はインストールされたのですが、2つ大きな問題がありました。

  • IE8のお気に入りを選ぶとPrint画面が表示され、お気に入りからサイトを選べない
  • IE6、IE7でサイト内にあるtextboxに値を入れられない

2個目のほうが致命的で、ログイン画面経由でどこかの画面を見たい場合にはアウトです。
おしいっ!

■参考リンク
試験管のなかのコード :: IE6, IE7, IE8 の共存方法メモ



やっぱりIETesterを使う

初めに結論:この方法で落ち着きました

今までの作業でIE8はすでに入っているのですが、スタンドアロン版のおかげでお気に入り機能が壊れているので、一旦IE8をアンインストールします。

・以下を参考にしました。
Internet Explorer 8 をアンインストールまたは削除する方法を教えてください

そして再起動。。。

またIE8のインストール。。。

そしてまたまた再起動。。。

ようやくIETesterを入れられます。

・ダウンロード
My DebugBar | IETester / Browser Compatibility Check for Internet Explorer Versions from 5.5 to 8


これで純正IE8と、IE8に互換モード用にエミュレートされているIE7とIETesterの中にあるIE6がそろいました。
IE7はIETester内にあるのを使ってもよいかもしれませんが、Cookieが使えないので、互換モードのほうがうまく動くならこっちを使いたいところです。

IE6でCookieに関するバグが出た場合にはどうしようもないですが、とりあえずこれが僕の中でベストなSetupになりそうです。



番外編 - Web SuperPreview

Microsoftが提供しているMicrosoft Expression Web SuperPreview for Windows Internet Explorerというソフトを使うと、
おそらく表示だけなんですが、IE6、IE7、IE8のデザイン違いを見ることができます。

これ使うことあるかな。。。

・ダウンロード
Download details: Expression Web SuperPreview for Internet Explorer

SinatraでちょいTwitterっぽいの書いてみた

sinatraRailsを使うほどがっつりWebアプリを作るのではなく、ちょいと試してみよう!というときにとっても助かるライブラリになります。
実際いろんなことができるので、作り込んでいけばすごいものが出来上がると思いますが、「JavaScriptを試すためにHTMLファイルを作る」と同じくらいPopにWebアプリが作れるので楽しいですね。

そんなsinatraでユーザー登録とかは特に実装していないのですが、タイムラインをAjaxで取得するみたいなものを書いてみた。
画面のデザインとか何も組み込んでいないのでシンプルですが、それっぽく試すにはちょうどいいですね。

sinatraのインストール

まずはsinatraのインストールです。

sudo gem install sinatra

これだけでsinatraの環境が整うのが面白い。

あとは

hello.rbとして保存して、以下を実行するだけ。

ruby hoge.rb

これで、http://localhost:4567/にアクセスすると、Hello World!!が表示されます。

今回使うライブラリのインストール

今回使用するライブラリをインストールしときます。

sudo gem install json
sudo gem install haml
sudo gem install sequel

DBはSqliteを使いました。Mac OS Xにはじめから入っているので楽チンですね。

twitter.rb

今回SequelというDB用ライブラリを使ってみたのですが、これは使いやすいですね。
たとえばもし該当のテーブルがなかった場合は、自動的に作ってくれる(create_tableメソッド)ので、Sqliteクライアントを使って自分でcreate tableをしなくてよいので楽です。

index.haml

テンプレートライブラリとしてhamlを使ってみたのですが、なかなかこれも面白い。
以下を参考に書いてみました。

ウノウラボ Unoh Labs: 5分で分かるHaml

@Timelinesや@UsersにDBから取得したタイムラインたちが入っているので、これをeachでイテレートしています。
中身はハッシュなので、timeline.messageという感じで取得が可能です。

ダウンロード

一応githubにアップしときました。

gist: 210639 - GitHub
gist: 210640 - GitHub

■関連リンク
Sinatra: README (Japanese)
ウノウラボ Unoh Labs: Sinatra気に入った
Ruby Freaks Lounge:第9回 SinatraとSequel・Hamlで掲示板アプリを作る|gihyo.jp ... 技術評論社
Rubyの軽量Webフレームワーク「Sinatra」がステキ - 医者を志す妻を応援する夫の日記

iframe内のDomContentLoadedを監視する方法

あまりないシチュエーションですが、iframeを動的に生成して作った場合にreadyを待ってiframe内の関数やら要素やらを参照する場合はjQuery.isReadyを監視すればよい。

この方法で、window.openしたウィンドウのDomContentLoadedのタイミングも取得できる。
jQueryテストツールのQUnitなんかが同じような方法を使っている。

親画面のHTML

iframe内のHTML


初めて知ったのですが、

でiframe内のhtml全体が取得できるので、ここからfindできるみたい。

だからいちいち

ってしなくても取得が可能。

■関連記事
JavaScriptで単体テストをするならQUnitはいかが?

■関連リンク
iframe 関連処理まとめ - Cyokodog::Diary
iframe内のコンテンツを親からスクロールさせる :: 5509
JavaScript インラインフレーム(iframe)関連 - とみぞーノート

ニコニコ動画検索ページを「再生が多い順」にするグリモン

ここ最近全然グリモン書いていなかったのですが、ニコニコ動画の検索ページのソート順プルダウンを毎回「再生が多い順」するという作業が面倒になってきたので書いた。

XPath使っちゃったので、HTMLの構造が変わったらアウトですが、今のうちは大丈夫そうだ。

ダウンロード

NicoSearchMostPlayback for Greasemonkey

NoTechnoNoLifeのタイトルFlashの解説

NoTechnoNoLifeのタイトルFlashの解説

自分のブログNoTechnoNoLifeのタイトルFlashを「どうやって作っているの?」とコメントで質問されましたので、たいしたFlashではないのですが、ざっくり紹介してみようと思います。

ブログにアニメーションするFlashを導入する場合、一番気になるのがHTMLのレンダリングに邪魔されてFlashのアニメーションがカクカクしちゃうということですが、
これに関してはdelay(遅延)を使ってある程度防ぐ方法にしています。
とくに動画を紹介しているサイトだと結構重くなるので、そうゆうときがこれまた難しいですね。

JavaScriptからDomContentLoadedのタイミングを受け取って、そのときにアニメーションを開始するなんて方法も使えそうですが、ExtarnalInterfaceを使いたくなかったので、こうゆう方法は使っていないです。

サンプルページ

まずはサンプルとなるページを用意したので、こちらをご覧ください。
NoTechnoNoLife/test.html

初めにタイトルとなるNoTechnoNoLifeの画像を表示しておいて、2秒ほど遅延させます。
その後に足やフラワーがアニメーションし始めます。

レイヤーの説明

これを表現するのに、今回は3枚のレイヤーを作っています。

タイトル画像を持つBaseLayer 足の部分を持つLegLayer そして最後に上から降りてくるflowerLayer

このFlashをクリックすると、自分の画面をリロードするのですが、これはflowerLayerにリンク機能を付けて実現しています。
なので、flowerLayerが降りて来ない限りクリックしても無反応になっています。(これはこれで問題かな。。。)

リンク機能もいろいろあって、JavaScriptのlocation.hrefを呼び出すとかあるのですが、微妙にクロスブラウザの処理が必要なので、

こんな風にnavigateToURLメソッドを使うようにしています。
これだとどのブラウザでクリックしても同じ挙動でした。

そしてこれらを順番にSpriteにaddChildしていき、それっぽくdelayをかけてアニメーションさせています。

使っているライブラリ

アニメーションの部分ではTweenerを使っていて、モザイクの機能も足したかったので、@24Log » Blog Archive » Tweenerでモザイク処理できるようにしてみたからモザイク用のライブラリを拝借して使っています。

いや〜助かります!

ソースコード

ブログに貼付けるにはちょっとコード量が多かったので、以下に置いておきます。

gist: 204756 - GitHub

まとめ

完全に自分用に作ったActionScriptなので、とっても恥ずかしいのですが、誰かのWeb制作の手助けになれば幸いです。

あと気分で画像やアニメーションを変えることがあると思いますので。。

JavaScript - HelloWorld

HelloWorld.png

前回jQuery.animateを順番に実行するaddCommand作りましたで紹介したaddCommand - jQuery Pluginを使ってアニメーション「HelloWorld」を書いてみました。

少ないコードでストーリーっぽいアニメーションを描くことができるので、この手のscriptを書くのに適しています。
まだまだ課題はあるんですがね。。。

アニメーションする要素の量が多いので、SafariかChromeで見た方がスムーズに動くと思います。

画像を使ったHelloWorld

・サンプル
addCommand - HelloWorld

・コード
gist: 200472 - GitHub

HTMLテキストを使ったHelloWorld

CSS3のText-Shadowを使っているので、Safari 3+, Opera 9.5, Firefox3.+で見てくださいね。

・サンプル
addCommand - HelloWorld2

・コード
gist: 200473 - GitHub

コードの解説

このコードは「画像を使ったHelloWorld」のJavaScript部分になるのですが、初めのfor文で各画像を画面外に配置して、座標をjQuery.dataに格納しておきます。

そして画像の個数分addCommandメソッドを使ってアニメーションをセットしていきます。
途中、「100 * index」としてdelayを掛けて遅延させてます。

大体これぐらいのコードを書けば、それっぽくアニメーションさせることが可能です。

以上、HelloWorldでした!

■関連リンク
addCommand - jQuery Plugin

■関連記事
ActionScript3 - HelloWorld
CSS3のText-Shadowで文字にEffectをかけてみる

jQuery.animateを順番に実行するaddCommand作りました - jQuery Plugin

jQueryで1つのアニメーションが終わったあとに、違うアニメーションを実行させたい場合は、callbackを使う必要があります。

これだとちょっとネストしちゃうし、なんとなく使い勝手が悪いので、セットした順番にアニメーション処理を実行するFlashのライブラリProgressionのaddCommandっぽいものを作ってみました。

何かJavaScriptでアニメーション作品を作ろうとすると必ずこの「1つずつアニメーション問題」が発生するので、この手の作品作りで何かの役にたてば幸いです!

addCommand - jQuery Plugin

使い方

Prop($.css)とDoTweener($.animate)というクラスを渡したり、functionを渡したり、さらに一気にアニメーションさせるように配列にDoTweenerを詰めて渡したり出来ます。

詳細

細かい使い方は以下のサイトに用意しましたので、参考までに。

addCommand - jQuery Plugin

サンプル動画

あと1個前のエントリーでJavaScriptでスクロールバーを波打たせる - Scrollbars Experimentを紹介しましたが、それっぽいことをaddCommandを使って作ってみました。

addCommand - Screencast from hisasann on Vimeo.

サンプル動画のソースコード

gist: 190118 - GitHub


またこの他のライブラリや作品はhisasann.comに掲載していますので、是非ご覧ください。

JavaScriptでスクロールバーを波打たせる - Scrollbars Experiment

まだどやって実現しているか見ていないのですが、divタグが何個も並んでいて、onscrollで隣接するスクロールバーの高さから計算して波打たせてるのかな。

Webkit系のエンジンで見るといい感じになりそうです。

Chrome Experiments - Detail - Wavy Scrollbars

[via]
House dust

CSS3のText-Shadowで文字にEffectをかけてみる

Pure CSS Letterpress Effect.jpg

Create a Letterpress Effect with CSS Text-Shadowの記事を見て触発された。

text-shadowというCSS3のプロパティを使うと上の画像のように、テキストにエフェクトをかけることが可能になる。

たとえば以下の感じ。

指定している値については以下を参照。

X軸方向への距離
左右のぼかし距離、マイナス値だと左、プラス値だと右。
Y軸方向への距離
上下のぼかし距離、マイナス値だと上、プラス値だと下。
ぼかし距離
ここを大きくするとぼかしの範囲が大きくなる。
ぼかしの色、この部分は最後に書いても最初に書いても同じように動作する。
つまりtext-shadow: #555 2px 5px 5px;でもよい。

サンプルコード

テストページ作ってみた。
ファイアーの感じとかも出せるので、これは楽しいですね!
CSS3 text-shadow Effect

■関連リンク
text-shadow - CSS Dencitie

CRASHCLOCK - SRC

21_21 DESIGN SIGHT-「骨」展 Bonesで発表されたSCRtha ltd.)制作のFlash作品。

トラス構造が物理演算で崩壊していく感じがステキすぎる!

SCR | CRASHCLOCK by thaここからスクリーンセーバーをダウンロードできるんですが、パソコンの性能が結構よくないと本来の動きは体感できないかもしれませんね。

中村勇吾氏、ハンパねぇな〜w

HTML5とCSS3を使ったすばらしいDEMO「死にたい」



WebKit Nightly Buildsを使った面白いデモがありました。

以下の記事で詳細が見れるのですが、デモの映像を見ているだけでHTML5とCSS3の可能性にわくわくしちゃいます。
とは言ってもまだまだWebkitのNightlyバージョンでしかこの動きは厳しいようで、今後各ブラウザがHTML5とCSS3に対応していくとしてもまだまだ厳しいんでしょうね。

HTML5 と CSS3 で 死にたい


サンプルページは\(^o^)/ - HTML5 CSS3 DEMOっ アニメーション - \(^o^)/になりますが、


サンプルページは高負荷です。パソコンの性能によってはカクカクしたり、最悪ブラウザがフリーズする可能性があります。

via: HTML5 と CSS3 で 死にたい

とのことですので、なるべくWebkitのNightlyで見るようにしましょう。

僕も何か作ってみたくなりましたw

いろんな言語のクロージャ

以前にJavaScriptのクロージャを無名関数、クロージャ、そしてレキシカルスコープへでまとめたのですが、今回は他のスクリプト系言語のクロージャを取り上げてみたいと思います。

Rubyのクロージャ

Rubyで関数と呼ばれるものは必ずクラスに所属しています。
トップレベルな空間にメソッドを定義するとObjectクラスに所属するメソッドになるようです。

そしてRubyのクロージャは実際には関数オブジェクトではなく、Procというクラスのインスタンスを返すようです。
Proc.newにはブロックを渡しこれをオブジェクト化したものを返すとクロージャが出来上がるというのが大体のイメージになります。

小難しいので以下のコードを見てください。

まず外側にある関数get_closureにはローカル変数としてcountがあります。
そしてreturnでProcインスタンス、つまりクロージャを返すようにしています。

このクロージャを取得すると呼び出すたびにブロックに渡された引数をcountに加算していきます。
JavaScriptのようにreturn function(){}のように無名関数を渡すのとちょっと違い、ブロックオブジェクトというところが難しいところですね。

そしてProc.new意外にもクロージャを作れるものとしてlambdaprocがあります。
書き方は以下の感じ。

※補足
Proc.newとlambdaの違いは、
lambdaのほうはブロックに渡された引数の数とcallメソッドが呼ばれたときの引数の数をチェックするが、Procのほうにはnilが入るみたいです。

[via]
Rubyのblock、Proc、lambdaを理解する - 医者を志す妻を応援する夫の日記

■参考リンク
Rubyの「クロージャ」再考 - バリケンのRuby日記 - Rubyist
まつもと直伝 プログラミングのオキテ 第5回(3) - まつもと直伝 プログラミングのオキテ:ITpro

Perlのクロージャ

まずブロックスコープを作成し、その中で$count変数とクロージャとなる$closure変数に関数を代入しています。
こうすることで$count変数は$closure関数が参照している間解放されずにスコープに存在し続けます。

Rubyの場合はブロックをreturnしていましたが、Perlではブロックで囲った中で関数を代入するという方法でできるんですね。
でもこの方法以外にもPerlだからいろんなトリックがありそうです。。。

■参考リンク
Perl5編 第28章 クロージャ
クロージャの定義 - Perl入門〜サンプルコードによるPerl入門〜

Pythonのクロージャ

Pythonの場合は先ほどRubyで出てきたlambdaを使うかローカル関数を定義してそれを返すかの2通りのようです。

ただPythonでクロージャを作る場合にはちょっとだけ注意する点があります。

僕はPythonのバージョン2.5.1を使っているのですが、このバージョンでは内側にある関数内で外側にある関数の変数に値を代入できません。
Pythonでは代入とはローカル変数に対して実行されるので、内側の関数内でcount += argとすると、

UnboundLocalError: local variable 'count' referenced before assignment

となり未初期化変数への加算となりエラーになってしまいます。
これを防ぐのにリストに入れるというのがあるようです。(トリッキーだな〜w)

Python3からはnonlocalとローカル変数ではないという情報を変数にもたせることができるので、
nonlocal count += argと書けるみたいです。

■関連リンク
Python 3.0 Hacks:第1回 nonlocalでクロージャが便利に|gihyo.jp ... 技術評論社
お気楽 Python プログラミング入門:第3回再帰定義と高階関数
pythonでクロージャ
Pythonでのクロージャは? - def __mopemope__(self, *args, **kwargs):

JavaScriptのクロージャ

普段使い慣れているだけあって、一番理解しやすいのがJavaScriptのクロージャです。
関数オブジェクトをreturnできるので、クロージャ=関数という感覚が掴めるので馴染みやすいクロージャですね。

無名関数を即時実行してclosure変数にはreturnされた関数オブジェクトが格納されています。
これでclosure関数を呼び出すとcount変数がレキシカルスコープになり、引数の値が加算されていく感じです。

ActionScript3のクロージャ

ActionScriptにはFunctionという型があるので、無名関数を作ってreturnするだけでクロージャが出来上がる。
JavaScriptとほぼ一緒ですね。

Javaのクロージャ

Java7でクロージャが入る入らないという話が以前盛り上がりましたが、あれってどうなったんだろう。。。

現時点でJavaにクロージャはありませんが、それっぽいものは存在します。
無名関数ではなく無名クラスです。

以下がクロージャ的無名クラスを返すクラスである。
このクラスのgetCounterメソッドを実行すると、return new Counter()と
何かクラスのようなものをnewしている。

本来ならreturn new (){}としたいところなのだが、受け取り側でどのような型で取得すればよいのが分からない。
静的言語ゆえな面倒くささはあるのだが、interfaceかClassを事前に定義しておき、
それを指定してnewする感じで使うのが一般的にようです。
今回はinterfaceが上位型の無名クラスなので上位クラスはjava.lang.Objectになる。

こっちは無名クラスを使うほう。

クロージャ(無名クラス)を取得しているgetCounterの型はClosureClass.Counterになるので
変数にもこの型を指定している。

まとめ

いろんな言語のクロージャを取り上げてみたが、プログラム言語ごとに仕様は違うし分かりやすいものもあれば
分かりにくいものも存在する。
Java7のクロージャの解説記事Java 7のクロージャ(BGGA版)のプロトタイプを試してみた(2)を見てみたのですが、さっぱり分からなかった。

ってかクロージャなのか?w

今回解説した内容意外でもさまざまな方法でクロージャを作成する方法があるかもしれません。
そうゆうハックを探すのもプログラム言語を理解するためには重要ですね。

■関連記事
クロージャのスコープは関数オブジェクト単位だよ
JavaScriptでちょっと面白いコード - 式クロージャ

JavaScriptライブラリ「Grow」のDomContentLoaded判定方法

JavaScriptライブラリGlowのDomContentLoaded判定部分をメモメモ。 jQueryとほぼ同じ感じだけど、glow.env.webkit < 525.13の判定はこのバージョン未満だとDomContentLoadedがないのかな? あと というonloadの詰め替えラッパーの記述がなつかしい。

Rubyでファイル名を使いたいモジュール名と同じにすると動かなくなる

ちょいハマってしまったのだが、何か試したいモジュールをgemとかでダウンロードしてきて、よしさっそく試してみるかとrubyファイルを作成したが実行してみるといっこうにエラーが消えない現象がある。

以下がどんぴしゃな内容なのだが、

モジュールを利用したRubyスクリプトが突然Name Errorになる - お題目うぉっち

ようはテスト用プログラムのファイル名をダウンロードしてきたモジュール名と同じにすると動かないということみたい。


Running

この現象に気がついたのが、Anemone - Ruby Web-Spider Frameworkというサイトをクロールしてリンクを取得してくるモジュールを試す際に同じ名前のanemone.rbというファイルを作成したのが原因。

もしもどうしてもanemone_test.rbとか作成したくない〜という場合は、ファイル名はanemone.rbにしておいて、requireで読み込む先を以下のようにすると動くようになる。

SafariのWebインスペクタはFirebugっぽくウィンドウに統合できる

知らなかった〜。
ゆえにあんまりSafariを開発用ブラウザにしてなかったw

以下のようにWebインスペクタの左下のボタンを押すと。


こんな感じにSafariのウィンドウに統合できるみたい。

でもFirebugの調査みたいに、マウスをもって行った箇所を表示するって機能はまだないのかな?
これがないといちいちhtmlタグから順番に降りていかないといけないから面倒・・・

RhinoでJavascriptの継続を使ってみる

継続と言うとSchemeが有名ですが、Rhinoのドキュメントを読んでいたら「Rhino 1.6R1」から継続が存在してたみたいだったのでとりあえず試してみた。
Rhino 1.6R1 変更ログ

継続とは?

継続と聞くとちょっと小難しいので、まずは軽く説明してみます。
継続とは「ある時点での状態」を変数に格納しておき、そのポイントに後から戻るということが可能になる概念である。

・・・

まったくもって小難しいのでとりあえず以下のSchemeのコードを見ていただきたい。

継続サンプル - Scheme

結果

こぶた
たぬき
きつね
ねこ

[via]
Schemeを作ろう 第3回

このコードではdisplayで文字を出力しているのだが、途中のcall/ccという部分が継続オブジェクトを生成している部分になる。
この継続オブジェクトをx変数にセットしているので、もし後でx変数に入っている継続オブジェクトを実行するとさらに

きつね
ねこ

と文字列が出力される。
このようにあるポイントを変数に記憶させておき後から呼び出せるのが継続になるのだ。

そしてそのときのスコープ内の値も保持されているのでクロージャっぽいですね。
ってかクロージャも継続と言ってもいいのかな?

Rhinoをインストールする

一応Rhinoを使ってJavaScriptの継続を試すのでのインストールを書いておきます。参考までに。
あとボクの環境がMacなのでWindowsの方は適宜読み替えていただきたい。

まずは以下からダウンロードします。
Rhino のダウンロード

そしてRhino Shellが使えるように、環境変数を設定しましょう!

ホールディレクトリにある.bash_profileファイルに以下を追記します。
(CLASSPATHに入れるパスはご自分の環境に合わせてくださいね。)

export CLASSPATH=/code/java/rhino1_7R1/js.jar
alias rhino="java org.mozilla.javascript.tools.shell.Main"

.bash_profileへの追記などは以下を参考にしてみてください。
Mac OS Xで環境変数にPATHを追加する方法

設定が終わったら、ターミナルから

$ rhino

と打つとそのままJavaScriptがirb形式でコードを入力できます。
rhinoから抜けたい場合は「quit()」と入力してください。

継続オブジェクトContinuationを使ってみよう

Rhinoで継続を使う場合は、Continuationというクラスをnewすることから始まります。
Continuationクラスをnewして変数に格納すれば、そこが継続として後から戻るポイントになります。

では実際に使ってみましょう!

このコードを保存してrhinoコマンドで実行します。

$ rhino -opt -1 -f coroutine.js

-opt -1は継続を使う場合に必要で、-fはファイルから実行するという意味になります。
Rhino Shell - MDC

先ほどのSchemeのコードに近い感じですが、showMessage関数を呼ぶとprint関数で順番に文字を出力していきますが、
途中にあるcall_cc関数内でContinuationクラスをnewして継続オブジェクトを返しています。
(ここでreturnされるオブジェクトはfunction型になります。)

そしてshowMessage関数の呼び出しの後に継続オブジェクトを関数として呼び出しています。
ただし継続オブジェクトが実行した後はc変数に入っている継続オブジェクトはundefinedになってしまうので、instanceofで継続オブジェクトかどうか判断しています。
これについては順番に説明して理解してみましょう!

以下にshowMessage関数を呼び出したところから処理の流れを記載してみました。

showMessage関数の呼び出し

文字列の出力(hoge1)

Continuationオブジェクトの生成

文字列の出力(hoge2、hoge3)

instanceofで確認→OK

継続関数オブジェクトの実行

文字列の出力(hoge2、hoge3)

instanceofで確認→NG

よって2回目の継続関数オブジェクトは実行されない

ちょっとややこしいですが、c()で継続関数を実行すると継続ポイントに戻って再度コードを実行していきますが、
再びc()の部分まで実行しようとしているのでそれをinstanceofで阻止している感じです。

また継続オブジェクトには引数を渡すこともできます。
「c("foo");」という感じで呼び出すと、「c = "foo"」と同じになり継続オブジェクトに渡す引数で処理を分岐したりもできます。

JavaScript1.7のyieldに似てる

一見yieldを使うと同じような雰囲気は出てるんですが、継続と少し違うのはyieldはポイントポイントで完全に処理が止まって待っててくれるのですが、
継続は処理をすべて1度実行しちゃいます。

継続とyieldの出力結果を見るとよく理解できると思います。

継続の場合の出力結果

hoge1
hoge2
hoge3
hoge4 ←ここが継続ポイント
hoge5

yieldの場合の出力結果

hoge1
hoge2
hoge3

まとめ

継続をどのようにうまく使うかなど、まだ全然理解できていないのでこれから少し掘り下げて勉強してみたいと思います。
(それならScheme勉強したほうが良さそうですねw)

あとGemmaさんの記事で、サーバーサイドJavaScript(Rhino)の継続でCoroutineを書いてみた - Gemmaの日記
というのがすごく参考になります、2つの関数を交互に実行する協調的マルチタスクな処理実装されています。
すごいっす。

■参考リンク
RhinoWithContinuations - Cocoon Wiki

画像をめくるjQuery Plugin - jStack作りました

画像をめくるjQuery Plugin - jStack作りました

Mootools版のmooStackからインスパイアされてjQuery版を作ってみました。

ただ画像をめくるだけだとつまらないので、トランプのようにシャッフルする機能を入れてみました。
ちょっと面白い動きをするのでなかなか気に入ってます。
遊んでみてください〜!

デモ、詳細は以下からどうぞ。
jStack.js - jQuery Plugin

■他に作ったもの。
画像がグルグル回るjQuery Plugin - jMerrygoround作りました

Macに発音させるsayコマンドでDaftPunkは厳しい

MacWiki - コマンド/say
Macに標準でインストールされているsayコマンドは、引数に与えた文字を読み上げてくれるコマンドです。
この時点でちょっと面白いのですが、さらに声の種類も豊富にあるのでいずれかを選んで発音させることができます。

実際のVoiceは以下のようになっており、結構種類がある。

$ ls /System/Library/Speech/Voices/

Agnes.SpeechVoice
Albert.SpeechVoice
Alex.SpeechVoice
BadNews.SpeechVoice
Bahh.SpeechVoice
Bells.SpeechVoice
Boing.SpeechVoice
Bruce.SpeechVoice
Bubbles.SpeechVoice
Cellos.SpeechVoice
Deranged.SpeechVoice
Fred.SpeechVoice
GoodNews.SpeechVoice
Hysterical.SpeechVoice
Junior.SpeechVoice
Kathy.SpeechVoice
Organ.SpeechVoice
Princess.SpeechVoice
Ralph.SpeechVoice
Trinoids.SpeechVoice
Vicki.SpeechVoice
Victoria.SpeechVoice
Whisper.SpeechVoice
Zarvox.SpeechVoice

この中でBadNewsとGoodNewsが使えなかったのですが、原因不明・・・

Voiceを選ぶときには-vオプションを指定する

say -v Boing San of a bitch

すべてのVoiceで発音させるシェルプログラム

すべてのVoiceを列挙して順番に発音させていきます。

Daft Punkっぽくやってみたかったけどダメだった

THE DAFT PUNK'S CONSOLE by NAJLE.comこれを見てsayコマンドでできるかな〜と簡単に考えていましたがやっぱりダメだった。
でもちょっとそれっぽくはなったかも。

全パターンを聞いてみて、「harder better faster stronger」の声に似ているのはTrinoidsでした。

これは近いんだけどキーを上げれないから厳しいな。
でも気合い入れればそれっぽくなるかも!
あとdo itのところが速過ぎるw

■関連リンク
シェルの変数に慣れる
【 文字列を置換する「sed」 】:ITpro
シェルスクリプト入門
・Macの読み上げアプリアップル - ダウンロード - ユーティリティ - iSpeech

Daft Bodies - Harder, Better, Faster, Stronger

この映像が本来のPVな気がしてきたw

ActionScript3 - HelloWorld

にとよんさんが作られたHelloWorldFlashをForkしてみた。

文字のラインにCircleを描く

forked from: Hello World!!! - wonderfl build flash online

元々のHello World!!! | wonderfl build flash onlineではFlash内をCircleで埋め尽くしていますが、ボクのほうは文字のラインにだけCircleを描くようにしています。

あとfiltersを使ってぼかして、BlendMode.ADDでキラキラさせてます。

文字のラインにアルファベットを描く

forked from: Hello World!!! - wonderfl build flash online

アルファベットにalphaを指定したいんですが、うまくいかなくてTextFieldにalphaをつける | (SCRATCHBRAIN.BLOG v2)を参考にやってみたのですが激重になってしまったので、画面の外からアルファベットを出現するようにしています。
こっちはいまいち文字が読めない感が否めない・・・

プログラムコード(Circleのほう)

PerlのMVCフレームワークCatalystをインストールしてみた

PerlのWAFを使ったことがなかったので、インストールしてみたのですがいやはや苦労しちゃいましたのでメモメモ。

インストール環境

OS
MacOS X Leopard
Perl
5.8.8

CPANからのインストール

ネットでCatalystのインストール方法を見ていると、いろんな人がいろんな方法でやっていて正直難しかったです。
どうやら以下の2つのモジュールを入れれば良さそうだと分かっても、CPANがアクセスするftpサーバーの都合でダウンロードできなかったりと意外と面倒でした。

  • Catalyst::Runtime
  • Catalyst::Devel


それで最終的に行きついたサイトが以下。
perl:catalyst [kazusa wiki]

こちらではcat-installというファイルをダウンロードし、

perl cat-install

を実行する。
これでCatalyst::Runtimeモジュールがインストールされます。

そして次に

sudo cpan Catalyst::Devel

を実行して、もう一つのモジュールをインストールします。

ただ、

Your terminal expects ISO-8859-1 (yes/no)? [yes] no

というのを聞かれなかったんだけど、途中に出てきてたのかな?
見当たりませんでしたw

CPANの接続先ftpでエラー

Not Connectのエラーがコンソールに出ていて、何回かやるとうまくいきそうなんだけど、ダメみたいでハマった。
調べてみたらCPANの接続先を追加するとうまくいくとなっていたので以下を参考に追加してみました。
LunaTear: CPANのサーバー追加

cpan
cpan> o conf urllist push ftp://ftp.u-aizu.ac.jp/pub/CPAN
cpan> o conf urllist push ftp://ftp.dti.ad.jp/pub/lang/CPAN/

そして一応追加されているか確認。

cpan> o conf urllist

大丈夫だったら

cpan> o conf commit

これで変更が反映されます。
commitしないといくらやっても接続先サーバーが追加されないので注意が必要です。

雛形を作ってみる

Ruby on Railsのようにザクッとテンプレートを作ってくれるので、ここがCatalystの魅力なんでしょうね。
コンソールで、

catalyst.pl HelloWorld

これでモデル、コントロール、ビューあたりが自動生成されるようです。

そしたらHelloWorldフォルダの中にあるスクリプトを実行してスタンドアロンな簡易サーバーを起動してみます。

cd HelloWorld
./script/helloworld_server.pl

これを実行するとコンソールにURLが表示されるので、後はブラウザでアクセスするだけです。

HelloWorld on Catalyst 5.80002

まとめ

Javaに慣れていると必要なライブラリはlibの中に入れとけば動くという感覚なんですが、こうゆう風にCPANから必要モジュールをインストールし、それらが「/Library/Perl/5.8.8」に勝手に展開されて後は呼び出すだけというのがまだちょっと慣れない。
どちらかと言えばプロジェクト単位にライブラリを配置したいという感じがします。

Movable Typeなんかがその方法を使っていて、必要なCPANモジュールはextlibというフォルダに格納されています。
なのでプログラムコードの中でそこを見に行くように、

なんてことをしないといけないのですが、どちらかというとボクはこっちより。
このブログのレンタルサーバーはロリポップを使っているのですが、telnetもsshも使えないのでCPANからインストールという方法が使えなそうです。
だからデプロイもftpになるのかな?めっ、面倒だ・・・w

最もシンプルにJavaのAOPを書いてみる→そしてJavaScriptへ

SpringSeasar2などのFrameworkを使っているとDIやAOPを簡単に実現できますが、このAOPを自前で手軽に書くにはどうやるのかな〜と思って調べてみた。
AOPとは[ThinkIT] 第5回:AOPとは何か (1/4)あたりを読むと分かりますが、ある処理を実行する前や後に追加で処理を入れることをいい、しかも実装クラスには手をつけずに外から処理を追加するように見せるのが特徴です。

ではシンプルにAOPを実現するコードを書いてみます。
今回はServiceというInterfaceを実装したServiceImplに文字を出力する処理だけを記述し、その前後にロギングの処理をAOPで織り込んでおきます。

Main.java

まずはメインとなる実行クラスを作ります。
このクラスで重要なのはProxy.newProxyInstanceというメソッドを使ってプロキシクラスを取得していることです。
たとえばServiceImplを普通にnewしてしまうと、純粋に文字を出力する処理しか存在しませんがこれではAOPを入れる隙間がありません。
なのでプロキシクラスを経由してServiceImplの処理を呼んでもらうようにします。

それがProxyというクラスの役目になります。

Proxy.newProxyInstanceメソッドの引数は

ClassLoader
プロキシクラスを定義するクラスローダ
Class<?>[]
プロキシクラスが実装するインタフェースのリスト
InvocationHandler
メソッド呼び出しのディスパッチ先の呼び出しハンドラ

になります。
第3引数に渡すInvocationHandlerに渡すクラスが実際のAOPとして折り込みたい処理を実装したクラスになります。
詳細は後で紹介します。

■参考リンク
Proxy (Java 2 Platform SE 5.0)

Service.java

普通にインターフェースです。

ServiceImpl.java

文字出力処理を実装しているクラスになります。
文字を出力し、returnとして出力した文字を返しています。

Intercepter.java

プロキシを作成するためにまずはInvocationHandlerインターフェースをimplementする必要があります。
そしてService.print()が呼び出されるとこのクラスのinvokeがディスパッチされます。

invokeメソッドの引数は

Object proxy
プロキシクラスの参照
Method
呼び出されたメソッドのMethodオブジェクト
Object[]
呼び出されたメソッドの引数配列

になっています。
ひとつ気をつけたいのはmethod.invokeを呼び出すさいの第1引数はproxy変数ではないことです。
proxy変数にはプロキシクラスの参照が入っているので、もしproxy変数をmethod.invokeに渡してしまうと無限にループしてしまいます。
なのでこのクラスではコンストラクタに実装クラスを渡すようにしています。
そして実装クラスをオブジェクトとしてmethodを呼び出します。

■参考リンク
InvocationHandler


これらを実装してMain.javaを実行するとprintの前と後にログ処理が追加され文字がコンソールに出力されます。
ちょっぴり面倒ですが、Intercepterクラスをしっかり作ればもっといろんあ織り込み処理が作れそうですね。

JavaScriptでAOPを実現してみる

では次にJavaScriptで↑で説明したようなAOPを作ってみたいと思います。
名前を一緒にしたほうが分かりやすいのでProxy.newProxyInstanceという関数を作り、この関数からプロキシオブジェクトを取得します。
実際にはオブジェクトを作り直しているだけですが、JavaのProxyクラスも同じようなことをやっているのでそこまで違いはないと思います。

コードは以下のとおり。

まとめ

JavaScriptでAOPを使うことは今のところないとは思いますが、いずれクライアントサイド・ストレージを使ってブラウザ側のDBを使うときにトランザクションをAOPを使って織り込みたいといった要望がでてきたときに便利かもしれません。
trycatchで囲ったりしてコネクション繋いだりトランザクション貼ったりするのはコード量も増えますし、結構面倒だったりもしますしね。

jQueryでツールチップを表示するシンプルなコード

そこまでシンプルでもないかもしれませんが、一応書いてみた。

構成としては、

  1. チップ用のdivタグを生成する
  2. チップを表示する対象となるSelectorにマウスイベントをセットする

これだけ。


■プログラムコード
一応jQueryPluginとして書いてみました。

このjsを読み込んだら、後は以下のように呼び出すだけ。

何度も呼ぶのがちょっと・・・
もうちょいキレイにして機能追加してPlugin化するのもありかな。

追記:
一応デモを用意してみた。
jAltTip.js - jQuery Plugin

Papervision3D - BitmapLayerEffectを試してみた

Mozilla Firefox

ActionScriptで3D空間 - Papervision3Dをためしてみたに引き続きPapervision3Dで遊んでみた。

Papervision3Dが持つBitmapLayerEffectクラスでどうやらエフェクト効果を付けられるようなので、試してみました。
それと奥のほうからズームするようにプログラムを少し修正。

ちょっぴり3Dっぽくなってきました。

Continue reading

ActionScriptで3D空間 - Papervision3Dをためしてみた

ActionScriptで3D空間 - Papervision3Dをためしてみた

Papervision3DはFlashを使って3D空間を簡単に作成できるようにしたActionScriptライブラリです。
Versionが1.Xから2.Xに変わって、かなり仕様が変わったようでネットに転がっているサンプルが結構動かなくて四苦八苦してしまったのでメモメモ。

ぶっちゃけ簡単にと言いましたがそれでもかなり敷居が高いと思います。
でも100行ちょいで3Dを描くことができるので、使い始めるとあっという間に時間がすぎてくほど面白いライブラリ。

ではさっそく使ってみましょう。

Continue reading

いろんな言語のSetter・Getterを比較してみた

プロパティ(属性)を持つクラスを使う場面は開発を行って行くと多々ありますが、各言語によって書き方はまちまちです。

とは言っても目指すところは同じだと思いますので、以下に何個か載せてみました。

JavaScriptのSetter・Getter

IE6、7で実装されていないため、今まで開発では全く使ったことがないですが、使い始めると便利そうですね。

現時点では以下の2パターンでgettter、setterを定義できる。

・Firefox独自実装、その後Safari・Operaも実装

  • __defineSetter__
  • __defineGetter__


・ECMAScript3.1実装

  • get getter()
  • set setter(value)


以下のコードはFirefox、Safari、Operaで動作確認済。

またIE8に実装されたObject.definePropertyメソッドというのがあるみたいなんですが、手元にIE8がないため確認できてないです。
詳細は以下に記述されてます。
IE8 の DOM のプロトタイプと Getter/Setter API はどうなるか - IT戦記
次の JavaScript の仕様はこうなる! ECMAScript 3.0 から 3.1 への変更点まとめ - IT戦記

ActionScript3のSetter・Getter

なんとなくこっちのほうが使う機会が多そう。


詳しい内容は以下からどうぞ。
【AS3入門】getterとsetter - 独学ActionScript

PerlのSetter・Getter

Perlでアクセサメソッドを作ろうとするとちょっぴりコード量が膨らみます。
ようは引数があればSetterと見なし、引数がなければGetterと見なすという感じです。

これをもっと簡略化してくれるCPANモジュールのMooseが気になるところです。

RubyのSetter・Getter

Rubyではそもそもオブジェクトの外部からインスタンス変数を直接参照することができないので、アクセサメソッドが必須になってきます。

以下の例は自分でアクセサを作った場合


でもこれを属性分作るのは面倒なので、以下のように簡単にアクセサメソッドを作ることができます。
ここらへんがRubyっぽいですね。

JavaのSetter・Getter

Javaのアクセサはみなさんご存知ごくごく一般的な感じ。
まぁこれでもEclipseの自動生成を使えば、Getter・Setterは自動で作ってくれるので便利と言えば便利なんですけどね。

まとめ

JavaScriptはやっぱり今の時点でもクロスブラウザの問題が出てきてて、実際に使われるのかどうかそのあたりが難しいところですが、
でもこうして見てみると昔のJavaScriptでは考えられないほど使いやすくなっているような気がします。

Rubyのように1行書けばよいのもあれば、setNameのように自前でメソッドを作らないといけないJavaなんかもあったり言語間ではバラバラなのはしょうがないですね。
いろんな言語を跨ぐと、この言語はどうだったっけかな?みたいに迷ってしまいそうですw

どうしてアクセサメソッドなんて面倒なものを使わないといけないのかは以下のリンクを参考にしてください。
オブジェクト指向プログラムでgetter/setterメソッドを使わなければならない10の理由

JavaScript版Box2dを手軽に使えるようにprotoBox2d書いてみた

Box2DJS - Physics Engine for JavaScript

ActionScriptで有名な(確か元はC++だったような)Box2dのJavaScript版がいつの間にか存在していたので手軽に扱えるようにprotoBox2dを書いてみました。
Box2d自体がprototype.jsを必須にしているので、やむなくボクもprototype.jsで書きました。
ここ最近jQueryばっかだったから正直prototype.jsがきつく感じられた。

一応IE6でも落下のみはできるのですが、すんごい重いです。
IE7はドラッグアンドドロップまでできるようにしてあります。ただこちらも重いです。

Webkit系のブラウザのSafariGoogle Chromeで試してください。ホイホイ投げれます。

デモ、詳細は以下からどうぞ。
protoBox2d.js - Box2d JavaScript Library

[via]
sasapong's room

jQueryでマウスから逃げるRunAwayFromMouse書いてみた Part2

RunAwayFromMouse.js

jQueryでマウスから逃げるRunAwayFromMouse書いてみたで書いたコードを改良して、マウスが動かなくなっても元の位置に戻ろうとするようにした。

それと逃げる範囲を大きくしたので、バラける感じがうまく表現できたと思う。

今まではマウスが動いたたびにmousemoveイベントでエレメントの個数分ループさせていたのですが、これだとめちゃくちゃ遅くてまずはここを以下のように改良した。

mousemoveイベントのコード

このイベント時はマウス座標を変数に格納するだけを行い、エレメントを逃げさせる処理は別のタイマーで書いた。
それが以下。

タイマーでエレメントを動かすコード

一応60ms単位でエレメントを動かしているが、もう少し感覚を短くしても問題はなさそうだ。
ただしやっぱりFirefoxだともっさりしてしまうので、大体60ms程度が望ましい。

動作は以下のリンクからどうぞ。

RunAwayFromMouse.js

まとめ

マウスの座標はmousemoveなどのイベント時じゃないと取得できないので、このイベントでは最小のコードを実行して、別スレッドでエレメントを動かすという発想はマウスから逃げるように文字が移動するJavaScriptから拝借した。

こうゆう最適化って一見面倒そうに感じますが、やってみると体感がいい感じになるので突き詰めていきたい感じです。

jQueryオブジェクトから配列に変換してくれるmakeArray

jQueryオブジェクトに複数のエレメントが格納されてて、これらをまとめた配列なんかが欲しいときに便利な関数。

lengthプロパティを持っていれば配列に変換してくれるようなので、独自なオブジェクトにも使えそう。

使い方は以下のような感じ。childrenで複数の要素を持つjQueryオブジェクトを配列に変換しています。

これ初めて使いましたw

画像がグルグル回るjQuery Plugin - jMerrygoround作りました

jMerrygoround - jQuery Plugin

仕事の一環で作ってみたのですが、使わなかったのでリニューアルして公開してみます。
普通に回るのはすでにあったりするのですが、ちょっとオモロ〜に回してみたいという方向けに作ってあります。
デモのところでいろいろ遊んでください。

この命名ははじめjSliderとかそのあたりの名前にしようかと思ったんですが、いまいちパッとこなくて、嫁さんに画像が回るのを見せながら「これ例えるなら何かな?」って聞いたら「メリーゴーランドだね!」と回答がきたので決定しましたw

追記:fukkenさんのいうカルーセルという名前もすでに結構使われてて、これは速攻でやめましたw


デモ、詳細は以下からどうぞ。
jMerrygoround - jQuery Plugin


あとキングボンビーがサイトを侵略する?jQuery Plugin - kingbonbi.js作りましたダンスっぽいことしたいと言っていたのでjMerrygoround Demo - actionMouseoverKingbonbiなんかも作ってみました。

Firefoxのリンクをクリックしたときの点線を消す方法

Twitter / 30DB30FC30E0

JavaScriptでaタグをクリックしてアニメーションさせるときとかに気になりがちな点線をCSSで消す方法です。

[via]
CSS Hacks and Issues

jQueryでマウスから逃げるRunAwayFromMouse書いてみた

untitled

マウスから逃げるFlashがかっこいいで紹介したFlashをJavaScriptで書いてみた。
マウスの移動に伴って回りの要素が逃げるように動きます。

canvasタグとdivタグの2パータンで作ってみたんですが、どちらもFlashとくらべるとかなりもっさりしちゃいますねw
Firefoxでは50個、Webkitでは100個を描画しています。
多分divタグのほうがcanvasタグより軽いです。

なのでSafariかChromeあたりでも見てもらえるとそれっぽくなると思います。

サンプル

コード

つくづく思いますが、jQuery使うとコードも少なくてすむので楽ですね〜。

マウスから逃げるFlashがかっこいい

マウスから逃げる - wonderfl build flash online

このぼやけた感じがすごいネオンぽくてすてきです。

AS?? - wonderfl build flash online

こっちのクリアな丸がなんかブドウっぽくてかわいい。


今日はこの2個のFlashを見て遊んでた。
自分でいろいろカスタマイズできるのが、このwonderflというサイトの特徴なんですが、
面白法人カヤックもなかなか良いサイト作りますな。

jQueryでサイト内リンクを使ってSmoothなScrollをする方法

追記(2009/03/30):
hashがない場合にreturnするように修正。
これがないと<a href="#">とかの場合にスクリプトエラーになるため。

サイト内リンクでアンカータグにhref="#hoge"なんて指定している場合に使えそうなscroller

これで自動でアンカータグをクリックするとアニメーションしながら目的値のところまでスクロールしてくれる。

^は初めの文字が#だった場合という意味なので、*にしてもよいかも。
もしhref="http://hoge.com/#hoge"とかの場合にはこの方法が有効。

こんなもんでいいのかな?
なんかさらにもっと簡単な方法がありそうだけど。

画像に水面の反射のような効果を付けられるReflector.js作りました

Reflector

既存であったりするんですが、自分が使いやすいように作ってみました。
以下の2パターンで画像のリフレクションを設定することができます。

reflection="true"が指定されたエレメントを一括でリフレクションさせる場合は以下のように記述してください。

エレメントを引数に渡してひとつの画像をリフレクションさせたい場合は以下のように記述してください。

詳細は以下のリンクからどうぞ。
Reflector.js - JavaScript Library

WiiリモコンからTwitterにPostしてみた

前に胎児がTwitterにPostする? - kickbeeBluetooth経由でお腹にいる赤ちゃんのキックをPostするというのを紹介したのですが、ためしにWiiのリモコンからやってみても面白いかも!ってことで試してみました。

最終的にはWiiリモコンの押したボタンをTwitterにPostするようにしてみます。

開発環境

まずは今回試した環境を以下に記載します。

OS
Mac OS X Leopard
JDK
1.5以降
BlueTooth
必須
コントローラー
任天堂Wiiリモコン

JDKが1.5以降となっているのは、今回使ったライブラリが1.5以降を必須としているためです。

どうやって通信するの?

Wiiリモコンと会話するにはBlueToothが必須になります。
そしてBlueToothから来たパケットを処理してどのボタンが押されたのか、または今どの座標にいるかなどを取得する必要がありますが、そういった基本機能はすでにライブラリとして提供されています。

なのでまずは簡単にライブラリの説明をして、その後実際にコードを書いてみたいと思います。

BlueCove - JSR082 API

JSR082 APIというのはBlueToothにアクセスする基本的なインターフェースを提供してくれます。
そしてMacやPC用に作られたオープンソースなライブラリは、「BlueCove」になります。

以下からbluecove-2.1.0.jarをダウンロードしました。
Downloads - bluecove - Google Code

WIIREMOTEJ

WiiRemoteJはMac OS XとWiiリモコンを繋ぐインターフェースを提供してくれるライブラリです。
先ほどのJSR 82を使ってWiiリモコンを探し出し、細かいプロトコルの変換なども自動で行ってくれるすぐれたライブラリです。

以下からWiiRemoteJ v1.6.zip.gzをダウンロードしました。
Index of /WiiRemoteJ

WiiリモコンとMacを繋いでみる

ボクは今回Eclipseを使って開発を行いましたのでその手順を以下に記載します。
まずは上記2つのライブラリをプロジェクトにドラッグし、ビルドパスを通しておきます。

WIIREMOTEJをダウンロードすると付属してくるファイルの中から

  • WRLImpl.java
  • Audio.au

をプロジェクトに追加します。
WRLImpl.javaはWiiリモコンとの基本的な操作が書かれたサンプルで、この中に今回使うエッセンスがぎっしり詰まっています。
またAudio.auは40秒間のサウンドクリップになりますが、JavaからWiiリモコンに音を出すときに使います。
もし音は出さなくてもよいという人はプロジェクトに含めなくても大丈夫です。

そしてWRLImpl.javaを実行してみます。

BlueCove version 2.1.0 on mac

とコンソールに表示されると思います。

このタイミングでWiiリモコンの1ボタンと2ボタンを同時押しします。
するとWiiリモコンの4つのライトが点滅しますので、コンソールを見て少し待ちます。

少しするとコンソールにいろいろ出力されますが、

java.lang.IllegalStateException: Devices are already being found! Only one "find" operation may run at once.

と表示されいっこうにスタンバイ状態にならなかったので、ハマりましたw
調べてみると海外の人で同じ現象になってる人がいました。
WiiLi.org java.lang.IllegalArgumentException: PCM values restricted by
に書いてあったのですが、

をMainメソッドの一番初めて入れればうまく動きました。

これでまた先ほどと同様にWRLImpl.javaを実行し、Wiiリモコンの1ボタンと2ボタンを押してみます。
Javaが起動してから3秒後くらいにボタンを押すとエラーになりにくくなりますが、もしうまく接続できない場合は何度か試してみてください。(なかなか一発で繋がりません・・・)

エラー内容が、

Failed to connect remote. Trying again.

の場合は一回Java側を停止さえてもう一度起動したほうが早く繋がるようになると思います。

とりあえず遊んでみる!

繋がったらWiiリモコンを振ってみたり、各ボタンを押してみるとコンソールにその情報が表示されると思います。
この時点ですげ〜感動!!

Accelerometer graph: Wii Remote

振ると画面の表示もこの画像のようになると思います。
とりあえずこれでうまく繋がりました。

TwitterにPostしてみる

先ほどのWRLImpl.javaをサンプルにして、以下のコードを書いてみました。
WiiRemoteJ.findRemote()が実際にWiiリモコンを探し出すコードです。このメソッドを呼ぶだけでWiiリモコンと繋がるなんてめちゃくちゃ便利!

addWiiRemoteListenerにリスナーをセットし、buttonInputReceivedメソッドは、ボタンを押したら呼ばれる部分になります。
なので、この部分にどのボタンを押したかをTwitterにPostする処理を入れています。
TwitterにPostする処理はTwitter4Jを使わせていただきました。

gist: 82868 - GitHub

結果:
P3:PeraPeraPrv

ほとんど自分でコードを書かなくてもこれぐらいのことができちゃうのがすごいですね。

番外編 - Wiiリモコンから音を出してみる

先ほどのAudio.au音楽ファイルを使ってWiiリモコンから音を出すサンプルです。
まぁWiiリモコンのスピーカーなので、あんまり音はでないですが、とりあえず何となく音は聞こえたのでよしとします。

gist: 82871 - GitHub

YouTubeでWiiリモコンからナイトライダーを流す動画がありました。
こんなにちゃんと音出るのかな?

Knight Rider Wii Remote

まとめ

ライブラリが充実していてほとんど自分でコードを書かなくてもこれぐらいのことができちゃうのはやっぱりすごいことですね。
動かなくて四苦八苦はしましたが、ハマるというのもこうゆう遊び感覚のコーディングの楽しいところです。

あとSourceForge.net: DarwiinRemote: Filesというアプリを使うとWiiリモコンでマウス操作ができるようになるのですが、ボクの環境なのかほとんど使いもんにならなかったですw

■参考リンク
WiiLi.org Wii Linux - JP:WiiremoteJ/Installation
WiiLi.org Wii Linux - JP:WiiremoteJ/ReadMe
JavaとWiiリモコンをBluetoothでつなげてみよう - ブログ: 岡崎 - Okazaki's blog
BlueCoveConfigProperties ( bluecove 2.1.1 -スナップショットAPI )を

JavaScriptで関数内のthisを文字列にする方法

jQuery() の挙動を解読する(29) jQuery.css() クラスメソッド upon ver1.3.2──jQuery解読(43)を読んでいて、jQueryのeachではthisが第1引数(文字列とか)になると書かれていたので実際に試してみた。

ソースコード

どうやら文字列を渡すとnew String()を行った状態で呼び出し先関数のthisにセットされるみたいですね。
そのthisと文字列結合をするとobject型からstring型へ自動でキャストしてくれます。

う~ん、今まで文字列なんて渡したことがなかったのですごい新鮮w

jQueryの場合

-webkit-transformを使ったCSSアニメーションを試してみた

Safari3.1以上で搭載されたCSSプロパティ-webkit-transformいまさらながら試してみた。
ChromeかSafari3.1以上で触ってみてください。

-webkit-transitionでアニメーションさせるCSSプロパティを指定して、例えばhoverでそのCSSプロパティの値を変更すればJavaScriptで実行しているようなアニメーションをしてくれる。

また-webkit-transform-originに50%を渡しているが、これはデフォルト50%なので特に意味はない。

translate、scale、rotateの合わせ技

透過

クリックで回転

ボーダー伸び縮み

※注意:0pxにするときにsolidがないとアニメーションしてくれない。


■関連リンク
Surfin’ Safari - Blog Archive ≫ CSS Animation
Weblog  Safari 3.1でやってみたかった3つの事
The Art of Web ~ CSS: Animation Using CSS Transforms

Twitterがクリックジャッキングを防止している方法

いつの間にかクリックジャッキングという脅威が発見されて、これはこれで恐ろしいな~と思いメモしとく。

クリックジャッキングとは、透過指定されたiframeなどの要素に標的サイトのコンテンツを読み込み、これを攻撃者サイトの要素よりも上に配置することで、Webブラウザの画面上には攻撃者サイトの要素だけを表示させ、その上でユーザーが行うクリック操作を標的サイトに対して行わせるもの。


via:
主要ブラウザすべてに影響する「クリックジャッキング」攻撃とは

なかなか巧妙だが確かにできる手法ではある。
また透過されているのでサイト訪問者は攻撃者サイトを見ていると思い込んでいるが、実は標的サイトが前面にきているのでもしボタンやテキストボックスの位置をうまいこと偽装すると容易にログイン情報などを盗み取れてしまう・・・怖い

2月にもTwitterがこの攻撃を受けて意図しない投稿をさせられてしまうという事例があったそうな。
んで、ローカルでiframeを読み込むHTMLを作成し、「http://twitter.com/home」を読み込んでみた。

一瞬普通にTwitterのホーム画面が出るが画面のレンダリングが下のほうに達すると何も表示されなくなったので何かしら対応したのだろう。

どのように対応したかは以下のソース。

攻撃者サイトがiframeで標的サイトを読み込んでいる

まずここでは標的サイトをiframeで読み込む。

標的サイト側ではwindow.top !== window.selfで不正に読み込まれたか判断している

window.top !== window.selfで自分自身がtopでない場合にinnerHTMLを空文字で上書きしている。
確かにこれならクリックジャッキングを防げそうだが、ブラウザのscriptが無効になっていると意味がない。

対応策

IE8 RC1にクリックジャッキングの問題を解決した機能が実装されているようだが、これはIE8の普及率に依存しそうだ。

FirefoxユーザーならクリックジャッキングにFirefox+NoScriptで対抗できるのか?で紹介されているNoScriptを入れて「<IFRAME>の禁止」にチェックを入れれば防げそうだ。
だたGoogle Adsenseはiframeを使って広告を出しているから、広告費で生計を立てている企業からするとこれはこれで痛そうだw

現時点ではこれぐらいしか防ぐ手立てがないようなので、信頼していないサイトでは閲覧のみにして入力するなどは控えめにしたほうがよさそうということですね。

CSS3のbox-sizingでpadding・borderをwidth、heightに含めてみる

CSS3 Basic User Interface Module

一般的にエレメントのwidthやheightはpadding・borderなどは含まないがこれを含めるかどうか指定できるのがこのbox-sizingだそうだ。

たとえばCSS3 box-sizing attribute - Helephant.comに書いてある画像を見てもらえれば分かるが、2個のfloatしているdivタグがあり一方は「width:30%」、もう一方は「width:70%」としている。
この場合は1pxでもpadding・borderなどがあると下に滑り落ちてしまうのだが、これを防ぐためにbox-sizingを使っている。

box-sizingで指定できるのは以下の値になる。

content-box
padding・borderを含めない
border-box
padding・borderを含める

ちなみにまだOpera以外のブラウザではbox-sizingと記述しても機能しない。
独自実装な-moz、-webkit、-ms-boxをプレフィックス付与して記述する必要がある。

box-sizingを使った例

box-sizingを指定しないパターンから指定したパターンで試してもらうと分かるのですが、id="div2"が下に落っこちない!
当たり前だがmarginを指定すると落っこちます。

使えるブラウザ

  • Firefox2以上
  • Safari3.1以上
  • Chrome0.2以上
  • Opera9.6以上
  • IE8以上

[via]
When can I use...

IETesterで試してみたが、一応Beta2では使えたお。

HTMLタグにカスタムな属性を追加しJSから取得する方法

HTMLタグにカスタムな属性を追加しJSから取得する方法

なんかいまさらな気もしますが備忘録として。

たとえばdojoなんかを使っていると以下のようにエレメントの属性に見たこともないのが書いてあったりする。

dojoのカスタム属性の場合

scriptタグのdjConfig、divタグのdojoTypeがそうですね。

自前のカスタム属性の場合

これを単純に自前でやってみる。

divタグにhogeという属性を書いて見ていざelem.hogeで値を表示しようと試みるがFirefoxでundefinedが返ってきてしまう。
でもIEではうまく取れた・・・

なんでだろう・・・

とりあえずFirebugで追ってみた。

まずはelemオブジェクトを見てみる。

一生懸命hogeプロパティを探してみるが見つからない。だがidプロパティは存在している。

次に属性としてちゃんと登録されているか確かめてみる。

として、attributesの中身を拝見。

item(0)
Attr nodeName=hoge nodeValue=hoge nodeType=2
item(1)
Attr nodeName=id nodeValue=hoge nodeType=2 childNodes=[1]
length
2

一部割愛したが属性の個数が2個になってる!
そして0番目にはnodeName=hogeと、hoge属性が格納されていた。

まとめ

普段あんまり気にしていなかったが、自分で追加した属性値はelem.hogeと書いても取得することができない。(Firefoxだと)
なので以下のようにして取得すること!

ちなみにjQueryを使っているなら以下のように書くからあんまり気にしないでも問題ないですね。

NodeList・HTMLCollectionを返すメソッド一覧

かなり個人的なメモですが、NodeList型や、HTMLCollection型を返すメソッドをまとめてみました。
また資料がDOM Level 1と古かったりもするので、必ずしも今のDOMレベルに合っていないかもしれません。

NodeListのメンバ

length
このプロパティは int 型である。
item(index)
このメソッドは Node を返す。index パラメータは unsigned long 型である。

HTMLCollectionのメンバ

length
このプロパティは int 型である。
item(index)
このメソッドは Node を返す。index パラメータは unsigned long 型である。
namedItem(name)
このメソッドは Node を返す。name パラメータは DOMString 型である。

NodeList型を返すメソッド

Document

getElementsByTagName(tagname)
このメソッドは NodeList を返す。tagname パラメータは DOMString 型である。

Node

childNodes
このプロパティは NodeList 型である。

Element

getElementsByTagName(name)
このメソッドは NodeList を返す。name パラメータは DOMString 型である。

HTMLDocument

getElementsByName(elementName)
このメソッドは NodeList を返す。elementName パラメータは DOMString 型である。

HTMLCollection型を返すメソッド

HTMLDocument

images
このプロパティは HTMLCollection 型である。
applets
このプロパティは HTMLCollection 型である。
links
このプロパティは HTMLCollection 型である。
forms
このプロパティは HTMLCollection 型である。
anchors
このプロパティは HTMLCollection 型である。

HTMLFormElement

elements
このプロパティは HTMLCollection 型である。

HTMLSelectElement

options
このプロパティは HTMLCollection 型である。

HTMLMapElement

areas
このプロパティは HTMLCollection 型である。

HTMLTableElement

rows
このプロパティは HTMLCollection 型である。
tBodies
このプロパティは HTMLCollection 型である。

HTMLTableSectionElement

rows
このプロパティは HTMLCollection 型である。

HTMLTableRowElement

cells
このプロパティは HTMLCollection 型である。

番外編

基本的に↑に書いたメソッドやプロパティはLiveなNodeList、HTMLCollectionになる。
ただし、以下のquerySelectorAllメソッドはStaticなNodeListが返るという仕様?(バグ?)だそうだ。

たとえば以下のようなコードを実行してもらえば分かるだろう。

Selectors API

querySelector
このプロパティは Element 型を返すので今回のとは違うな。
querySelectorAll
このメソッドは NodeList を返す。name パラメータは DOMString 型である。

querySelectorAllがliveじゃないNodeList返すのはなんで? - vantguarde - web:gでもあるようにliveじゃないStaticNodeListが返るめずらしいメソッド。

参考にした資料

付録 E: ECMAスクリプト言語バインディング

Document Object Model (Core) Level 1
Document Object Model Core Level 2
Document Object Model Core

第23回 NodeListインターフェイスを利用する
Web Kit DOM Programming Topics: JavaScriptからのドキュメントオブジェクトモデルの使用

FirebugがXMLHttpRequestを監視している方法を読んでみる

JavaScriptを使って何か物を作っている人はまず間違いなくFirebugを使っているというほどFirebugは世の中のJavaScripterに浸透しています。

alert文をひたすら書いてデバッグしていた時期が懐かしいです。(今でもalertを使うことはありますが)

そして一番楽になったといえばAjax関連の開発が昔と比べて格段に楽になりました。
これはAjaxリクエストが送信されたタイミングと応答が返ってきたタイミングでFirebugがコンソールに内容を出力してくれるからだと思います。
これ以外にもどれくらい通信速度がかかったかなども見ることができるのでとってもありがたいです。

そんなAjaxの監視をFirebugが一体どうやってやっているのかをここで紹介してみようと思います。

Firebugインストール

Firebugがまだ入っていない人はFirefoxを立ち上げてFirebugを入れてみましょう!

Firebug :: Firefox Add-ons

ソースコードの場所

ボクの環境では以下の場所にFirebugが置いてあります。

C:\Documents and Settings\hogeuser\Application Data\Mozilla\Firefox\Profiles\yrljtiye.dev\extensions\firebug@software.joehewitt.com

もうみなさんも慣れて来たと思いますが、実際のコードはこのディレクトリのcontentフォルダの中にあります。
ここにJavaScriptやらxulやらCSSなどがゴロゴロありますが、今回見るファイルはそんなに多くはないので大丈夫です!

ソースコードリーディング

ボクはこの手のソースコードを追う場合は、まずは関連しそうなキーワードでgrepしちゃいます。
たとえば今回はAjax部分の監視をしている箇所なので、おそらく「XMLHttpRequestがなんたらかんたら」みたいな部分がありそうだな~なんて。

なので「XMLHttpRequest」でgrepし、そこからソースコードリーディングを始めてみたいと思います。
grepする範囲はcontentディレクト内の全ファイルからということにしてみます。

またコードの量がそこそこ多いので、メソッドの中とかかなり端折った形で紹介していきますのでご了承ください。

net.js

XMLHttpRequestをキーワードにgrepした結果、net.jsがとってもあやしそうです。
2047行目にinstanceofでXMLHttpRequestかどうかを判断している箇所があるので、なんとなくここっぽいですね。

2047行目

では次にここのgetRequestWebProgressメソッドを呼び出している箇所に飛びましょう

どうやら同じファイルの2658行目のonModifyRequestメソッドから呼ばれているみたいです。

2658行目

onExamineResponseメソッドからも呼ばれているようですが、onModifyRequestメソッドのほうがネーミング的にとっつきやすいのでとりあえずこっちでw

ではさらにonModifyRequestメソッドを呼び出している箇所に飛びましょう

すぐ上にあるobserveというメソッドが読んでいるようです。
ここまでの時点でなんとなく見えてきましたね。

リクエストが送信されるタイミングでonModifyRequestメソッドが呼び出され、その中のgetRequestWebProgressメソッド内でXMLHttpRequestかどうかを判断しているという感じです。

ではobserveがいつ呼ばれるのかが知りたいところ。
とりあえずobserveでgrepをしてみたもののいまいち呼び出している箇所がなさそうです。

リフレクションだと見つけにくいな~なんて思っていたら、registerObserverというメソッドがあるのに気がつきました。
う~ん、登録しているのか~。あやし~い~。

ということで2609行目のregisterObserverを見てみます。

2609行目

なんとなく2種類のイベントにHttpObserverというオブジェクトを渡しているのが確認できます。
実はこのhttp-on-modify-requestというイベントが今回のキモになります。
http-on-modify-requestとは

http リクエストが作られたときに呼ばれます。通信路 (channel)
はヘッダーなどの変更などが可能です。


via: Observer Notifications - MDC

とhttpリクエストが送信されたときに呼ばれるそうです。
さらにaddObserverメソッドの第1引数には、nsIObserverインターフェースを実装したオブジェクトを渡すようにと書かれています。

[scriptable, uuid(DB242E01-E4D9-11d2-9DDE-000064657374)]
interface nsIObserver : nsISupports {
void observe( in nsISupports aSubject,
in string aTopic,
in wstring aData );
};

nsIObserver - MDC(肝心な部分が英語ですがw)
nsIObserverService - MDC

ということはリクエストが送信されたタイミングで、イベントhttp-on-modify-requestにセットされたHttpObserverオブジェクトのobserveメソッドが呼び出されるという仕組みになりますね。

やっとobserveが呼び出されるポイントがつかめました。
先に進みましょう!

次はイベントを登録していたregisterObserverメソッドを呼び出している箇所です。

grepした結果192行目で呼び出しているようです。

192行目

じゃあこのinitializeUIメソッドを呼び出している箇所はというと・・・
grepしてみても他のオブジェクトのinitializeUIメソッドは呼ばれているようなんですが、肝心なFirebug.NetMonitorのinitializeUIメソッドが呼ばれている箇所が見当たりません。

・・・

実は2804行目でFirebug.registerActivableModuleメソッドにFirebug.NetMonitorを渡しているようです。

2804行目

なんとなく見えてくるのがinitializeUIはどうやら登録しておけば勝手に呼ばれるメソッドなの?みたいな。

firebug.js

実は登録したメソッドを呼び出している箇所がfirebug.jsの224行目になります。

224行目

このメソッドの

がそれにあたります。

Firebug.registerActivableModuleメソッドで登録しておいたinitializeUIをdispatch関数がリフレクションで呼び出してくれている感じになります。

ではFirebug.initializeUIメソッドはダレが呼んでいるのかと。

chrome.js

chrome.jsの157行目に

157行目

となっているのでおそらくこの部分ですね。

ではさらにさかのぼってFirebugChrome.initializeUIを呼んでいる部分へ!

1043行目のbrowser1Loadedという関数の中にありました。

1043行目

さらに次~!

browser1Loaded関数は102行目で

102行目

ほほぅ、loadイベントですね。分かります!
これは拡張がロードされたタイミングのイベントになりますね。

さらに次~!

initializeメソッドを呼び出しているのはすぐ上のpanelBarReadyメソッドになります。

58行目

bindings.xml

最後のFirebugChrome.panelBarReadyメソッドは実はJavaScriptファイルからの呼び出してではなくbindings.xmlというbindingを定義しているファイルからになります。

id="panelBar"というbinding要素が生成されたタイミングでconstructorタグ内の処理が呼ばれます。
このときにFirebugChrome.panelBarReadyメソッドを呼び出しているということですね。


これでやっと、


FirebugにAjax通信したときに表示される仕組みが分かりました!


最後のほうはグダグダでしたが、なんとなくFirebugがXMLHttpRequest送信時にconsoleにログをはく仕組みを理解していただいたと思います。
普段使っているだけあって、こうゆうところにも注意して見てみると面白いですね。

番外編:いつも使っているエディター

ボクがつかっているエディターはPeggyというエディターでシェアウェアですが、1ヶ月のお試し期間があります。

あんまり使っている人がいないようですが、ボクにとっては最強のエディターです。
オススメな機能はプロジェクトを持てることですね。

プロジェクトを作成して、例えばFirebugのソースを一式登録しておけばいつでもプロジェクトファイルを開くだけで見ることができます。
ボクの中では軽いIDEみたいな扱いになってますw
あとスニペットもデフォルトでかなり入っていて、自分で登録も簡単にできるのでJS書くときは便利です。

「func」まで入力したら後はCtrl+/でインテリセンスみたいな。

MacのときはTextMateですね。
PeggyはWindow版のTextMateみたいな感じで使ってます。(スニペットがヤヴァ過ぎる!)

Ruby on RailsのコーディングスタイルにTextMateは最適ですが、jQueryやPrototype.jsのコーディング時にも役にたちます。

拡張的な参考記事

Firefox拡張機能(Extention)の簡単な作り方メモFirefox拡張機能(Extention)の簡単な作り方メモ Part2


続きで簡易版XMLHttpRequest監視Extentionを紹介してみます。

Continue reading

Google Visualization APIメモ

まだあんまり使ったことなくて、ちょこっと調べたのでメモメモ。

コードは以下のようにVisualization APIをloadするかたちで使用する。
そのとき使いたい表示コントロールをpackagesに渡す。

もし複数の表示コントロールを使いたい場合は以下のように配列に複数入れると可能。

サンプルコード

行をクリックすれば色が変わるし、列Titleをクリックすればソートされる。
これは便利だな~。

google.visualization.Query

を使ってAjaxクエリを発行できるが、個人的にはこのTable機能単体で使う可能性あり。
Ajaxは別の方法で取得する。

ドキュメントなどなど

本家ドキュメントはGoogle Visualization API - Google Codeより。

和訳もGoogle Visualization API - Using Visualization : Overview の和訳 その1|株式会社 フラッツで見ることができます。

こちらでGoogle Visualization APIを使ったサンプルをコード付きで見ることができます。
AJAX APIs Playground

[via]
はてなブックマーク - monjudohのブックマーク

■参考リンク
Google Visualization APIを早速使ってみた - builder by ZDNet Japan

Rails2のto_jsonで簡単にJSONを返す方法

Rails2からto_jsonというメソッドが使えるようで、Mapに対してto_jsonしてやると簡単にJSON形式で返すことができるみたい。

controller.rb

index.json.erb

index.html

結構Jsonパーサーみたいなのを作るのってしんどいからこうゆうのすごい便利!

■参考リンク
Rails2.1でSWFUploadを使うの続き。JSONでレスポンスの続き - Paradigm Shift Design

Rails2をインストールするときのメモ

rubyのバージョン:1.8.6

Railsのインストール

いつものgemを使ったインストール。

gem install rails

しかしgemが古いとかでエラーが出てしまったのでアップデート。

gem update --system

んでまた、

gem install rails

今度はエラーなし。

rails --version # Rails 2.2.2

入った!

SQLiteのインストール

Rails2.0.2からデフォルトDBがSQLiteになったようなので、SQLiteを入れる。

SQLite Download Pageにコンソール用のexeとdllをダウンロードしにいく。

ダウンロードしたdllファイルとdefファイルをパスが通ってるruby\binにコピー。
(のちのちruby ./script/dbconsoleなんかを使うならexeもコピーしとく)

これだけではSQLiteがrubyから使えないので、sqlite3-rubyをインストール・・・

gem install sqlite3-ruby

がエラーが出た。

C:\_\rails>gem install sqlite3-ruby
Building native extensions. This could take a while...
ERROR: Error installing sqlite3-ruby:
ERROR: Failed to build gem native extension.

c:/ruby/bin/ruby.exe extconf.rb install sqlite3-ruby
checking for fdatasync() in rt.lib... no
checking for sqlite3.h... no

nmake
'nmake' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。


Gem files will remain installed in c:/ruby/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4 for inspection.
Results logged to c:/ruby/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.2.4/ext/sqlite3_api/gem_make.out

調べてみたら因果律量子論 Ruby on Rails nmakeがありませんに解決策が書いてあり、

sqliteのバージョンが新しい物は、ソースインストールみたいなイメージらしくnamekeが必要らしい。
>gem install sqlite3-ruby -v 1.2.3.2.3'

これで、インストールがうまくいくみたいだ。

via: 因果律量子論 Ruby on Rails nmakeがありません

とのことなので

gem install sqlite3-ruby -v 1.2.3

で一つ前のバージョンをインストールした。

プロジェクトの作成

rails hoge -d sqlite3

-d sqlite3」でDBを指定して実行すると、database.ymlがそれ仕様になってくれる。

development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000

雛形を作成する。

ruby script/generate scaffold hoge name:string age:integer

んでマイグレーション。

rake db:migrate


以下にアクセスしておきまりの画面が出れば成功!

http://localhost:3000/hoges

■参考リンク
Rails 2.0のscaffoldを使ってみた - idesaku blog
Ruby on Railsインストールメモ - rubyco(るびこ)の日記

JavaScriptでロールオーバーアニメーション Part3

JavaScriptでロールオーバーアニメーションJavaScriptでロールオーバーアニメーション Part2に引き続きであんまり変わっていないんですが、こうゆうのも面白いかも。

今までは高さ20pxのdivタグを横にスライドさせていて、いわゆるプログレスバーっぽさがあったのですが、今回は高さ0pxにしておいて横にスライドするタイミングでじょじょに高さ20pxになるようにしてみた。

続きで動作確認。

Continue reading

JavaScriptでロールオーバーアニメーション Part2

JavaScriptでロールオーバーアニメーションに引き続きマウスオーバー時のアニメーションをJavaScirptで実装しています。


trick7 - ロールオーバー効果へのこだわり2を読んで、dajistudioさんのサイトのアニメーションで気になっていたことがすべて分かった。

たとえばいっきにマウスオーバーした場合は、すこしアニメーションが遅れる。
ただし1つ1つゆっくりとマウスオーバーするとアニメーションに遅れはない。

このレベルは使っている人はほとんど見つけられないと思うけど、なんだか心地よい感じがするのは確かだろうね。
無意識に作用するアニメーションほどかっこいいものはないっ!

なので、この遅延アニメーションをJavaScriptで実装しました。
たぶんタイマーを使っているんじゃないのかな?本家のほうは。

JavaScriptソースコード

jQueryのdataメソッドを使って、マウスオーバーのアニメーションが終わっているのかどうかのフラグ判定しています。
これにより、マウスオーバー直後にマウスアウトしてもアニメーションは終わっていないので、このタイミングで遅延アニメーションを実行します。

続きで動作確認。

Continue reading

JavaScriptでロールオーバーアニメーション

trick7 - ロールオーバー効果へのこだわりを見て、うわ~最後のほうをTweenさせるだけでこんなに気持ちいのかとJavaScript版を作ってみました。

しかし、やっぱりFlashJavaScriptの違い顕著に出てしまったのですがそれっぽくなったと思います。

JavaScriptソースコード

2つのdiv要素を用意しておいて、1つ目の要素にマウスが乗ったときに2つ目の要素をアニメーションさせています。
1つ目の要素を覆うように2つ目の要素が重なるので、そのタイミングでmouseoverが発生してしまうためz-indexでアニメーションする要素を後ろ側に隠しています。

それとanimateメソッドでwidth:0pxからアニメーションするのではなく、いったんcssメソッドを使ってwidth:200pxまで進めておいて、最後の50pxをアニメーションするようにしています。
このひと手間でオモロ~になりました。

続きで動作確認。

Continue reading

カラフルな要素があっちいったりこっちいったり - xyz.js

ちまたで有名なWonderfl Build Flash Onlineをダラ見してたら、これまた面白いFlashを見つけてしまったのでJavaScriptでソレっぽく再現してみました。

↓これがそのFlash。イカス!
code on 2008-12-23 | Wonderfl Build Flash Online
何個かfoakされているので、他の方のを見てみても面白いです。

ただFlashでできることがJavaScriptでできなかったりもするので完璧に再現はしていませんが、一応それっぽく。
JavaScriptでRotationが使えたら要素をグルグル回せるんですがね。

初めcanvasのrotateを使おうかと思ったのですが、座標の記憶とかtranslateとかややこしそうだったので断念・・・

JavaScriptソースコード

実際のActionScriptで使われているTweenerライブラリの部分はjQueryのanimeteメソッド、easing部分はjquery.easingプラグインを使って補いました。

続きで動作確認できます。

Continue reading

マウスから逃げるように文字が移動するJavaScript

monstropolis.org -- intro10

ここ最近画像を動かすことばかりにハマっていたので、こうゆう文字を移動させるのはすごい新鮮でした。

こまかくspanタグで分割された文字がまるでマウスから逃げるように移動するのがとってもかっこいい。
なんかすごい作りたくなったきたw

コードを見てみると、やっぱり複雑な計算が入っててどうしてもこっちが苦手なんだけど、最近Flexに夢中だからどうしてもさけて通れないんだよね〜。

慣れかな?

monstropolis.org -- intro10

IEではbuttonタグのvalueが取れない

2 IEで<button>のvalueを.val()経由で取得できない


IEでは<button value="value">text</button>の内、value="value"の値を$(this).val()経由で取得することができません。


ただ、これはFirefoxでは正常に取得できるため、IEでは通常のDOM経由でも取得できないのかもしれません。


via: jQueryを使うときに気をつけるべき8のポイント : tech.kayac.com - KAYAC engineers' blog

おお~、なんか懐かしいと思ってちょい実験。
buttonタグっていろいろと問題テンコ盛りですよね。

前に記事にしたIEとFirefoxでテキストボックス上でのEnterの挙動についてでもSubmitするときの情報が変動しちゃうし…

サンプルコード

value経由でもgetAttribute("value")でもやっぱりIEではダメでした。

とりあえずW3C見に行ってみたら。
ほ~ら、ちゃんとvalueってあるじゃ~ん。んもうIE。

<!ELEMENT BUTTON - -
(%flow;)* -(A|%formctrl;|FORM|FIELDSET)
-- push button -->
<!ATTLIST BUTTON
%attrs; -- %coreattrs, %i18n, %events --
name CDATA #IMPLIED
value CDATA #IMPLIED -- sent to server when submitted --
type (button|submit|reset) submit -- for use as form button --
disabled (disabled) #IMPLIED -- unavailable in this context --
tabindex NUMBER #IMPLIED -- position in tabbing order --
accesskey %Character; #IMPLIED -- accessibility key character --
onfocus %Script; #IMPLIED -- the element got the focus --
onblur %Script; #IMPLIED -- the element lost the focus --
>
Forms in HTML documents

jQueryを見に行ってみる

とりあえずjQueryで取れないという話だったので、見に行ってみた。
valメソッドは359行目あたりにあります。

おそろしいほど端折りましたが、大体↑の感じ。
やっぱり普通にvalueを返しているんですね。

buttonタグ恐ろしや…

[via]
jQueryを使うときに気をつけるべき8のポイント : tech.kayac.com - KAYAC engineers' blog

Firefox拡張機能(Extention)の簡単な作り方メモ

Firefoxの拡張はJavaScript、CSS、XMLを使うことにより自作することができるのですが、意外と敷居が高くそこまでドキュメントなんかも豊富ではないので、自分用のメモとして簡単な作り方レシピを残してみようと思います。

開発用のプロファイルを作成する

既存のプロファイルで開発してもいいのですが、いろいろ設定をいじることになるのでここでは開発用のプロファイルを作成しています。

  1. Firefoxを閉じる
  2. ファイル名を指定して実行から「firefox -ProfileManager」で起動する
  3. 適当な名前(ここではdev)でプロファイルを作成する
  4. ファイル名を指定して実行から「firefox -no-remote -P dev」で起動する

これで新しい環境でFirefoxがしたと思います。

開発用に設定値を変更する

Firefoxのアドレスバーにabout:configを打ち込んで、以下の4つの値をtrueにします。

  • javascript.options.showInConsole
    • JavaScriptのエラーをエラーコンソールに出力する
  • javascript.options.strict
    • JavaScriptのエラーを厳密にする
  • browser.dom.window.dump.enabled
    • dump関数によってコンソール(Windowsの場合,コマンドプロンプト)へ文字列を出力可能にする
  • nglayout.debug.disable_xul_cache
    • XULのキャッシュを無効にする

■参考記事
Firefox 3ではじめる拡張機能開発:第1回 最小構成でインストール|gihyo.jp … 技術評論社

んでボクの環境では下の2つがなかったので、
C:\Documents and Settings\user\Application Data\Mozilla\Firefox\Profiles\hogehoge.devにあるprefs.jsに以下を直接設定しました。

これでコードを修正するたびにFirefoxを再起動しなくて済みます。

作業ディレクトリを作成する

Firefoxは通常xpiファイルとして配布されますが、コードを修正するたびにxpiファイルにしてFirefoxにドラッグするとなると、
これは相当な面倒になるので、Firefoxには他の場所にあるソースコードをリンクとして読み込むように設定します。

今回は、

C:\_\firefox\hello ←ここが作業ディレクトリ

のようにフォルダを作成して、Firefoxからこのフォルダを見てもらうようにします。

リンクファイルを作成する

先ほどFirefoxにはソースコードのリンクを指定すると説明しましたが、普通Firefoxの拡張は

「C:\Documents and Settings\user\Application Data\Mozilla\Firefox\Profiles\hogehoge.dev\extensions」

のような場所に存在します。
ここにリンクを作成する感じです。

まずはこのディレクトリ内に「hello@xuldev.org」というファイルを作成しましょう。
そしてファイルの中身に

C:\_\firefox\hello

と書いて、先ほどのディレクトリへのリンクファイルを作成します。
これでhelloディレクトリ内にあるソースコードが読み込まれる感じになります。

クロムマニフェスト(chrome.manifest)の作成

chrome.manifestファイルをhelloディレクトの直下に作成し、以下を記述します。

content hello content/
overlay chrome://browser/content/browser.xul chrome://hello/content/hello.xul

chromeパッケージ名とソースファイルの相対パス指定します。
ここのoverlay宣言ですが、これはFirefoxの画面情報としてで読み込まれるchrome://browser/content/browser.xulに対して
chrome://hello/content/hello.xulも追加してちょみたいな感じです。
これにより自分で追加したメニューなどが表示されることになります。

install.rdfの作成

helloディレクトリ直下にinstall.rdfファイルを作成し、以下を記述します。
ここは作る拡張の情報が記載されているファイルになります。

拡張のバージョンや対応しているFirefoxのバージョンなどを記述します。

以下重要なエレメントだけ説明。

em:id
メアド形式かUUIDで指定します。ここは一意にならなくてはなりません
em:version
拡張機能のバージョン
em:type
2:拡張機能、4:テーマ、8:ロケール、16:プラグイン、などなど
em:optionsURL
メニューのアドオン→設定ボタンを押せるようになります

■参考リンク
Install Manifests - MDC

自作xulを作成する前の事前準備

事前準備としてhelloディレクトリ直下にcontentフォルダを作成しときます。
現状前の構成は、

「C:\_\firefox\hello」ディレクトリの直下に

・contentフォルダ
・chrome.manifestファイル
・install.rdfファイル

がある感じです。

hello.xulの作成

contentディレクトリの直下にhello.xmlxulファイルを作成し、以下を記述します。

ここが実際の拡張に対するxulコードになります。
xml形式でボタンやラベルなどを配置できるので、htmlの知識がある人ならピンとくるはずです。
特にイベント登録でonmousedownを使っているのでまさにJavaScriptですね。

ここで重要なのがstatusbarというタグにid="status-bar"を指定していますが、これは適当につけているわけではなく
すでにchrome://browser/content/browser.xulで定義されているid="status-bar"のstatusbarタグに対するオーバーレイになります。
なので、このid指定を間違えるとステータスバーに表示されなくなってしまうので気をつけてください。

どうゆうidが指定されているかの調査方法は↓のほうに書きます。

hello.jsの作成

↑のxmlのscriptタグで外部jsファイルを読み込んでいるので、それを作成します。
contentディレクトリの直下にhello.jsファイルを作成し、以下を記述します。

単にalertを実行しているだけなので、onmousedown='Hello.alert("Hello")'としちゃってもいいのですが、
ここはサンプルなのであえてそうしてます。

またHelloオブジェクトを作成して、その中にalert関数を入れていますが、ここで読み込まれるjsファイルは
グローバルな環境になってしまうので、すでにありそうな名前のオブジェクトを作ってしまうと他の拡張が動かない場合があります。
(Helloも微妙にあぶないですが…w)

なので、拡張に見合った名前のオブジェクトを作成してその中に関数を追加していくようにしましょう!

アドオン→設定ボタンを押せるようにする

contentディレクトリの直下にprefs.xulファイルを作成し、以下を記述します。
常にデフォルトな設定が読み込まれる拡張なら良いのですが、ユーザーに設定値を選ばせる拡張なら設定ボタンを押せる必要があります。

とりあえずラジオボタンで選べるように作ってみましょう。
preferencesタグのidとradiogroupタグのpreferenceは一致するように指定してください。
ここが間違っているとエラーになってしまいます。

現時点では設定ボタンが押せる状態になるだけですが、後で取得する方法を説明します。

Firefxoを起動してみる

ではとりあえずFirefoxを起動してみましょう!
ちゃんと拡張が読み込まれれば、アドオンを追加したときのウィンドウが表示されると思います。

もしアドオンのウィンドウにビックリマークがある場合はどこかの指定が間違っていることになります。

設定で指定した条件を取得する

Firefox起動のテストがOKなら、次に設定で指定したラジオボタンの情報を取得してみましょう。
まずはhello.xulのonmousedown='Hello.alert("hello")'をonmousedown='Hello.alert()'と引数なしにします。

続いてhello.jsを以下のように変更します。

JavaScriptからXPCOMを利用するには,XPConnectという技術を使います。
XPCOMとはFirefox側で提供している機能をまとめたフレームワークになります。
今回は設定画面で設定した内容を取得するので、XPCOM経由で取得する感じです。

またデフォルト値を設定しておく必要があるので、
helloディレクトリの直下にdefaultsフォルダpreferencesフォルダhello-prefs.jsファイルを作成しときます。

その中に以下のコードを記述してください

これをしとかないと、ユーザーが設定画面でOKを押さない限りthis.getPref("hello", "extensions.hello.")の戻り値が
undefinedになってしまいます。

再テストしてみる

基本的にソースコードを修正したら、Ctrl + Nなどで新しいウィンドウを開けば再読み込みされます。
ですが、install.rdfを修正した場合はそれだけではダメなので、一旦Firefox上で拡張を削除してから
もう一度hello@xuldev.orgファイルをドラッグしてあげましょう。


設定画面で選んだ値がalert表示されたでしょうか?(0 or 1)
よっしゃ~~~!

番外編 - browser.xul内のidを特定する方法

オーバーレイのところでもお話しましたが、オーバーレイ対象のidが分からないとxulを書くことができないので
そのidを探す方法を書いてみようと思います。

以下のをアドレスバーに入力してみてください。

chrome://browser/content/browser.xul

Firefoxの中にFirefoxが表示されると思いますw(なんかすごい)

そしたらFirebugを開いてインスペクター(調査)で目的の箇所をクリックすればそこのxul情報が見れるので、
これでidも特定できますね。

Firebug以外にもDOMInspectorでも同じことができるみたいです。

番外編 - デバッグ方法

デバッグをする方法はボクが知る限り3つあります。

・1つ目はalert表示させるパターンですが、これは普通のJSのデバッグでも有用ですが、
for文とかで回している中でalertするとループのたびにポンッと表示されるのでちょっとうざいです。

alert - MDC

・2つ目はdumpを使う方法ですが、これは試したことがないですw
Firefoxを起動時に「-console」を付けたりしないといけないので、これもまたちょっと面倒です。

dump - MDC

・3つ目はエラーコンソールに出力させる方法です
ボクはこれを良く使います。

ただし、この書き方はFirefox3かららしいです。
今まではXPCOM経由でログを吐かなければならなかったようで、実際には以下のコードになります。

こうゆう関数を一個作ってしまえば問題ないのですが、毎回書くのは難点ですね。
しかもlogという名前の関数だと他の拡張とバッティングしそうなので、もう少し工夫する必要もありますしね。

まとめ

ここまでのことが一通りできたら、他にいろいろ応用できそうですね。
ブロガーなら自分の使いやすいようなcopy+の作成や、Firebugに機能の追加なんかもできちゃいます。

ちょっと面倒ではありますが、作ると楽しいFirefox拡張をどんどん作っちゃいましょう!

Part2へ続く。
Firefox拡張機能(Extention)の簡単な作り方メモ Part2

参考リンク

XUL Reference - MDC
XUL Apps > Tips > prefs.js に設定を保存する・設定を読み込む - outsider reflex
Firefox拡張機能(extension)の作り方 ― ありえるえりあ
FireFox Extensionの作り方

Prototypejsのdom:loadedを検証(IEの場合)

いまさらながらPrototype.jsのdom:loadedがIEでDOMContentLoaded的な扱いになるか試してみた。
普通に使わせてもらっているから、ちゃんと動いているんだろうけど何せ擬似なDOMContentLoadedですからね。

Prototype.jsでは3960行目あたりからdom:loadedの部分になります。
んで、IE版のところは3988行目から。

こんな感じです。

scriptタグを生成して、ロードが完了したタイミングでセットされた関数をfireしています。
ここでscriptタグにはdefer属性が指定されているので、このscriptタグの中にはdocument.writeがないことを条件にしています。
つまり、この部分を遅延評価してね~という感じですね。

この遅延のタイミングがDomContentLoadedと同じ?とみなしているようです。

順番としては、

  1. ブラウザがHTMLを上から順番に評価し始める
  2. JavaScriptからscriptタグが追加されるが、defer属性が入っているのですぐに実行しない
  3. 画面全体のDomが構築される
  4. defer属性が付いていたscriptタグの中身が評価される
  5. よってこのタイミングがDom構築完了を意味する

ほんと?w
いやちゃんと動作するんだからそうなんでしょう。
defer属性をこうゆう風に使うなんて、なんかとっても面白いですね。

サンプルコード

少し重めの画像を適当に用意して、さきほどの擬似DomContentLoadedとwindow.onloadの中でalertを表示されています。
これでどっちが先に呼ばれるかが重要ですね。

結果はちゃんと「dom:loaded」→「onload」の順番でした。
ただし、上の画像がない場合など比較的HTML要素が少ない場合ではonloadのほうがdom:loadedより速かったです。
なので画像を使わないテキストサイトとかだとdom:loadedを待つよりonloadを使ったほうがよさそうですね。

ちなみにjQueryのIE版DomContentLoadedは

以下のように、document.documentElement.doScroll("left")が正常に動くまで実行しています。
これを考えた人は本当にすごいですね。
IEContentLoaded - An alternative for DOMContenloaded on Internet Explorer

なぜ、document.documentElement.doScroll("left")でExceptionが発生しないとDomContentLoadedだと思ったんでしょう。

補足

IEscript要素にdefer属性をつけるとinnerHTMLに代入したscriptが実行されるという仕様がある。


via: script要素のdefer属性の実装 - Thousand Years

なんてこともあるみたいです。

FirebugのmonitorEventsでイベント丸見え

いやはやこれは便利だ。
ここ最近全然使っていなかったが、あらためて使うと便利さが理解できる。

サンプル

で特定のエレメントのクリックイベントを監視。

で特定のエレメントのイベント全部を監視。

NodeList[0]とNodeList.item(0)では戻り値が違う

getElementsByTagNameとかで取得したNodeListから参照したいエレメントを削除して、それから中身を見ようとした場合elems.item(0)とelems[0]では戻り値が違う。
まぁ当たり前といっちゃ当たり前かもしれない。

item(0)は関数で指定したノードがない場合にnullを返す、[0]は直接NodeListを見に行ってそこに定義がないからundefinedかな。

とはいっても、

これはちゃんと通るから、大丈夫かな。

このほうが無難かも。

一応DOMの規定では配列のようにアクセスしても、item関数経由でアクセスしてもいいみたいです。

NodeListをforinするとわ~お

ちなみにNodeListをforinとかで回すとえらいことになる可能性があるので、注意が必要です。

これだと欲しいエレメントのpタグ以外に

  • length
  • item()
  • namedItem()

が取れちゃうから。
なので、普通にfor文で回したほうがよいですね。

高速化するなら

NodeListやHTMLCollectionに直接アクセスするより、一旦静的な配列にしたほうが速い - 素人がプログラミングを勉強するブログ

一旦配列に突っ込んだほうが速いようです。
意外や意外!

ブラウザごとのJavaScriptアニメーション比較

ここ最近JavaScriptでアニメーションする機会が結構増えてきたのですが、やっぱりブラウザによって速度というか動きがかなり違うので、その比較をメモメモ。

IE6.0

IE6.0は以外にもアニメーション処理は速いというか滑らかです。

前にもJavaScriptでアニメーション(animate)するときに気をつけたいことで紹介しましたが、中に画像がたくさんあるdivタグmargin-leftとかでアニメーションすると激重になる可能性があるので注意が必要です。

position:absoluteでのアニメーションはかなり調子良いです。

IE7.0

比較的問題がないブラウザです。

marginを使ったアニメーションにも強いですし、opacityを使って透過してフェードアウトとかにも強いです。
IE7.0は重い重いという話が良くありますが、アニメーションに限ってはなかなか出来るやつですw

Firefox2.0

これが一番曲者かと。

アニメーションする際に対象のdivタグがoverflow:autoになっていると、すごいチラ付きが発生しますし、アニメーション処理自体にもモッサリ感があります。

このoverflowの話は結構面倒で、今まではIEとIE以外のJSコードを分ける処理は結構書いていましたが、Firefoxの場合にもoverflowをhiddenにしたりautoにしたりと独自実装になる感じです。

Firefox3.0

Firefox2.0と比べるとまぁ良いのですが、タブをいっぱい開いていたりFirefoxのメモリ使用量が多いとアニメーション時にもたつく感じがあります。(これはFirefox2.0も同じです)

こちらもoverflowは対策が必要です。

Opera9

Operaのアニメーションはとてもきれいです。 margin、positionとも滑らかにアニメーションします。

ただLightBox風のJSを作る場合に、レイヤーを貼った上にボックスを表示してその表示方法がアニメーションのときにはちょっと注意が必要です。

input type="button"を押したらボックスを表示するとして、レイヤーが表示され始めているのにレイヤーの後ろにいるbuttonを押せてしまう場合があります。

つまりレイヤーが表示されたタイミングでbuttonのonclickをfunction(){}(つまり空)にしてやるとか、それ以外でフラグを使ってすでに押されていることを把握する必要があります。
(※これは画像ボタンにすることで解消されるかも?未検証)

Safari3.1

完璧なブラウザです。

特にアニメーションに限っては文句の付けようがない感じです。
Safariの欠点は、Safariでは画像のloadが終わっていないとwidth、heightがうまく取得できないでも紹介しましたが、jQueryのreadyではDOM構築が終わっていない場合があるので、アニメーションさせたい対象のエレメントの幅を取得したい場合はonloadを待つほうが無難かもしれません。

Google Chrome

Safariと同じWebkitベースのブラウザなので、同じくキレイです。

ただ、ちょっと未確認なんですがJSファイルをBOMありのUTF-8で保存した場合に、うまくJSファイルを読み込んでくれなかったです。

他のブラウザでは問題なかったのですが、Google Chromeだけで発生しました。
対応としては、BOMなしのUTF-8Nとかで保存しました。
う~ん。

Netscape7

アニメーションはFirefox2.0よりは滑らかに感じますが、やはりちょっと微妙です。

各ライブラリがNetspaceに対応していないのもあり、opacityの透過などは自前で容易する必要もあったりします。
一応Netscapeではfloatしているブロックにrelativeをかけても効かないでちょっとした欠点も載せているので参考にしてください。

これ以外にアニメーションと関係ないですが、CSSで
background: url(/hogehoge.gif) no-repeat left 7px;
みたいにピクセル単位で座標を指定する場合がありますが、これにはNetscapeは対応していません。
いろいろ試してはみたのですが、ダメでした。
なので、
background: url(/hogehoge.gif) no-repeat left center;
などで対応。

まとめ

全ブラウザで同じように見せるスタイルシートも大変な作業ですが、JavaScriptを使ったアニメーションもブラウザの個性に対応しないといけないので、まだまだクロスブラウザ対応は必要そうですね。

Ajaxのオブジェクト(XMLHttpRequest or Msxml2.XMLHTTP)や基本的なDOM操作はライブラリが吸収してくれますが、アニメーションに限ってはどのスタイルを使ってアニメーションをするかは自分で決めなきゃいけないので、これからいろいろ調べていきたいと思います。

とはいってもjQueryのanimateメソッドにはすっごく助けられていますがw

■参考記事
jQueryのanimateメソッドの使い方
JavaScriptでアニメーション(animate)するときに気をつけたいこと

Netscapeではfloatしているブロックにrelativeをかけても効かない

ネスケのクロスブラウザ対応なので、あんまり必要はないかもしれないですが、
一応こんな現象を発見したのでメモメモ。

以下のように外枠のブロックに「float: right;」と「position: relative;」が掛かっている状態で、
中にいるブロックに「position: absolute;」で絶対配置にしています。

こうゆう例はちょっと珍しいですが、中にいるブロックが複数あってz-indexで切り替えるときとか
こんな感じかと思います。


んで、上の例だとネスケではrelativeが効かず、画面の左端に中のブロックが移動してしまいます。

これを解消するには「float」と「position」を別々のブロックにしてあげるとうまくいきます。

解決策

何かと何かを一緒のブロックに指定するとうまくいかないケースはIEだけかと思っていましたが、
以外にもネスケでこうゆうパターンがありました。

参考までに!

onloadを待たずに特定のエレメントに処理を実行する方法

ちょっとonloadを待たずに処理するのはどうやろう・・・みたいな疑問が沸いたのでメモメモ。

onloadイベントはwindowオブジェクトやimgタグ、scriptタグなど特定のものにしか存在しないので、擬似的に対象エレメントのDOM構築が終わったかどうかの判定ができません。
onload

なのでタイマーを使ってエレメントが取得できるまで繰り返し、その後に処理を実行するという方法ならDOM構築完了時に処理が実行できそうです。

たとえば上記のようなエレメントがあって、ここからid="hoge"のinnerHTMLをonloadイベントを待たずに取得したい場合は
以下のように書く感じです。

特定エレメントのidプロパティが取得できたらDOM構築が完了と考えていますが、もしかしたらこれだけだと判定としては弱いかもしれません。
ここは要調査!

画面の高さが結構ある画面なんかで画面初期でselectboxをdisabledにしたい~というときにonloadを待っているとかなり時間が経った後にdisabledになるので、こうゆう方法もありかもしれません。
DomContentLoadedでもそこそこ時間がかかるはずっ。

※divタグ自身にonloadがあったらな~。

jQuery Pluginの書き方

※10/14 もう少し詳しく書いてみる!

jQueryのプラグインなんかを書き始めると、どうゆう風に記述するかいろいろ人によって違うのでちょいとまとめてみました。
おそらくこれ以外にもありそうですが、比較的メジャーな感じで並べています。

jQueryには
  1. ①$("#hoge")で取得するオブジェクト
  2. ②jQueryオブジェクトそのもの

と2つのオブジェクトが存在します。
違いは①のほうは「$("#hoge").hogehoge();」という感じで書くことができ、②のほうは「jQuery.hogehoge();」とちょっとしたユーティリティのように書けます。
メソッドが実行されるタイミングで対象のエレメントが特定されてて欲しいなら①、そうでないなら②みたいにボクは使っています。

これを踏まえて以下のコードはjQueryオブジェクトにそのまま追加するパターンとして紹介しています。
もし①で使えるように追加するなら「$.fn.hoge」というようにfnを途中に追加してください。

一般的な書き方

よく見るコードはこの書き方かと思います。
関数の中では$で記述できるので比較的楽です。

ちょっと普通な書き方

これは1番目とあんまり大差はないですが、これも$で書けるのでまぁ楽チン!

jQueryオブジェクトをそのまま使う書き方

これは毎回jQueryドットと書かないといけないので、ちょっと面倒。
やっぱり1番目のほうがスマートですかね。

関数スコープに閉じ込めない書き方(これは良くない)

う~ん、これはjQueryっぽさがなくなっちゃうし、関数の外で書いた変数はスコープグローバルになっちゃうし・・・
バッドノウハウですねw


あと肝心なもう一個を記述し忘れてましたw

extendを使う書き方


以下jQueryの解説スライド。
こうゆうのをちょっと覗いてみるのも面白いですよ!

UTF-7でスクリプトを実行させるXSSについて

IEでUTF-7なスクリプトをiframeの中に表示するとXSSが発生するメモです。
あんまりこの話には詳しくないので、今後の調査材料として残しときます。
(※一応悪用厳禁であります!)

iframe内のエンコードが正しく指定されていない場合は、そのiframeの親にあたる部分のエンコードが自動的に適用されるというIEのバグがあるみたい。
今回はそれのちょこっとした検証!

1番初めに呼ばれるhtml(①.html)

iframe内で呼ばれるGetメソッド

結果

doGetメソッド内でエンコードを正しく設定せずにレスポンスしているため、IEでalertが表示される。

その他の実験まとめ

  1. 「①.html」ではなくiframeのパスを直接呼んだ場合はscriptは実行されない
  2. 「①.html」にmetaタグを正しく指定すればscriptは実行されない
    <meta http-equiv='content-type' content='text/html;charset=utf-8'>
    ただしutf-7を指定した場合はscriptは実行される(まぁそうだろうな)
    <meta http-equiv='content-type' content='text/html;charset=utf-7'>
  3. サーバー側でエンコード指定してもIEが解釈できないエンコードの場合はscript発生
    arg1.setContentType("text/html");
    arg1.setCharacterEncoding("utf8");	//正しくはutf-8
    
  4. 当たり前だがiframe内のhtmlに正しくmetaタグを指定すればscriptは実行されない

このお話はなかなか奥が深くてむずかしいですね。
とにかくIEに依存した Webアプリケーション セキュリティのプレゼン資料を見て勉強するしかなかそうです!


■参考にさせていた資料
IEに依存した Webアプリケーション セキュリティ
そろそろ UTF-7 について一言いっとくか - 葉っぱ日記
まだまだあるクロスサイト・スクリプティング攻撃法:ITpro
36. UTF-7とクロスサイト・スクリプティング:ITpro

(function(){})()の代わりにnew function(){}って方法もあるよ

だいたいは①の方法で即時実行な無名関数を作ると思うんですが、②みたいに書くこともできる。
でもボクはやっぱり①の書き方のほうが好きだな〜。

ただし、②の使い方にはちょっと気をつけないといけないです。
というのも②はfunctionをnewしちゃっているので、この関数はコンストラクタになってしまうこと。
なので以下のようにその関数が属するオブジェクトが変化してしまします。

もうちょい分かりやすく書くと以下の感じ。

func2のほうはnewした段階でコンストラクタが呼び出されるので、thisが代入先のobjに切り替わる。

ということでやはりnew function(){}よりも(function(){})()のほうが無難そうですねw
jQueryなんかもコード全体を(function(){})()で囲って、スコープを関数内に閉じ込めたりしてるし。(理由になってない!)

canvasを使って波紋が広がるripple.js作りました

ripple

canvas使って何かしたいな〜と思っていたら、波紋を描いたらちょっと面白いかもと思ってこんなJavaScript作ってみました。
あんまり深いこと考えてないですw

マウスの移動に波紋が付いてきます。
またクリックすると少し大きい波紋が広がります。

一応コードは以下の感じ。
canvasを使って丸を描いてます。(すごいシンプルっ!w)

またイベントのセットは以下のようにmousemoveclickに割り当ててます。
すいません、今手元にIEがないのでIEのチェックだけ出来ていないです。多分以下のコードで動くような〜。

Eventが発生するたびにマウスの座標をRippleクラスに渡しています。その後drawメソッドで描画しています。

とりあえず触ってみてください。
ripple.jsを触ってみる

ちょっと気に入っているのはこういったアニメーションするときに少し描画を遅らせるとそれっぽくなる気がします。
なので、マウスを移動したときに少し遅れて波紋が付いてくると思います。
こうゆうの結構好きです。

ソースは以下からダウンロードできます。
ripple.js


他にもこんなん作ってます。どうぞよろピク。
キングボンビーがサイトを侵略する?jQuery Plugin - kingbonbi.js作りました
なんかものが落ちるjQuery Plugin - JDropper作りました

Chromeのユーザーエージェント

一応メモ。
Webkitやね〜。

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.X.Y.Z Safari/525.13

[via]
CyberAgent SEO Information

WebkitのDOMContentLoadedはDOM構築が完了していないかもしれない

Safari3.1でDOM構築が終わったタイミングでイベントを登録していたのですが、うまくいかなかったときのお話です。
jQueryを使っていたので自動的にDOMContentLoadedイベントに登録されると思っているのですが、これがどうもDOM構築が終わっていないんじゃないかと。

それが判明したのが、画像をスライドするパーツを製作していたときにスライド対象のdivタグのwidthを取得していて、このwidthがなぜかSafari3.1だと小さく取得されました。

以下にその例を載せて起きます。

SafariのDOMContentLoadedで失敗したパターン

画像がたくさん並んだボックスを左や右へスライドさせるときに、何枚あるか分からなかったので画像が入っているボックスのwidthを取得して計算をしていました。
以下にサンプルのHTMLを載せています。

このページの全体の高さは2500pxほどあります。ちょっと縦長なページ。
わけあってdivが2階層いますが、スライドさせる対象のエレメントはulタグになります。
このulのmargin-leftやmargin-rightを変更することによって画像がスライドしているように見せる感じで作っていました。

んで画面のDOM構築が終わった段階で、ulタグの幅を取得しようとしたのですが、なぜかSafari3.1でだけwidthが少なかったのです。
たとえばFirefox3では1000pxあったのに、Safari3.1では650pxとか。
かなり中途半端なwidthが取れていたので、これはもしやDOM構築終わってないんじゃ?
と思ってwindow.onloadにfunctionをセットしてみたところ・・・


「Safari3.1でもwidthが1000pxで取得できました。が~~~ん」

jQueryのreadyの中身について

久々にjQueryのreadyの部分を追ってみました。
bindReadyというメソッドが2329行目あたりにあります。
その中に以下の記述があるのですが、これは「webkit nightlies currently support this event」とコメントされているとおりSafari3.1ではDOMContentLoadedがあるのでif文に入ります。
参考リンク:Changeset 26101 -- WebKit -- Trac

そしてこのDOMContentLoadedを登録しつつ、その先に進みます。
2366行目あたり。

ここでSafariの場合に2つの方法を使ってDOMContentがLoadedになったかを確認しています

まずdocument.redayStateがloadedかcompleteになるまで自分自身の関数をループします。
ここのチェックが終わったらstyleタグとlinkタグの合計数とdocument.stylesheets.lengthが一致するまで繰り返します。

これら2つの条件をクリアしたらやっとDOMContentがLoadedになった状態とみなすようです。
なかなか複雑ですねw

ここでちょっと気になるのですが、Safari3.1では「DOMContentLoaded」がありますが、その後の「if ( jQuery.browser.safari ) {」にも入ってしまうのです。
なので2重のほうほうでDOM構築を待つ感じになっています。どっちのほうが速いの?w

ちょろっと簡単にテストしてみました

上記のコードを実行した場合の挙動が少しへんでした。
まずDOMContentLoadedでjQuery.readyが登録され、その後のSafariの分岐でdocument.readyStateの状態を監視します。
するとdocument.readyStateのif文には約1回くらいしか入らず、その下にあるif文には一切入りませんでした。

順番にしてみました。

  1. DOMContentLoadedにjQuery.readyを登録
  2. Safariの場合にdocument.readyStateを監視
  3. DOMContentLoadedイベント発生でjQuery.isReadyがtrueになる
  4. document.readyStateを監視しているがjQuery.isReadyがtrueなのでループを抜ける
  5. だからdocument.stylesheetsのlengthチェックが走らない

う~~~ん・・・
だとするとSafariのDOMContentLoadedのほうがjQueryのDOM構築待ちより速いということでしょうか。
速い故にまだ構築し終わってない?w
まさかね!

まとめ

かなりイレギュラーなパターンだと思いますが、Safariでこういう現象があったのは確かです。
なのでwindow.onloadを待つか、documentのDOMContentLoadedを待つかはテストしながら判断したほうがよいかもしれません。

Firefox3.0やIE7、IE6では特に問題がなかったです。
SafariのDOM構築って少しくせがあるので、そこが悩みどころですね。
レンダリング超速いですが・・・

JavaScriptで単体テストをするならQUnitはいかが?

「JavaScriptのテストってわざわざXUnit系を使ってまでする必要はない!」
みたいな意見は多々あるのですが、ライブラリなどを作っているときには非常に便利だったりします。
ちょこっとした修正がどの程度影響があるか分からないときに、テスト用のコードをしっかり書いてあればそれを実行するだけですんでしまいますからね。

そんで最近になって
JavaScript--単体テスト環境の選択肢 - builder by ZDNet Japan
という記事を見てて、「あれ?Qunitがないぞ!」と思ったので簡単に使い方を書いてみたいと思います。

上記リンクの記事ではJsUnitRhinoUnitのことが書かれていますが、これらはJavaありきというかANTありきなので、ちょろっとテストコードを書くというスタンスにはなかなか難しいと感じています。
ただJsUnitは全ブラウザを登録しておけば、いっきにクロスブラウザのテストを実行してくれるので便利といえば便利なんですけどね。

その点QUnitはjQuery用のテスティングフレームワークなので、コード量も少なく簡単にテストコードを書いていけます。
(少しだけjQueryに関する知識が必要になってきちゃうのはご愛嬌)

jQueryを使ったテスティングフレームワークですが、別に自作のライブラリのテストももちろんできますので、開発で使っているライブラリをテストすることができます。

使えるメソッドいろいろ

QUnit - jQuery JavaScript LibraryのAPI documentationのところに使い方が書かれていますので、ここではよく使いそうなメソッドだけを説明したいと思います。

test( name, test )

nameにはテスト名、testには実行したいテストコードを匿名関数で記述します。

module( name )

nameにはテストしたい単位を渡します。これはテストをしているときの目印になります。
たとえばレイヤーを操作するテストをしたい場合に

としておくと、テスト結果画面で
「レイヤー表示テスト module: レイヤーの枠を表示する (0, 1, 1)」

みたいにmoduleの手前にプレフィックスが表示されます。

ok( state, message )

stateにはfalseとtrueを指定できます。
falseの場合にはNG、trueの場合にはOKとなります。
これは帰ってきた値がtrueかfalseか、または通過したかしないかなどの判定に使えそうです。

messageは表示したい文字列を渡します。

equals( actual, expected, message )

これはよく使うやつですね。
actualとexpectedの値が同じ場合にOKとなります。

messageは表示したい文字列を渡します。


すぐに使いそうなのをご紹介しましたが、もっと詳しく知りたい場合にはjQueryのテスティングフレームワークQUnit (でぃべろっぱーず・さいど)をごらんください。
「提供されているメソッド」に詳しく書かれています。

QUnitのダウンロード

QUnit - jQuery JavaScript LibraryのUsing QUnitのところにjsとcssのリンクがあるのでここからダウンロードできます。

ダウンロードするのが面倒というかたは次の「QUnitを使ってみる」に進んでください。

QUnitを使ってみる

以下がQUnit用のHTMLになります。
ここにテスト結果がどんどん表示される感じです。

もしQUnitをダウンロードされた方はtestsuite.cssとtestrunner.jsのパスを変更してください。

今回はテスト用のコードを「qunit.js」に、テスト対象のコードは「hogehoge.js」として話を進めていきます。

テストしたいコードは以下になります。

文字列を返してきているので、これはequalsでチェックできそうです。
なので、qunit.jsには

と記述してテストを実行してみました。
実行結果は以下の画面になります。

failedが0になっているので、バグはなさそうですね。
おそらく大体がこういったテストで十分だと思うのですが、もしHTMLエレメントを使ったテストの場合には少し工夫が必要です。
どっかのdivタグのinnerHTMLを書き換えたテスト、id指定で取得したエレメントのwidthのテストなどはどうしてもHTMLを必要とします。
次はHTMLエレメントに対してテストをする場合を解説してみたいと思います。

HTMLエレメントに対するQUnitテストコードを書いてみる

今回はHTMLエレメントを透過させるメソッドをテストコードを書いてみました。
初めに必要になるファイルを解説します。

  1. qunit.js - テストコードが記載されているファイル
  2. hogehoge.js - テスト対象のコードが記載されているファイル
  3. opacity.html - 透過のテストをするときに使うHTML

透過に関するテストって自動でできるの?と考える方がいらっしゃるかもしれませんが、これが以外とできるんですw

先ほど使ったQUnitテスト結果HTMLは、あくまでもテスト結果を表示するものなのでこれとは別にHTML(opacity.html)を用意します。

まずは透過させるコードです。

これのテストコードは以下になります。

ここからがちょっと新しいテストコードになります。
テストコードの中でtestwinというメソッドを呼んでいます。これは新しくウィンドウをPopupさせ、そのHTMLの描画が完成した瞬間にテストコードを実行してくれるすぐれものです。
つまりopacity.htmlを新しいウィンドウで開いてDOMの構築が完了したら透過のテストコードを実行してくれる感じです。

これはjQueryのoffset.jsの中を参考にしています。

続いてopacity.htmlの中身。

ここではjQueryのファイルとテスト対象のhogehoge.jsを読み込んでいます。
そしてscriptタグで「$(function(){});」を実行しています。
先ほどのテストコードでPopupした画面のDOM構築を待つと解説しましたが、これはつまりjQueryのjQuery.isReadyがtrueになるのを監視しているのです。
jQuery.isReadyはreadyというメソッドが呼ばれて初めて監視がスタートされるので、ここで$(function(){});を実行しているのです。
ちょいややこしいですねw

これでテストするためのコードがそろいましたので、実行してみたいと思います。

おお~Opacityのテストが実行されました。
$w("#opacity").setOpacity(0.2).getOpacity()で返ってきた結果が0.2なのでちゃんと透過機能がはたらいたようです。

まとめ

HTMLエレメントのテストで別のHTMLファイルを作らないといけないのはちょっと不便かもしれませんが、1回作ってしまえば後は何度でもテストが可能ですので、いつかきっとプログラマーを助けてくれると思います。

QUnitはJavaやANTなどが不要なため、完全に独立したテスティングフレームワークとして使えるので
「JSでテストコード書きたいけど敷居が高いな~」
という人にはもってこいなのではないでしょうか?

良く分からないこと

IE7.0でウィンドウを開いてテストするときに、まれにうまくいかないことがあります。
F5とかで再度テストをすれば大丈夫ですが、そうゆうときもあるようです。
Safari3.1やFirefox3では特に問題なかったです。
でもなぜIEだけ・・・

■関連リンク
Getting Started With jQuery QUnit for Client-Side Javascript Testing - Chad Myers' Blog
jQueryのテスティングフレームワークQUnit (でぃべろっぱーず・さいど)

onunloadイベントが拾えないパターン

onunload時に何か処理を実行して、その処理がとっても大切な場合は以下のパターンのときに
注意する必要があるかもしれないというメモ。

リンクを押して他の画面に遷移した場合

Firefox3.0
OK
IE6.0
OK
IE7.0
OK
Safari3.1
OK
Opera9.5
OK


F5を押した場合

Firefox3.0
OK
IE6.0
OK
IE7.0
OK
Safari3.1
OK
Opera9.5
NG


ブラウザを閉じた場合

Firefox3.0
OK
IE6.0
OK
IE7.0
OK
Safari3.1
NG
Opera9.5
NG

JavaScriptからOpacity(透過)を設定する方法

JavaScriptでアニメーションさせようとしたとき、意外と使うのがこの透過。
じょじょに透過させていくとか、見栄えもかっこよくボクは良く使います。

でも既存ライブラリを使った場合、Netscapeに対応していない場合が多いです。
jQueryPrototype.jsはそもそも対応ブラウザにNetscapeが含まれていないので当然といえば当然ですね。
それでもNetscape対応させたい場合のメソッドを作ってみました。
すんごい短いコードですw

一応ライブラリごとのOpcityの設定について書いておきます。

jQueryからOpacity

PrototypeからOpacity

自作メソッドからOpacity

3パターンのOpacity設定を使って、どのブラウザでも透過ができるようになっています。

JavaScriptやCSS、Railsなど使えそうなチートシートいろいろ

Cheat Sheets - Added Bytesで開発に役立ちそうなチートシートが公開されています。

PDFで落とすことができますが、PNGもあるのがありがたい。

チートシートもみやすく前にPrototype.jsのチートシート(ver1.5、1.6)で紹介したものを合わせてどこかに貼っておけばきっと開発を助けてくれるはず。


JavaScript Cheat Sheet


JavaScript Cheat Sheet - Cheat Sheets - Added Bytes

CSS Cheat Sheet


CSS Cheat Sheet (V2) - Cheat Sheets - Added Bytes

JavaScriptライブラリ毎のSelectorAPIの速度一覧

普段はPrototype.jsjQueryを使ってJavaScriptを書いているのですが、そこまで複雑なCSS SelectorAPIは使ったことがないのでこうゆう一覧、というか実際に実行して確認できるのはありがたい。

SlickSpeed Selectors Test

SlickSpeed Selectors Test

検証してくれるJavaScriptライブラリは以下のとおり。

  • DOMAssistant2.7.2
  • jQuery1.2.6
  • Prototype1.6.0.2
  • Mootools1.2
  • ExtJS Core2.2
  • Dojo1.1.1
  • YUI2.5.2

MacのSafari3.1で試してみたのですが、DOMAssistantというライブラリがおそるべき速さで実行できています。
もっとも遅かったのはYUIですが、Prototypeもそれに負けずに遅い感じでした。

jQueryはさすがですが、Extに負けているのがビックリ。

いろんなブラウザで試せばこれで一通りのベンチマークになりますね。
とはいっても複雑なCSS SelectorAPI書くより、idふるなり適当なclassを割り当てたほうが良さそうですねw

addEventListenerとattachEventでは実行される順番が違う

たとえばPrototype.jsを使っている場合、

こんな感じでイベントを登録することができる。
また同じオブジェクト(window)に対して同じイベント(load)を指定した場合は、追加として登録される。
なので上書きはされない。

こうゆう場合にIEとIE以外では挙動が違うので一応メモを残しておきます。

IEのattachEventの実行順序

一番最後に追加されたイベントから一番最初に追加されたイベントにさかのぼるように実行される。

なので上記のコードでは2→1

IE以外ののaddEventListenerの実行順序

一番最初に追加したイベントから一番最後に追加されたイベントを実行される。

なので上記のコードでは1→2

まとめ

初めPrototype.jsが何かしているのかと思ったのですが、とくにそれっぽい箇所がなく以下のように自作した関数でも再現したため、こうゆう挙動は一般的なんでしょうね。

一番最初に登録したイベントから実行されるのを望む場合はIEとIE以外で挙動が違うのでハマる危険性がありますね。

追記:
IEのイベント実行順序は不定? - inamenaiの日記でさらに実験をしていただきました。
attachEventは単純に逆順になるわけではなくランダムだそうですw
でも何度か実行しても同じ順序になるようなので、何か法則でもあるんでしょうか・・・

CSSファイル内に他のCSSファイルをインクルードする方法

ひとつのCSSファイルを共通部分をあの画面とこの画面とかで共通で仕様したいがlinkタグを追加したくないとかに便利。

読み込むCSSは1つのファイルなのに、CSSファイルの中から別のCSSファイルをインクルードしてくれるので、2個のCSSファイルを読み込んでくれる。

index.html style.css include.css


あんまり使う機会はなさそうですねw

DOM Events - DOMAttrModifiedを使ってみる

イベントを登録されたオブジェクトの属性が変更された場合にfireされるイベント。
Document Object Model Events

あるHTMLオブジェクトの属性を監視するときに便利かもしれませんね。

setIntervalで監視しているのをこういったイベントに置き換えることによって、簡略化もできるし。
でもFirefox限定・・・

DOM Events - MDC

DOMとJavaScriptについて

DOM(Document Object Model)とは、HTML文書およびXML文書のためのAPIである。」
というのがDOMの説明に多いのだが、一体何がDOMで何がDOMではないのかを判断するのがちょっぴり難しい。

JavaScriptをコーディングしていて、「あ~この部分はDOMだな」とか「う~ん、ここはDOMではなくJavaScriptだな」とかを明確に判断する必要はないんだけれど、分かればもっと楽しくなるんじゃないかな。

なのでDOMで遊ぶ際に必要な知識なんかを以下にまとめてみました。
既知の情報も多々ありますが、個人的なメモなのでご了承ください。

DOMとは?

HTML(XML)のようなタグ構造を持つ文書に対して、あたかもオブジェクトのようにアクセスするためのAPIです。 HTMLはタグという文書構造になっているので、例えば「
」のようにidにhogeという文字を持つdivタグにアクセスしたいとしたとき、その方法を提供してくれるのがDOMの機能です。 document.getElementById - MDC

文書の構造なのにJavaScriptからオブジェクトのようにアクセスできるのはとっても大切で、表示している文字列を書き換えたり背景色を変更したり、アニメーションさせたりといろんなことができてとっても楽しいのです。

そういった便利な関数やプロパティはオブジェクトとして提供されDOMインターフェースというものを通じてボクらはアクセスすることができます。

たとえば以下のようにtableタグを作るためにdocumentオブジェクトが持つcreateElementメソッドを使ったとしましょう。
この場合var宣言で定義されたobjには何が入っているのでしょうか?

JavaScriptでいうところのオブジェクトなのには変わりないのですが、new Object()とした場合と今回のようにcreateElementした場合ではオブジェクトの中身が全然違います。
「HTMLTableElementというDOMインターフェースを実装したtableオブジェクト」というのがobjに入っているオブジェクトの正体ですね。
(なんだか長ったらしいですが・・・w)

createElementでtableオブジェクトを作った場合にはinsertRowというメソッドを持ちますが、new Object()ではそのようなメソッドは持っていません。
これはHTMLTableElementインターフェースを実装しているかそうでないかの違いです。
HTMLTableElement (Common DOM API)

DOMって他の言語でも使えるの?

DOMの機能はPerl・Java・ActiveX・Pythonなどで提供されているようです。
確かにXMLを読み込むような処理の場合にDOMが使えれば簡単にアクセスできますもんね。

PythonのDOMを使った例

# Python DOM example
import xml.dom.minidom as m
doc = m.parse("C:\\Projects\\Py\\chap1.xml");
doc.nodeName # DOM property of document object;
p_list = doc.getElementsByTagName("para");


via: 導入編 - MDC

JavaのDOMを使った例

初めにXMLの読み込み処理がありますが、それ以降はほとんどJavaScriptで使ったものと同じですね。

このようにDOMは他の言語でも提供されているありがた~いオブジェクトなわけです。
これもDOMというものを中立に考えて機能を実装してくれているからなのでしょう。

何がDOMで何がJavaScript?

ここが本題といったところでしょうか。
どこがDOM?みたいに疑問を持つことは普段のコーディングにあんまり影響はしませんが、たとえばwindow.alert()ってDOMなの?そうじゃないの?みたいに少し突っ込んでみると興味が沸いてくると思います。

alert() は引数の文字列が入ったダイアログをポップアップする DOM のメソッドです。


via: The DOM and JavaScript - MDC

とmozillaで解説されているので、これは間違いなくDOMの機能でしょう!

では以下でDOMの場所を特定して解説してみたいと思います。
なおThe DOM and JavaScript - MDCのDOM と JavaScript - 何が何をしているのか?を参考にしています。というかほぼ一緒!


サンプルコードたったこれだけです!w
これだけあれば十分です。

var obj =

ここはobjというJavaScriptの変数を作成しています。

document.getElementsByTagName("div");

Documentインターフェースを実装しているdocumentオブジェクトのgetElementsByTagNameメソッドを使ってHTMLページの順番でdivタグを取得しています。
ここで取得されるオブジェクトはNodeListインターフェースを実装している配列になります。
なのでlengthというプロパティを持ってはいますが、これはJavaScriptの配列のlengthとは違います。
NodeListインターフェースが提供しているlengthとJavaScriptが提供している配列という違いですね。

alert(

DOMの機能を使ってダイアログを表示します。
(今までにこのメソッドを何度使ったことか・・・最近はconsole.logになりつつありますが)

obj.item(0).id);

ここはちょっぴり複雑ですね。
まずobjにはNodeListインターフェースを実装した配列が入っています、そしてその一つ一つにはHTMLDivElementインターフェースを実装したオブジェクトが入っています。
NodeListインターフェースにはitemというメソッドがあり、引数に数値を指定することでdivオブジェクトを取得することができます。

そして取得したdivオブジェクトが持つidというプロパティにアクセスしていますね。
idというプロパティはElementインターフェースが提供しているプロパティです。
ということはHTMLDivElementインターフェースとElementインターフェースを実装しているということになります。
(2個も実装しているなんてなんて贅沢なっ!)

基本的なclassName、id、innerHTML、styleなどは確かにどのHTMLオブジェクトでもアクセスできるので一元的にElementインターフェースで実装しているんですね。
ほほぅ。
element - MDC

たった2行のJavaScriptを見てみましたが、こんなにもいろんな実装がされているなんて!といった感じでしょうか。
先のコードでDOMじゃない部分といえば、変数宣言のvar obj部分と;セミコロンくらいです。
それ以外が全部DOMで提供された機能だったというわけです。
DOM様様ですねw

まとめ

なんとなくDOMについてまとめておきたかったので今回の記事を書きましたが、結構ボリューム感がありました。
とはいってもmozillaのサイトに行けば、JavaScriptの仕様はたいてい記載されていますし、今は詳しく書かれた本もたくさん発売されています。
勉強するにはもってこいな時代ですね。
6年くらい前はまだAjaxもそんなに普及されていなくて、そもそもAjaxという言葉はなかったからずうっと「非同期」なんて呼んでいたりしました。
その当時はwindow.alertはDOMの機能だってことは、どこにも書いてなくて先輩とかに聞いて回ったのを覚えています。

なんかものが落ちるjQuery Plugin - JDropper作りましたで作ったオモロ~なプラグインもDOMの機能なしには語れないのです。

DOMを学びやすいJavaScript解説本

JavaScript 第5版
JavaScript 第5版
posted with amazlet at 08.09.02
David Flanagan
オライリー・ジャパン
売り上げランキング: 7060

やっぱりサイ本はかかせないです。
この本は重要なところを太字とかにあんまりしてくれていないので文章を読む感じで学習するのが得意な人に向いているんじゃないでしょうか。

Head First JavaScript 頭とからだで覚えるJavaScriptの基本
Michael Morrison
オライリージャパン
売り上げランキング: 4564

この本最近買ったのですが、アツいですw
イラストばんばん使いまくりで、クロスワードとかも途中にあって、学習というより遊びながらな印象があります。

まるごとJavaScript & Ajax ! Vol.1
天野 仁史 舘野 祐一 川崎 有亮 arton 田中 孝太郎 国分 裕 山本 有悟 海野 裕也 nanto_vi
インプレスジャパン
売り上げランキング: 125084

かゆいところまで突っ込んで解説されているので、かなりな良本です。
雑誌感覚なので、気軽に読めるのもいいですね。


■関連リンク
W3C Document Object Model
Gecko DOM Reference - MDC
org.w3c.dom (Java 2 Platform SE 5.0)

Arrayをforinするより普通にfor文で回すほうが速い

Arrayのlengthはいったん変数に格納してからループしたほうが速いに引き続きベンチマーク。

そういえば配列をforinで回したことがあんまりなかったので、普通のfor文とどっちが速いのかな~という疑問が沸いたので試してみた。

配列をforinで実行した場合

Firefox3.0
481ms
IE6.0
3234ms
IE7.0
219ms
Safari3.1
219ms
Opera9.5
234ms

配列を普通のfor文「for (var i = 0; i < a.length; i++)」で実行した場合

Firefox3.0
7ms
IE6.0
32ms
IE7.0
16ms
Safari3.1
16ms
Opera9.5
31ms


この結果でびっくりしたのが、forinで回した場合のIE6.0の遅さ
じゃっかんブラウザも固まりかけていました。

配列に対して以下のように3つしか値が入っていないのに、lengthが1001になる場合にはforinのほうが有効かもしれませんが、そうゆう使い方はあんまり配列ではしないのでやっぱり普通にfor文で回したほうがよさそうですね。

さらにlen=arr.lengthのように一旦lengthを退避すればなお良いということかな。

■関連リンク
JavaScriptの配列をも~っと深く理解する:lengthの不思議な動作 - page2 - builder by ZDNet Japan

Arrayのlengthはいったん変数に格納してからループしたほうが速い

既出な内容ではあるが、一応メモとして残しとく。

配列を走査するときに、配列のlengthを一旦変数に格納したほうが速いんじゃないかという話。
実際試してみた。

コードは以下の感じでどのブラウザでも実行できるようにしました。

配列のlengthを退避せずに実行した場合

Firefox3.0
12ms
IE6.0
63ms
IE7.0
63ms
Safari3.1
31ms
Opera9.5
32ms

配列のlengthを退避して実行した場合

Firefox3.0
7ms
IE6.0
16ms
IE7.0
31ms
Safari3.1
16ms
Opera9.5
16ms


おお~、全然違うみたい。
とはいっても9万回以上ループした場合の結果なので、実際の開発でこれぐらいの差がでるかどうかは微妙ですが、塵も積もれば何たらってやつで意識しておけば処理の重いJavaScriptでもちょっとしたメリットはあるかもしれません。

■関連リンク
JavaScriptの配列をも~っと深く理解する:lengthの不思議な動作 - builder by ZDNet Japan
配列を for で回すときは length を何度も参照すると遅い - gan2 の Ruby 勉強日記

Webサイトの高速化 - styleはheadタグ内に書くと描画が速い

Webサイトの高速化 ルール5 CSSは上に! (Yahoo! developer netoworkより翻訳) | パフォーマンスチューニングblog | インターオフィスより

スタイルシートの読み込みは普通headタグ内で行いますが、ときとして後からHTMLに追記したスタイルがHTMLの下のほうにある場合があります。
(本当はちゃんと別ファイルとして作成しなきゃいけないのですが、直接書かれている場合があったり・・・)

こういったことをしてしまうと、画面の描画に影響を受けるということを以下の記事で知りました。
IEなどはスタイルが読み込み終わるのをじ~と待っていて、Firefoxは待たずにどんどん描画してしまうので、display:noneな要素も一瞬見えてしまうなどの問題があったりするみたいです。



スタイルシートを下のほうに配置すると、IEも含めて多くのブラウザにとって、徐々にページを表示することができなくなります。ブラウザは、スタイルが変更されてページ要素を再描画しないといけなくなるのを避けるために、ページを読み込み終わるまで描画をブロックします。そのため、ユーザは真っ白なページを見続けることになります。Firefoxは描画をブロックしません。そのためスタイルシートをロードし終わった時にページ要素を再描画する場合があります。その結果、the flash of unstyled content problem(スタイル適用前のコンテンツが一瞬見えてしまうこと)といった問題が発生する場合があります。


via: Webサイトの高速化 ルール5 CSSは上に! (Yahoo! developer netoworkより翻訳) | パフォーマンスチューニングblog | インターオフィス


ユーザビリティとして真っ白な画面が何秒か表示されているのは具合が悪いもんです。
たとえば昔、巨大なTableタグでHTMLを囲っているときがありました。
今みたいにdivタグでfloatされるのが流行る前ですね。
Tableタグはその中身がダウンロードし終わらないと描画が開始されないので、ブログとかのテンプレでこの方法を使っているとユーザーは5秒以上何もない画面を見たりしてました。

それとAjax関連で通信をしているあいだ、グルグル回るアニメーションgifとかで「今検索してますよ~」を通知して待っているあいだもユーザーを不安にさせないなんて方法も今となっては主流ですね。

ちょっとした工夫で描画が変わってくるのはなかなか実感がないですが、意識しているだけで全然違うんでしょう!

いやはや勉強になります。

キングボンビーがサイトを侵略する?jQuery Plugin - kingbonbi.js作りました

更新履歴

2008/08/23
- いろいろ調整しながらなので、動かなかったりご迷惑をお掛けいたします。とりあえず落ち着きました。
- ブログパーツ用のコードを変更しました。JSファイルの読み込みではなくアンカータグにしました。

kingbonbi
なんかものが落ちるjQuery Plugin - JDropper作りましたに引き続きオモロ〜なJavaScriptを作ってみました。

なんでキングボンビーを採用したのかよく分からないのですが、お風呂の中でなんか面白いことJavaScriptで出来ないかな〜と考えていたらキングボンビーに行きつきましたw
しかも名付けて「kingbonbi.js」!!
そのままです。

ブログパーツかBookmarkletとして公開いたします。
また今回もソースコードは公開いたしますので、何かの参考になれば幸いです。

続きからご覧ください。

Continue reading

jDropper.jsのブログパーツとBookmarklet

更新履歴

2008/08/23
- ブログパーツ用のコードを変更しました。JSファイルの読み込みではなくアンカータグにしました。

この前リリースしたなんかものが落ちるjQuery Plugin - JDropperのブログパーツとBookmarkletを用意してみました。

単になんかものが落ちるだけのjQuery Pluginですが、いろんなブログ上で実行してみると背景の配色が各々のブログで違うのでなんか面白かったですw

ブログパーツ用のコード

<a href="javascript:(function(){var%20s=document.createElement('scr'+'ipt');s.charset='UTF-8';s.language='javascr'+'ipt';s.type='text/javascr'+'ipt';var%20d=new%20Date;s.src='http://lab.hisasann.com/jdropper/js/bookmarklet.js?u='+escape(document.location.href)+'&d='+d.getMilliseconds();document.body.appendChild(s)})();"><img src='http://lab.hisasann.com/jdropper/img/jdropper2.png' style='border: 0px ;'/></a>

Bookmarklet用のリンク

以下のリンクをブラウザのお気に入りにドラッグしてください
jDropper

ご利用にあたって

本PluginはjQueryを使っておりますので、ブログパーツやBookmarkletを使った場合に画面の挙動がおかしいなどの現象がある場合にはご利用にならないようお願いいたします。

jQueryのheight()やwidth()はOpera9.5に対応していない気がする

jQueryは1.2からheightメソッドやwidthメソッドでdocumentwindowのサイズを取得することができるが、Opera9.5対応がされてないような気がしたのでメモメモ。

heightメソッドやwidthメソッドは本当に便利で以下のようにエレメントの幅や高さを簡単に取得することができる。

これはこれで重宝するメソッドではあるのですが、どうもOpera9.5でwindow(表示されている領域)の幅や高さを取得したときに思ったとおりにならなかった。

で、実際jQueryを見に行ってみた。

jQuery 1342行目

No~~~~~!
Operaの場合(jQuery.browser.opera)にdocument.body[ "client" + name ]で取得している。
このdocument.body[ "client" + name ]はおそらくOpera9.5未満のバージョンで有効なんじゃないかな?
今手元にその環境がないので確かめられないのだが、以下のとおり9.5からは
document.documentElement.clientWidthdocument.documentElement.clientHeightを使うべきだと思う。

Opera 9
標準
document.body.clientWidth
document.body.clientHeight


互換
document.body.clientWidth
document.body.clientHeight


Opera 9.5
標準
document.documentElement.clientWidth
document.documentElement.clientHeight


互換
document.body.clientWidth
document.body.clientHeight


via: ブラウザの表示領域のサイズを取得する方法。 - Enjoy*Study

ということでOperaでうまく取得できないので、自作!

jQueryのメソッドをさらにラップする形にしてみました。
これでいけるっしょ!
でもこれだと今度9.5にしか対応していないから、バージョンごとに分けないといけないのか。
面倒だな〜w

次のjQueryのバージョンで直るのかな?

Safariでは画像のloadが終わっていないとwidth、heightがうまく取得できない

IE6.0、IE7.0、Opera9.5、Firefox3.0ではちゃんと画像の幅や高さが表示されるのに、
Safariでは画像のwidth属性height属性をキチっと指定しないと「0」になってしまう。

今回はjQueryを使ってサンプルを紹介していきます。

たとえば以下の場合

そんなに普段画像の幅や高さを取得したりすることは少ないかもしれないが、
意外とハマるので気をつけたい。


そしてこれを回避するためには以下のように画像のonloadを待つ必要がある。

これでSafariでようやく画像の幅、高さが取得できるが、毎回onloadイベントをbindさせるのも面倒だし、
バインドできないシチュエーションなんかもあるかもしれない。

なので単純にimgタグの中にwidth属性とheight属性を必ず書くようにする。
これでSafariの場合でも問題なく幅、高さを取得できます。

実際のデザインのときはだいたいimgタグのwidth属性とheight属性は書いているけど、
書き忘れ時にこの現象に遭遇するでしょう。
こうゆうのって意外とハマりますよね。

なんかものが落ちるjQuery Plugin - JDropper作りました

更新履歴

2008/08/21
- easingの種類を増やしました
- id:pyangoroさんの指摘で名前を変更しましたw
- id:ぁゃιくない(*~Д~)さんのさんまの名探偵的なゲームだと面白いという意見によりちょいゲーム化
- duration(速度)をパラメータとして渡せるようにしました

jdropper

画像やHTML要素が雨のように降り注いだら面白いな〜と思ってこのjDropperを制作しました。
特にこれを使って何かが出来るわけではないですが、ブログパーツの一種として使っていただけたら幸いです。

続きからご覧ください。

Continue reading

Mac OS X 10.5にMT4をインストールしてみた

Perlの勉強としてPlaggerをおすすめされている方は多いと思いますが、せっかく普段MTを使っているのでローカルにMT4をインストールしてみました。

MT4をダウンロードする

以下のサイトからダウンロードし、解凍しときます。

Six Apart - Movable Type のライセンスと購入について

httpd.confの編集

Mac OS Xには「/Users/[ユーザ名]/Sites/」ディレクトリにhtmlファイルを置くと自動的にhttpでアクセスできるようになります。
まずはWeb共有で公開するためのフォルダでCGIが動くように設定します。

このディレクトリにある自分の名前のconfファイルを編集します。(httpd.confファイルではありません)
編集にあたって事前にコピーしてバックアップしておくことをオススメします。

[ユーザー名].confを開いて、

を以下のように編集します。

これでCGIが動く環境が整いました。

Web共有を有効にする

システム環境設定の「共有」を開きます。
そして以下のように「Web共有」にチェックを入れれば完了です。

51716709

MT4をサイトディレクトリに配置する

解凍したMT4フォルダをFinderからサイトディレクトリに配置しました。

あとは「http://localhost/~[ユーザー名]/mt4/」にアクセスすればMT4のindex.htmlが読み込まれます。
やった〜〜!

■関連リンク
Mac OS X 10.5 ( Leopard ) でCGIを使用する - sbs_tsの日記
の記事を大変参考にさせていただきました。

買った本

Head First JavaScript 頭とからだで覚えるJavaScriptの基本
Michael Morrison
オライリージャパン
売り上げランキング: 1352

いっけん筋肉増強をさせられるんじゃないかと思っちゃうジャケットですが、JavaScriptをイラスト付きで解説しているということで購入。
4200円だからすり切れるまで読みますw

Firefoxプラグインで入力補完が使えるCSSエディタ

Firefoxプラグインで入力補完が使えるCSSエディタ

ちょろっとCSSを書きたい人向けなFirefoxプラグインです。
入力補完機能があるので、「あのプロパティどうゆうスペルだっけかな?」というときに重宝しそうです。

MacのTextMateを使っている人にはまったくもって必要のないプラグインですが、それでもちょろっとCSSには向いていますね。

以下のサイトの「Click here to download and install DiavoloTest 0.6.」というリンクからダウンロードしました。

<Glazblog/>

Event.observeでセットするfunction内のthisについて

例えば以下のようにセットすることは多々あると思うのですが、

注意したいのは「this.id」としている部分。
ここのthisはもちろん"hoge"オブジェクトになっててほしいところなんですが、IEではwindowオブジェクトになってしまいます。
以下のサンプルではalert(this.id)でhogeが表示されてほしいところですが、windowIdが表示されます。

が~~ん!

これはPrototype.jsの中でattachEventを使ってイベントを登録しているのが原因かな~なんて思っています。
まぁIEでイベント登録するときはattachEvent使うしかないのですが・・・

ためしにEvent.observeの部分を自分で書いてみたのですが、やっぱりattachEventの部分が「windowId」になる。

さらっと使っていますが、「Event.element(e).id」を使って自分自身のオブジェクトを取得できるようです。
一応これで解決かと思いきや、まだダメなパターンがありそうです。

クリックされたエレメントの上位エレメントにイベントが登録されている場合

クリックされるアンカータグのひとつ上のエレメントにIDがふられて、そのエレメントにイベントが登録されているパターン。

この場合だとまずIEでthis.idはwindowオブジェクトだし、Event.element(e).idで取れてくるのはアンカータグのIDだし・・・
んもうっ。

結局のところ

なんか嫌だけど、こうなの?w

すんごい初歩的なところで悩んでいますが、jQuery使っているとこのあたりが非常にもどかしい。
というかもっといい方法がありそうだw

JavaScriptでアニメーション(animate)するときに気をつけたいこと

サンプルコードを書いていないんだけど、ちょっと基本的かつ意外とハマる問題かな~と思ったのでメモメモ。
とは言っても2点だけw

スライドするdivタグの中にはoverflow:autoなdivタグは入れないほうがいいかも

このシチュエーションは意外あると思う。
divタグ(div1)の中に複数のdivタグ(div2)が入っていて、外側のdiv1をアニメーションでスライドさせてdiv2の部分を切り替えるシチューエーションの場合、div2がoverflowをautoになっているとFirefoxチラチラする。
他のブラウザではこのチラチラ現象は起きないんだけど、どうしてもFirefoxで起きてしまう。
(IE6.0、IE7.0、Safari3.1、Opera9.5ではチラチラしない)

解決策

これを防ぐにはoverflowをhiddenとかにしてautoじゃない状態にする。

ちなみにjQueryでは、animate関数(3026行目の中でこのチェックをしているがアニメーションするdivタグの中にいるdivタグには適用されないので自分でhiddenにする必要がある。

アニメーションする前にhiddenにして、アニメーションが終わったらautoに戻す感じね。

スライドするときにmarginをマイナスとかにしてスライドするとIE6で重くなる場合がある

jFlowというスライド用のjQueryプラグインではmarginLeftmarginT