Hatena::Groupmoz-addon

Ci.nsIZIGOROu

2007-10-11久しぶりにJavaScriptしてみる

XML版HTCを書くための永久保存版テンプレートとbehaviorを使った時の実行順序、イベントなど

| 02:40 |  XML版HTCを書くための永久保存版テンプレートとbehaviorを使った時の実行順序、イベントなど - Ci.nsIZIGOROu を含むブックマーク はてなブックマーク -  XML版HTCを書くための永久保存版テンプレートとbehaviorを使った時の実行順序、イベントなど - Ci.nsIZIGOROu

タイトル長いw

ちまたでIE独自実装の話*1が盛り上がっていますが、独自実装の中でもやはり熱いネタと言えばDHTML Behaviorでしょう。

behaviorのサンプルはIE5時代の物なので、XMLなんだか良く分からないマークアップ形式なのですが、今回はこれをXMLとして正しい形でテンプレート化しました。是非お使い下さい。*2

HTCファイル

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<public:component xmlns="http://www.w3.org/1999/xhtml" xmlns:public="urn:HTMLComponent">
  <script type="text/javascript">
    alert("b");
  </script>
  <public:attach event="onload" onevent="alert('window onload');" for="window" />
  <public:attach event="onreadystatechange" onevent="alert('document onreadystatechange : ' + document.readyState);" for="document" />
  <public:attach event="onreadystatechange" onevent="alert('element onreadystatechange : ' + element.document.readyState);" for="element" />
  <public:attach event="oncontentready" onevent="alert('element oncontentready');" for="element" />
  <public:attach event="ondocumentready" onevent="alert('element ondocumentready'); alert(element.hasAttribute('id')); alert(element.hasAttribute('class'));" for="element" />
  <public:method name="hasAttribute" />
  <script type="text/javascript"><!--
    function hasAttribute(sName) {
      return element.outerHTML.match('<[^>]+>')[0].indexOf(" " + sName + "=") > -1;
    }
  --></script>
</public:component>

呼び出し側のHTML

こんな感じで。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
  <head profile="http://purl.org/net/ns/metaprof">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <title>behavior template</title>
    <script type="text/javascript">alert("a");</script>
    <style type="text/css">
    body {
      behavior: url("./htc/sample.htc");
      background-color: #777777;
    }
    </style>
    <script type="text/javascript">alert("c");</script>
    <meta name="author" content="ZIGOROu" />
    <meta name="description" content="" />
    <meta name="keywords" content="" />
  </head>
  <body id="htcTest">
    <script type="text/javascript">alert("d");</script>
    <h1 class="h">Behavior Template</h1>
    <div class="section">
      <h2 class="h">Webアプリケーション</h2>
      <p>
        最近余り書く気力が無いです。
      </p>
      <div class="section">
        <h3 class="h">Perlについて</h3>
        <p>
          Perlに関しては次のような指摘があります。
        </p>
        <blockquote cite="http://profile.allabout.co.jp/pf/anagram/qa/detail/6863" title="今回のmixiのリニューアルについて - 寺田 あつし : Web制作・クリエイティブ [All About プロファイル]">
          <p>
            いずれにしても上場企業のする仕事とは思えません。<br />
            そもそもせっかくリニューアルといっているのに、いまだにphpではなくperlで動いているあたり。。。
          </p>
        </blockquote>
      </div>
    </div>
    <script type="text/javascript">alert("e");</script>
  </body>
</html>

呼び出しの順序とIEのイベント

実は幾つか仕込んであるalertの順序が非常に重要です。

HTML内部のalert
  • style要素の直前
  • style要素の直後
  • body開始タグの直後
  • body終了タグの直前
HTC内部のalert
  • public:component開始タグの直後
  • public:attachでwindowのonloadイベント
  • public:attachでdocumentのonreadystatechangeイベント
  • public:attachでelementのonreadystatechangeイベント
  • public:attachでelementのoncontentreadyイベント
  • public:attachでelementのondocumentreadyイベント
実行結果
  1. a (style要素の直前)
  2. c (style要素の直後)
  3. b (public:component開始タグの直後)
    1. ここで背景が灰色になる
  4. element onreadystatechange : loading (public:attachでelementのonreadystatechangeイベント)
  5. d (body開始タグの直後)
  6. e (body終了タグの直前)
    1. ここでテキストは全て表示される
  7. element oncontentready (public:attachでelementのoncontentreadyイベント)
  8. element ondocumentready (public:attachでelementのondocumentreadyイベント)
  9. document onreadystatechange : complete (public:attachでdocumentのonreadystatechangeイベント)
  10. window onload (public:attachでwindowのonloadイベント)

と言う結果になる。

実験結果のまとめ
  1. head要素内のstyle要素の評価はhead要素内の全てのscript要素の実行が終わった後
  2. behavior内のscript要素が実行されていく
  3. その要素のreadystatechangeイベントが発火、その要素の読み込みが開始(readyStateがloadingになる)
  4. その要素内のscript要素が上から順に実行される
  5. その要素のcontentreadyイベントが発火
  6. その要素のdocumentreadyイベントが発火
  7. documentのreadystatechangeイベントが発火、documentの読み込み終了(readyStateがcompleteになる)
  8. windowのloadイベントが発火

って感じ。Mozilla等のDOMContentLoadedとかとの違いは未調査です。*3

oncontentready, ondocumentready, onloadの違い

ここはMSDNを当たりましょう。

When the oncontentready notification fires, the content of the custom element has been successfully parsed and built. An HTC file should attach a function to this event if it is to set any properties that apply to the custom element or its contents. Also, oncontentready is the correct event to use to initialize a viewlink element behavior in script.

When the ondocumentready event fires, the document has been completely parsed and built. Initialization code should be placed here if the component needs to navigate the primary document structure. The ondocumentready event notifies the component that the entire page is loaded, and it fires immediately before the onload event fires in the primary document.

About Element Behavior - Component Initialization
凄いざっくり訳して*4みると、
oncontentreadyが発火したとき、カスタム要素の内容のパースとビルドが成功しています。 もしカスタム要素やその要素の内容に対してプロパティを設定する場合は、HTCファイルの中でこのイベントに関数をattachしなければなりません。 さらにoncontentreadyはviewlink要素のbehaviorをスクリプトの中から使う為の初期化が完了した事も意味します。 ondocumentreadyが発火したときは、documentのパースとビルドが成功したときです。 もしコンポーネント*5が元のdocumentオブジェクトの構造に対して操作を行う事が必要な場合は、その初期化コードはこのイベントに置かれるべきです。 ondocumentreadyイベントはコンポーネントに対してページのロードが完了した事を知らせて、その後すぐに元のdocumentオブジェクトのonloadイベントより前に、このイベントを発火します。
って感じかな。多分。 viewlinkはドキュメントを斜め読みなんでいまいちなんだか分かって無いです。 試せば分かる事だけど、全ての要素のoncontentreadyが完了したら、ondocumentreadyが発火するんだと思われます。従って、
  1. 最も速く特定の要素に対して何かイベントハンドラを追加したければoncontentreadyのタイミングで出来そう。
  2. onloadイベントに初期化コードを引っ掛けるのでは無くて、ondocumentreadyに引っ掛けるのが吉。
と言えそうです。 IE対策の為にbehaviorを使うのは結構面白そう。pngのアルファチャンネル対策だけじゃ勿体無いくらいbehaviorには面白い機能が満載なので、是非使ってみて下さい。 但しセキュリティには十分熟慮する必要があるでしょう。
おまけ*6
ちゃっかりここではbody要素に対してだけだけども、IEでは使えないhasAttribute()を実装してみた。w 全称セレクタを使ったbehaviorでnodeTypeがELEMENT_NODEなelementに対してだけattachすればIEでもhasAttribute()が使えるようになります。

仕様の出所*7

W3Cに草案が出ていて、 HTML Components にある。
これによれば、xmlnsはまぁいいんだけどhtml要素がroot要素になってる。 なのでテンプレ化するとしたらhtml要素をrootにもって来るべきかも。

*1:条件付きコンパイルを使った高速化のネタ。id:amachangスバラシス

*2:多分、ほとんどの人には意味が無いだろうけどw

*3:誰かきっとやってくれる!w

*4:適当ですので自己責任で

*5:HTCの事

*6:追記1: 2007-10-12T02:43:06+09:00

*7:追記2: 2007-10-17T13:41:32+09:00

latchetlatchet2007/12/13 12:32はじめまして。
ZIGOROuさんのXML版HTCを使用させていただきました。
ファイルの公開と解説エントリーが勉強になります。
ありがとうございました。
http://juce6ox.blogspot.com/2007/12/iedomload-cached-htc.html

ZIGOROuZIGOROu2007/12/18 14:30どうもです。こんなエントリ良く見つけましたねw
実際のエントリも拝見しました。
元ネタのDean Edwardはこのonload問題って割と最近まであーだこーだ言って、最終的に解決って言ってたような。。。
詳細は分かりませんがw

bemojmxrnobemojmxrno2013/08/10 05:41nbjxpnp{.beepo, <a href="http://www.tzzrunuevw.com/">kpzqmhmyhy</a> , [url=http://www.gddguscjdt.com/]rfegozcyej[/url], http://www.ehqystjvqz.com/ kpzqmhmyhy