18 スクリプト

目次

  1. スクリプトの概説
  2. スクリプトをサポートするユーザエージェント向けの文書設計
    1. SCRIPT要素
    2. スクリプト言語の指定
    3. 組込みイベント
    4. 文書の動的変更
  3. スクリプトをサポートしないユーザエージェント向けの文書設計
    1. NOSCRIPT要素
    2. スクリプトデータをユーザエージェントから隠す

18.1 スクリプトの概説

クライアント側スクリプトとは、HTML文書と連携するか、または文書に直接組込まれるようなプログラムのことである。このプログラムは、文書がクライアント環境に読み込まれる際に実行されたり、リンクがアクティブになった際などに実行されたりする。HTMLがスクリプトをサポートする方法は、スクリプト言語の種別からは独立である。

スクリプトを用いると、著者は、HTML文書を高度に動的にしたり対話的にしたりする方向で拡張できる。例を挙げよう。

著者がHTML文書に添付できるスクリプトには、2つの種類がある。

注意。 本仕様には、スクリプトに関連して、 スクリプトマクロについての詳細情報がある。

18.2 スクリプトをサポートするユーザエージェント向けの文書設計

以下の各節では、スクリプトをサポートするユーザエージェントに関係する内容を説明する。

18.2.1 SCRIPT要素

<!ELEMENT SCRIPT - - %Script;          -- script statements -->
<!ATTLIST SCRIPT
  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
  type        %ContentType;  #REQUIRED -- content type of script language --
  src         %URI;          #IMPLIED  -- URI for an external script --
  defer       (defer)        #IMPLIED  -- UA may defer execution of script --
  >

開始タグ: 必須、終了タグ: 必須

属性定義

src = uri [CT]
この属性は、外部スクリプトの所在を指定する。
type = content-type [CI]
デフォルトのスクリプト言語を上書きし、当該要素内容のスクリプト言語を指定する。スクリプト言語は、「text/javascript」のようにMIMEタイプで指定する。著者は当該属性値を必ず記述しなければならない。この属性のデフォルト値は存在しない。
language = cdata [CI]
推奨しない この属性は、当該要素内容のスクリプト言語を指定する。この値は言語の識別子ではあるが、識別子が【インターネットの】標準ではないので、この属性は推奨しないこととなり、typeを採用する。
defer [CI]
この論理型属性を設定した場合、ユーザエージェントに対し、当該スクリプトが文書の本文を少しも生成しないことが示唆される。例えば、JavaScriptでいう「document.write」が含まれない、など。従ってユーザエージェントは、【スクリプトの実行を待たずに】パースとレンダリングを継続できる。

別途定義がある属性

SCRIPT要素は、HTML文書にスクリプトを組み込むもので、 HEAD要素あるいは BODY要素に、何回出現してもよい。

スクリプトは、この SCRIPT要素の内容か、または外部ファイルで定義される。 src属性の設定がない場合、ユーザエージェントは当該要素の内容をスクリプトであると解釈しなければならない。 src属性の値がURIだった場合、ユーザエージェントは当該要素内容を無視し、このURIからスクリプトを取得する必要がある。 charset属性で指定されている文字符号化方法src属性が示すスクリプトの符号化方法を示していて、当該 SCRIPT要素とは無関係であることに、注意されたい。

スクリプトはスクリプトエンジンによって評価される。スクリプトエンジンはユーザエージェントにとって既知でなければならない。

スクリプトデータのシンタクスは各スクリプト言語に依存する。

18.2.2 スクリプト言語の指定

HTMLは特定スクリプト言語に依存しないため、著者はユーザエージェントに対し、各スクリプトの言語を明示しなければならない。スクリプト言語は、デフォルト宣言と局所宣言の双方で明示することができる。

デフォルトのスクリプト言語  

著者は、文書中のすべてのスクリプトのデフォルトであるスクリプト言語を、 HEAD要素の META宣言で、次のように指定しなければならない。

<META http-equiv="Content-Script-Type" content="type">

このtypeは、スクリプト言語を示すMIMEタイプで、例えば、「text/tcl」、「text/javascript」、「text/vbscript」である。

META宣言が存在しない場合、デフォルトは「Content-Script-Type」HTTPヘッダで指定できる。

    Content-Script-Type: type

このtypeも、スクリプト言語を示すMIMEタイプである。

ユーザエージェントは、次の優先順位に従ってデフォルトのスクリプト言語を決定する必要がある。

  1. Content-Script-Typeを指定するMETA宣言がある場合、文字列中で最後に現れる宣言の内容をデフォルトのスクリプト言語に決定する。
  2. そうしたMETA宣言がなく、Content-Script-Typeを指定するHTTPヘッダがある場合、文字列中で最後に現れるヘッダの内容をデフォルトのスクリプト言語に決定する。

デフォルトのスクリプト言語を指定していない文書で 組込みイベントスクリプトが指定された要素を含むものは、不正である。ユーザエージェントはこれを解釈しようと試みてもよいが、解釈を試みるよう要求されるわけではない。 オーサリングツールは、著者が不正な文書を作らないですむよう、デフォルトスクリプト言語の情報を生成する必要がある。

スクリプト言語の局所宣言 

文書中のどの SCRIPT要素インスタンスも、type属性が指定されていなければならない。あるSCRIPT要素のtype属性値は、当該要素のデフォルトスクリプト言語を上書きする。

次の例は、デフォルトのスクリプト言語を「text/tcl」と宣言している。ヘッダにはSCRIPT要素が1つあり、これは外部ファイルの、text/vbscriptであるスクリプトを用いる。本文にあるSCRIPT要素の内容は、text/javascriptで記されている。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>スクリプトがある文書</TITLE>
<META http-equiv="Content-Script-Type" content="text/tcl">
<SCRIPT type="text/vbscript" src="http://someplace.com/progs/vbcalc">
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT type="text/javascript">
…JavaScriptのスクリプト…
</SCRIPT>
</BODY>
</HTML>

スクリプトからHTMLの要素を参照する 

各スクリプト言語には、スクリプト内からHTML文書オブジェクトを参照するための規約が存在する。本仕様は、HTML文書オブジェクトを参照するための標準機構を定義するものではない。

しかしながら、スクリプトから要素への参照は、要素名に従わねばならない。スクリプトエンジンは、要素を識別する際に次の優先基準に従う必要がある。まず、name属性と id属性の双方が設定されている場合はname属性が優先する。次に、どちらか一方の場合は、ある方を用いる。

18.2.3 組込みイベント

注意。 HTML文書の著者への助言。組込みイベントの領域では、例えばスクリプトとイベントとの結合方法など、頻繁に変更があり得る。この領域の研究は、W3Cの文書オブジェクトモデル作業班のメンバーが行なっている。より詳しい情報はW3CのWebサイト http://www.w3.org/ で得られる。

属性定義

onload = script [CT]
onloadイベントは、ユーザエージェントが1つのウインドウの読み込みを終了した時点、あるいは1つのFRAMESET中のすべてのフレームの読み込みを終了した時点で発生する。この属性は、BODY要素とFRAMESET要素で使える。
onunload = script [CT]
onunloadイベントは、ユーザエージェントが1つのウインドウあるいはフレームから文書を除去する時点で発生する。この属性は、 BODY要素とFRAMESET要素で使える。
onclick = script [CT]
onclickイベントは、ポインティングデバイスのボタンが要素の上でクリックされた時点で発生する。この属性は、ほとんどの要素で使える。
ondblclick = script [CT]
ondblclickイベントは、ポインティングデバイスのボタンが要素の上でダブルクリックされた時点で発生する。この属性は、ほとんどの要素で使える。
onmousedown = script [CT]
onmousedownイベントは、ポインティングデバイスのボタンが要素の上で押し下げられる際に発生する。この属性は、ほとんどの要素で使える。
onmouseup = script [CT]
onmouseupイベントは、 ポインティングデバイスのボタンが要素の上で放される際に発生する。この属性は、ほとんどの要素で使える。
onmouseover = script [CT]
onmouseoverイベントは、ポインティングデバイスが要素の上に移動してきた際に発生する。この属性は、ほとんどの要素で使える。
onmousemove = script [CT]
onmousemoveイベントは、ポインティングデバイスが要素の上を移動する際に発生する。この属性は、ほとんどの要素で使える。
onmouseout = script [CT]
onmouseoutイベントは、ポインティングデバイスが要素の上から離れていく際に発生する。この属性は、ほとんどの要素で使える。
onfocus = script [CT]
onfocusイベントは、ポインティングデバイスかタブ移動によって要素がフォーカスを受けた際に発生する。この属性は次の要素で使える。 AAREALABELINPUT SELECTTEXTAREABUTTON
onblur = script [CT]
onblurイベントは、ポインティングデバイスかタブ移動によって要素がフォーカスを失った際に発生する。この属性はonfocus属性と同じ要素で使える。
onkeypress = script [CT]
onkeypressイベントは、要素上で何かあるキーが押されて放された際に発生する。この属性は、ほとんどの要素で使える。
onkeydown = script [CT]
onkeydownイベントは、要素上で何かあるキーが押し下げられる際に発生する。この属性は、ほとんどの要素で使える。
onkeyup = script [CT]
onkeyupイベントは、要素上で何かあるキーが解放される際に発生する。この属性は、ほとんどの要素で使える。
onsubmit = script [CT]
onsubmitイベントは、フォームが提出される際に発生する。この属性はFORM要素のみに適用される。
onreset = script [CT]
onresetイベントは、フォームがリセットされる際に発生する。この属性は FORM要素のみに適用される。
onselect = script [CT]
onselectイベントは、ユーザがテキストフィールド中のテキストを選んだ際に発生する。この属性はINPUT要素と TEXTAREA要素で使える。
onchange = script [CT]
onchangeイベントは、コントロールが入力フォーカスを失った際に、フォーカスを得た時と比べて値が変化していた時に発生する。この属性は、INPUTSELECT TEXTAREA要素に適用できる。

ユーザがユーザエージェントと対話する際に発生する複数のイベントと1つの動作を結びつけることも可能である。上に列挙した「組込みイベント」はどれも、スクリプトを値に取る。このスクリプトは、当該要素に関係するイベントが発生する度に常に実行される。 スクリプトデータのシンタクスは、各スクリプト言語に依存する。

フォームのコントロール要素であるINPUT, SELECTBUTTON TEXTAREA、並びにLABEL要素は、すべて何らかの組込みイベントに反応する。これらの要素がフォームの外部に出現する場合、これは文書のグラフィカルなユーザインターフェースを増強するために使われていると思われる。

例えば、アクティブになった際に、フォームを提出するのではないがサーバと交信をするような押しボタンを文書に組込みたいと考える著者もあろう。

ここで、組み込みイベントに基づくユーザインターフェース機能と利用可能なコントロールの例を幾つか示す。

次の例では、userNameへのテキスト入力が要求される。ユーザが入力フィールドを離れようとする際、 onblurイベントがJavaScriptの関数を呼び出し、userNameに適切な値が入力されているかどうかが検定される。

<INPUT NAME="userName" onblur="validUserName(this.value)">

更に別のJavaScriptの例を示す。

<INPUT NAME="num"
    onchange="if (!checkNum(this.value, 1, 10)) 
        {this.focus();this.select();} else {thanks()}"
    VALUE="0">

今度はテキストフィールドのイベントハンドラであるVBScriptの例を示す。

    <INPUT name="edit1" size="50">    
    <SCRIPT type="text/vbscript">
      Sub edit1_changed()
        If edit1.value = "abc" Then
          button1.enabled = True
        Else
          button1.enabled = False
        End If
      End Sub
    </SCRIPT>

これをTclにした例を示す。

    <INPUT name="edit1" size="50">
    <SCRIPT type="text/tcl">
      proc edit1_changed {} {
        if {[edit value] == abc} {
          button1 enable 1
        } else {
          button1 enable 0
        }
      }
      edit1 onChange edit1_changed
    </SCRIPT>

続いて、スクリプトの記述内容にイベントを組込んだJavaScriptの例を示す。まず、単純なクリックハンドラの例。

    
<BUTTON type="button" name="mybutton" value="10">
<SCRIPT type="text/javascript">
      function my_onclick() {
         . . .
      }
    document.form.mybutton.onclick = my_onclick
 </SCRIPT>
 </BUTTON>

次に、もう少し面白いウインドウハンドラの例。

    
<SCRIPT type="text/javascript">
      function my_onload() {
         . . .
      }

      var win = window.open("some/other/URI")
      if (win) win.onload = my_onload
</SCRIPT>

これはTclでは次のようになる。

 <SCRIPT type="text/tcl">
     proc my_onload {} {
       . . .
     }
     set win [window open "some/other/URI"]
     if {$win != ""} {
         $win onload my_onload
     }
 </SCRIPT>

ここで、組込みイベントハンドラ中の「document.write」あるいはこれと等価な命令文が、現在の文書を更新するのではなく新しい文書を作成するのである点に注意されたい。

18.2.4 文書の動的変更

文書の読み込みと同時に実行されるスクリプトは、文書の内容を動的に変更できる。この変更能力は、スクリプト言語自体に依存する。例えば、複数のベンダーがHTMLオブジェクトモデルの「document.write」命令文をサポートしている。

文書の動的変更は、次のようにモデル化できる。

  1. すべての SCRIPT要素は、文書が読み込まれる際の順番で評価される。
  2. 与えられたSCRIPT要素にあるSGML CDATAを形成する、すべてのスクリプト構成素が評価される。 その結合生成テキストは、文書中の当該SCRIPT要素の位置に挿入される。
  3. 生成されたCDATAは、再評価される。

HTML文書は、どのSCRIPT要素の処理前も処理後も、HTML DTDに適合するよう制約される。

次の例は、スクリプトが文書をどのように動的に変更するかを示す。

 <TITLE>テスト文書</TITLE>
 <SCRIPT type="text/javascript">
     document.write("<p><b>Hello World!<\/b>")
 </SCRIPT>

上のスクリプトは、次のHTMLマーク付けと同等の効果を持っている。

 <TITLE>テスト文書</TITLE>
 <P><B>Hello World!</B>

18.3 スクリプトをサポートしないユーザエージェント向けの文書設計

この節では、著者が、スクリプトをサポートしないユーザエージェントで機能する文書をどのように作ればいいかを説明する。

18.3.1 NOSCRIPT要素

<!ELEMENT NOSCRIPT - - (%block;)+
  -- alternate content container for non script-based rendering -->
<!ATTLIST NOSCRIPT
  %attrs;                              -- %coreattrs, %i18n, %events --
  >

開始タグ: 必須、終了タグ: 必須

NOSCRIPT要素を使うと、著者は、スクリプトが実行されない際の代替内容を提供できる。 スクリプトを認識するユーザエージェントは、 NOSCRIPT要素の内容を、次の場合にしかレンダリングしてはいけない。

クライアント側スクリプトをサポートしていないユーザエージェントは、この要素の内容をレンダリングしなければならない。

次の例では、SCRIPTを実行するユーザエージェントは動的に生成したデータをいくつか文書に組込み、スクリプトをサポートしないユーザエージェントでも、ユーザはリンクを通じてデータを取得できる。

<SCRIPT type="text/tcl">
 …データを組込むためのTclスクリプト…
</SCRIPT>
<NOSCRIPT>
 <P><A href="http://someplace.com/data">data.</A>にアクセスされたし。
</NOSCRIPT>

18.3.2 スクリプトデータをユーザエージェントから隠す

SCRIPT要素を認識しないユーザエージェントは、要素の内容をテキストとしてレンダリングしようとしがちである。 JavaScript、VBScript、並びにTclを含むいくつかのスクリプトエンジンは、スクリプトの命令文をSGMLコメントに囲い込むことを許容している。 そこで、SCRIPT要素を認識しないユーザエージェントはコメントを無視するが、マトモなスクリプトエンジンはコメント中のスクリプトを実行する必要があることを理解する。

問題を解決する別の方法は、スクリプトを外部文書とし、 src属性で参照することである。

JavaScriptでのコメント化スクリプト
JavaScriptエンジンは、SCRIPT要素の始めに文字列「<!--」が存在することを許容し、この場合当該行の末尾までの文字を無視する。 JavaScriptは、「//」を当該行の末尾まで続くコメントの開始であると解釈する。この「//」は、【SGMLコメントを閉じる】文字列「-->」をJavaScriptパーサから隠すために必要とされる。

<SCRIPT type="text/javascript">
<!--  to hide script contents from old browsers
  function square(i) {
    document.write("The call passed ", i ," to the function.","<BR>")
    return i * i
  }
  document.write("The function returned ",square(5),".")
// end hiding contents from old browsers  -->
</SCRIPT>

VBScriptでのコメント化スクリプト
VBScriptでは、単引用符によって、当該行の残りの部分がコメントとして扱われることとなる。そこで、単引用符が、VBScriptで「-->」を隠すために使われる。

   <SCRIPT type="text/vbscript">
     <!--
       Sub foo()
        ...
       End Sub
     ' -->
    </SCRIPT>

Tclでのコメント化スクリプト
Tclでは、「#」が当該行の残りの部分をコメントとする。

<SCRIPT type="text/tcl">
<!--  to hide script contents from old browsers
  proc square {i} {
    document write "The call passed $i to the function.<BR>"
    return [expr $i * $i]
  }
  document write "The function returned [square 5]."
# end hiding contents from old browsers  -->
</SCRIPT>

注意。 ブラウザの中には、最初の「>」という文字でコメントを閉じるものもある。こうしたブラウザからスクリプト内容を隠すためには、例えば「x > y」ではなく「y < x」と記すなど、関係演算子や移動演算子において被演算子を移項するといった手法や、各スクリプト言語固有の方法で「>」をエスケープするといった手法が取り得る。


訳者代表: 内田明 (UCHIDA Akira)
email: uchida@happy.email.ne.jp