JavaScript第五版読書会#7のレポートです。今回はCSSとイベント処理の入門的内容でした。ご参加頂いた皆様、ありがとうございました。JavaScriptからCSSを扱うそれ程難しくはないので、簡単にまとめておきます。インライン指定されたスタイルのみなので気を付ける必要があります。僕も最初の頃は知らずによく間違えていたのですが、これを知っていると無駄に時間を使わなくて済むと思います。);}</script>bar実行する上記コードを実行すると分かりますが、インラインで定義したものしか取得出来ないので、注意が必要です。スタイルシートオブジェクト各要素にインラインでCSSを指定するには、前述の方法でいいのですが、次は外部CSSや埋め込みのstyle要素の扱いです。ほとんど使った事がなかったのですが、document.styleSheetsを使って、操作が出来ます。IEの場合はプロパティやメソッド名が違うので少しだけ注意が必要ですが、以下のリンクが参考になります。みぞーノートgetComputedStyleここまでで、JavaScriptからインラインで書かれたCSSや、外部CSS、style要素で書かれたCSSの値を取得出来る事が分かりました。このままでは、最終的にどういうCSSが当たっているかが分かりません。そこで現在のスタイル値を参照出来るのが、getComputedStyle()メソッドです。getComputedStyle()については、id:amachangのエントリが詳しいです。Safariもバージョン3からは取得出来るようで、手元のWin版ver3.2.2で確認すると、そのまま取得出来ました。getComputedStyle()の第二引数は擬似要素。mozillaやFirefoxでは省けないので、通常はnullを指定するIEはHTMLElementのcurrentStyleプロパティを使う(擬似要素は調べる事ができない)getComputedStyle()とcurrentStyleは別物getComputedStyleが理論値なのに対して、currentStyleは実測値Operaは両方使える理論値(算出スタイル)と実測値を補足すると、例えばCSSでフォントに「MSゴシック」を指定したとします。実際に使用しているフォントを返すのがcurrentStyleです。いえ、currentStyleもどこまで正確かは怪しいようです。【Javascript】CSSの値を取得するCSSの扱い方のまとめJavaScriptからCSSを扱う為の方法を表にしておきます。0)セレクタとスタイルを分けて指定。引数はHTMLElement。第二引数は擬似要素で、通常はnullを使う。null)IEはHTMLElementがcurrentStyleというプロパティを持っている。厳密にはgetComputedStyle()で取得出来る値と違う。ちなみにOperaもこのプロパティを持っている。link要素にdisabledが使える見出しの通りなのですが、link要素にもdisabledが使えるようです。HTML要素ではなく、JavaScriptから操作する必要があります。</body></html>あまり使い所は少ないかも知れませんが、ユーザー側でCSSのオンオフをさせたい時はいいかも知れません。Dayに合わせて、ページ読み込み時にJavaScriptでCSSをオフにするぐらいしか、使い所が思い浮かばない。Walker見栄えの分離についてここまで書いておきながら言うのも何なのですが、CSS自体の操作はあまり行わない方がいいかなと思っています。保守性が悪くなるので、多用するべきではないと思っています。classの追加等でスタイルを切り替える方が保守しやすく、HTML、CSS、JavaScriptの分離が行いやすいと思います。イベント周り最初に結論。同じ要素に複数のイベントハンドラを割り当てる必要がある時は、素直にライブラリを使う。Operaも細かい挙動で違いがあるという話も出ていました。イベント周りは、今までの経験上でもブラウザ毎の差異が大きい部分と感じます。イベントタイプonclickなどのイベントタイプですが、ブラウザ毎に使える種類とその挙動に違いがあります。今回読んだ範囲では、ブラウザ間の違いはほとんど触れられていなかったので、参考リンクを張っておきます。tables英文ですが、イベントタイプとサポートされるブラウザが表になってまとまっており、とても参考になります。Level2のイベントJavaSctiptのイベントには二つの種類があり、これは似て異なるものです。Level2のイベントと呼ぶそうです。この辺りはあまり分かっていなかったので、今回は勉強になりました。Level2で定められているイベントが優れているのは、主に以下の2点です。実装状況はブラウザ毎に異なります。イベントが発生した要素のHTMLElementオブジェクトになります。ここで気を付けないといけないのが、オブジェクトのメソッドをハンドラとして渡した際のthisが変わる事です。IEでは使えませんが、addEventListenerを例にします。false);上記のコードを実行した際に、obj.propの「property」が呼ばれそうですが、実際にはundefinedです。これは、thisがイベントの発生したHTMLElementになる為です。上記のような時はどうするかというと、人によってやり方は違うかも知れませんが、僕はクロージャーを使う事が多いです。false);他にはapply()でラップした関数オブジェクトを渡す方法があります。Prototype.jsのbind()とかbindAsEventListener()はaplly()でラップしたものを返しているだけです。イベントの伝播(バブリング)イベントは伝播します。子から親へ伝わります。子要素で起きたイベントは、必然的に親要素にも伝わります。Level0もLevel2も同じです。親要素にイベントが伝播していく仕組みがあります。onclick="alert('bar')">実行してみる</a></span>上記のコードを実行してみる例の場合、リンクをクリックすると、その親要素のonclickも実行されます。HTML上の親要素を辿りながら同じイベントが実行されていく事をバブリングというそうです。このバブリングを含めて、DOMで定められているイベントの伝播には3つのフェイズがあります。キャプチャー(優先して処理されるイベントの捕捉)ターゲットノードでのイベントハンドラ実行バブリング(ターゲットからルートノードまでのイベントを実行)1はイベントが発生したノードのルートノードから、イベントが発生したノードまで、親から子に向けてイベントハンドラを捕捉して実行します。2はイベントが発生したノードのイベントハンドラを実行します。3はイベントが発生したノードから順番に子から親に向けて、ルートノードまでの各ノードのイベントハンドラを実行。以上のような流れでイベントが実行されます。英文ですがW3Cの図が分かりやすいです。Level2だと、1〜3になります。子要素で発生したイベントも捕捉出来るしかし、強制的にイベントが呼ばれるので、望まない動作になる時がある使い方によっては便利でもあり、不便でもあります。これはEventオブジェクトでコントロール可能で、途中でバブリングを停止する事が出来ます。文殊堂EventオブジェクトイベントハンドラはEventオブジェクトを扱う事が出来ます。そのイベントが発生したノード等、イベントに関する情報が入っているオブジェクトです。IEはwindow.eventにイベントオブジェクトが定義され、それ以外のブラウザはイベントハンドラの第一引数に渡されます。Level0の場合は、以下のようなコードでEventオブジェクトが取得出来ます。clickhandle;</script>JSから定義onclick属性で定義onclick属性の中で直接コードを書く場合は、暗黙的にeventという変数に入っているみたいです。イベントハンドラはこのオブジェクトを使って、ターゲットノードを特定したり、バブリング中のカレントノードを知る事が出来ます。バブリングを途中で停止させるメソッドも、このイベントオブジェクトが持っています。詳細は以下を参考にどうぞ。ArchivaaddEventListenerを使った処理IEの話は一先ず置いておき、通常のブラウザの話からです。Level2である、addEventListenerを使った処理を見ていきます。addEventListenerはIE以外の主なブラウザで使えます。Level2では複数登録出来ます。複数のイベントハンドラを定義した時は、登録された順で実行されるとは限らない事に注意する必要があります。addEventListenerに渡すハンドラーはfunctionオブジェクトでなくても、handleEventをメソッドとして持つオブジェクトも渡せるようです。素人がプログラミングを勉強するブログaddEventListenerの第三引数をtrueにすると、バブリングフェイズではなく、キャプチャーフェイズで実行されるようになります。子要素でイベントが発生したとしても先に処理が出来ます。読んでいる時は皆一言も喋らなかった。笑えない実装内容でした。Level2に満たない内容で、独自実装の色が強いです。ここで言うIEは6と7を指していて、試してないですが恐らく8も同じだと思われます。attachEvent多くのブラウザがaddEventListenerでイベントを登録するのに対して、IEはattachEventというメソッドを使います。Level2を満たしていないので、addEventListenerのように第三引数がなく、キャプチャーフェイズでの実行は不可です。ここで登録されたイベントハンドラはグローバル関数となり、thisにはwindowオブジェクトが入ります。これがどういう問題を起こすかは後述します。イベントオブジェクトIEのイベントオブジェクトはwindow.eventで参照出来ます。addEventListenerの場合はハンドラにEventオブジェクトが渡されますが、IEはwindow.eventを参照する必要があります。イベントは平行して起こらない為、その都度上書きすればいいという考えのようです。以下はよくあるクロスブラウザを考慮したイベントハンドラのコードです。window.event);}attachEventとthisキーワードIEのattachEventを使った場合は、イベントが発生した要素が分からないという問題があります。IEのattachEventはグローバル関数として登録される(thisはwindowオブジェクトになる)IEのEventオブジェクトにはcurrentTargetがないので、バブリングで処理中のノードが分からないDOMレベル0ならバブリング中のノードもthisで取得可能だが、eventオブジェクトから取れない以上、処理中のノードを取得出来ない複数のハンドラを使用する場合など、attachEvent(DOMレベル2相当)を使う必要がある時は、クロージャーを使う方法がある。イベントハンドラから、クロージャーを使って、イベントが発生した要素を参照するという方法しかし、クロージャーを使うとメモリリークを引き起こす上記のような問題があります。いう形が多いようです。読書会の後に色々調べた所、finalyを使って循環参照を削除する方法もあるようです。zorioの日記この記事を書いている時に気付いたのですが、IEのメモリリークはマシにはなっているようです。IEのメモリリークが直ってるっぽい。MoonIE8についてCSSの標準対応は大分進んだようですが、イベント周りは変更する気があるのかないのか、そのままのようです。今回の読書会と直接関係はないですが、IE8については以下もリンク張っておきます。IT戦記いつも思うのですが、サイ本がIEを解説する時の文章には、悪意が感じられます。イベントのまとめ表をクリックで拡大出来ます。Level0のハンドラを解除した事が無かったのだけど、Firefoxはnullにすると実行されなくなった。他のブラウザは分からない。true;ここまでで、イベント処理の概要が掴めました。個人的にあやふやなまま覚えていたイベント周りの処理が理解出来て良かったです。この状態で、2008年5月のid:amachangのエントリを見ると、さらに理解が深まります。Level2を使うという三択で保守性がどうのという議論みたいになっているのですが、JavaSctiptのイベントを分かっているかどうかで、見る角度が全く変わる記事だと思います。一年前に読んだ時と比べて、別のエントリのような感覚がしました。属性を使わないことによって本質的ではないことをたくさん書かないといけない上記に書かれている事が理解できました。先のid:amachangのエントリのコメント欄から、IEのメモリリークの問題は2007年に修正されたという情報もあります。IEのメモリリークが直ってるっぽい。環境がなくて未確認なのですが、nanto_viさんが解説してくれる事に期待。Level0のonclick="hoge()"みたいに使うのもありだと思います。Level0の出番は多いと思います。Level2が必要になった段階では、ライブラリを導入すればいいかなというのが、個人的な一応の結論です。おまけこのエントリのテーブルを見やすい大きさで表示しようとすると大きすぎるので、拡大縮小出来るスクリプトをやっつけで作りました。綺麗に書けそうですが、現状で公開しておきます。以下みたいな感じで使います。type="text/javascript">zoomTable('40%','100%');</script>tableの後にzoomTableという関数を、縮小時のフォントサイズと拡大時のフォントサイズを指定して呼び出します。縮小時にはzoominというclassが、拡大時にはzoomoutというclassが定義されるので、適当なスタイルを当てて下さい。一部のブラウザしか対応していませんが、私はマウスカーソルが虫眼鏡になるようにしています。Chromeは対応して、Operaは未対応のようです。IEは.curに変換すればいけそうですが、今回はパス。運営側としての反省点は、告知が直前になってしまった事が、特に申し訳なかったと思っています。あと毎回気になるのがネットワークです。会場次第かなー、という気がします今回はオンラインでも何人か参加頂き、コミュニケーションを取れたがよかったと思います。これまではオンラインでの参加者が少なかったので、ustreamとlingrをやっていて良かったと思いました。懇親会ではシリコンバレーバレーかぶれの人達から、色々話しを聞いたりと楽しかったです。意外と普通の居酒屋でした。リーズナブルなので、蛍池ではいいかもです。大阪以外での開催も考えているので、今後ともKanasan.JSを宜しくお願い致します。