18 スクリプト

18.1 スクリプトへの導入

クライアント側のスクリプトは,HTML文書に付随するか,又はHTML文書に直接に埋め込まれるプログラムとする。そのプログラムは,文書がロードされる場合か,又はリンクが活性化されるなどのそれ以外の時に,クライアントのマシン上で実行される。HTMLのスクリプトのサポートは,スクリプト言語には依存しない。

スクリプトは,高度に活動的であってしかも対話的な方法で,HTML文書を拡張する手段を文書作成者に提供する。その例を次に示す。

文書作成者がHTML文書に添付してよいスクリプトには,次の2種類がある。

備考  この標準情報(TR)は,スクリプトマクロに関する箇条で,スクリプトに関するより詳細な情報を扱う。

18.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"などの内容型として指定される。文書作成者は,この属性に対する値を提供しなければならない。この属性に対するデフォルト値は存在しない。
language = cdata [CI]
推奨しない。 この属性は,この要素の内容のスクリプト言語を指定する。その値はスクリプト言語のための識別子だが,これらの識別子は標準化されていないので,typeを利用することが望ましく,推奨しない
defer [CI]
設定される場合,この論理的属性は,例えばjavascriptの"document.write"とは違い,スクリプトが文書内容を生成しないということを,利用者エージェントに提供する。したがって,利用者エージェントは,構文解析及びレンダリングを続行することができる。

他の箇所で定義される属性

SCRIPT要素は,文書内にスクリプトを置く。この要素は,HTML文書のHEAD又はBODYで何度も現われてよい。

スクリプトは,SCRIPT要素の内容の中,又は外部ファイルで定義してよい。src属性が設定されない場合,利用者エージェントは,要素の内容をスクリプトとして解釈しなければならない。srcがURI値をもつ場合,利用者エージェントは,要素の内容を無視し,そのURIを介してスクリプトを取得しなければならない。charset属性は,src属性によって指定されるスクリプトの文字符号化を参照する点に注意すること。charset属性は,SCRIPTの内容には関係しない。

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

スクリプトデータの構文は,スクリプト言語に依存する。

18.2.2 スクリプト言語の指定

HTMLは特定のスクリプト言語に依存しないので,文書作成者は,利用者エージェントに各スクリプトの言語を明示的に知らせなければならない。デフォルト宣言又は局所宣言のいずれかを通じて,これを行ってよい。

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

文書作成者は,次のMETA宣言をHEADに含めることによって,文書におけるすべてのスクリプトに対してデフォルトのスクリプト言語を指定することが望ましい。

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

ここで,"type"は,スクリプト言語を命名する内容型とする。値の例としては,"text/tcl","text/javascript","text/vbscript"などがある。

META宣言がない場合,デフォルトは,"Content-Script-Type" HTTPヘッダによって設定できる。

    Content-Script-Type: type

ここでの"type"も,スクリプト言語を命名する内容型とする。

利用者エージェントは,次の手順に従って,文書に対するデフォルトスクリプト言語を決定するのがよい。手順は,優先順位の高いものから列挙する。

  1. META宣言が"Content-Script-Type"を指定する場合,文字ストリームにおける最後のMETA宣言が,デフォルトスクリプト言語を決定する。
  2. そうでない場合であって,HTTPヘッダが"Content-Script-Type"を指定する場合は,文字ストリームにおける最後のHTTPヘッダが,デフォルトスクリプト言語を決定する。

デフォルトスクリプト言語情報を指定せず,組込みイベントスクリプトを指定する要素を含む文書は,不正とする。利用者エージェントは,不正に指定されたスクリプトを解釈しようと試みてもよいが,そうする必要はない。作成ツールは,デフォルトスクリプト言語情報を生成し,文書作成者が不正な文書を生成しないように支援することが望ましい。

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

type属性を介して,各SCRIPT要素におけるスクリプト言語を指定することもできる。デフォルトスクリプト言語指定が存在しない場合には,この属性を,各SCRIPT要素に設定しなければならない。デフォルトスクリプト言語が指定されている場合には,type属性が,この指定を上書きする。

次の例では,デフォルトスクリプト言語を"text/tcl"と宣言する。ヘッダには,SCRIPTが一つ含まれるが,そのスクリプトは外部ファイルに置かれており,スクリプト言語"text/vbscript"で記述されている。本体にもSCRIPTを一つ含まれており,"text/javascript"で書かれたスクリプトを含んでいる。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
     "http://www.w3.org/TR/REC-html40/strict.dtd">
<HTML>
<HEAD>
<TITLE>A document with SCRIPT</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">
...some JavaScript...
</SCRIPT>
</BODY>
</HTML>

スクリプトからのHTML要素への参照 

各スクリプト言語には,スクリプト内からHTMLオブジェクトを参照するための,それ自体の規約がある。この標準情報(TR)は,HTMLオブジェクトを参照するための標準的な機構を定義しない。

しかし,スクリプトは,割り当てられた名前に従って,要素を参照することが望ましい。スクリプトエンジンは,要素を識別する場合,次の優先順位規則に従うのがよい。すなわち,name属性及びid属性の両方が設定されている場合には,name属性が優先する。そうでない場合は,どちらを使用してもよい。

18.2.3 組込みイベント

備考  HTML文書の作成者には,スクリプトがどのようにイベントと結び付けられているかなど,変更が組込みイベントの領域で発生することが多いと忠告しておく。この領域の研究は,W3C文書オブジェクトモデル作業グループのメンバによって行われている。さらに情報を入手したい場合は,http://www.w3.org/でW3Cウェブサイトを参照のこと。

属性定義

onload = script [CT]
onloadイベントは,利用者エージェントがウィンドウ又はFRAMESET内のすべてのフレームのロードを終了する場合に発生する。この属性は,BODY要素及びFRAMESET要素と共に使用してよい。
onunload = script [CT]
onunloadイベントは,利用者エージェントがウィンドウ又はフレームから文書を除去する場合に発生する。この属性は,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イベントは,要素がポインティング装置又はタブナビゲーションのいずれかによって注目点を受信する場合に発生する。この属性は,次の要素と共に使用してよい。すなわち,LABEL, INPUT, SELECT, TEXTAREA, 及びBUTTON
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イベントは,制御が入力注目点を失い,さらにその値が注目点を獲得して以来変更されている場合に発生する。この属性は,INPUT, SELECT, 及びTEXTAREA
の各要素に適用される。

利用者が利用者エージェントと対話する場合に発生するイベントの幾つかと動作とを関連付けることができる。上に列挙されている各"組込みイベント"は,スクリプトである値をとる。スクリプトは,その要素に対してイベントが発生する場合,常に実行される。スクリプトデータの構文は,スクリプト言語に依存する。

INPUTSELECTBUTTONTEXTAREALABELなどの制御要素は,すべてある組込みイベントに応答する。これらの要素がフォーム内に現われない場合には,これら要素を文書の図形的利用者インタフェースを強化するために使用してよい。

例えば,文書作成者は,活性化した場合に,フォームを実行依頼しないがサーバと通信する押しボタンを文書に含めたいと考えてもよい。

次の例は,組込みイベントに基づいた,可能な制御及び利用者インタフェースの振る舞いを示す。

この例では,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. SGML CDATAを生成する一定のSCRIPT要素内のすべてのスクリプト構成要素が,評価される。結合され生成されるテキストは,SCRIPT要素の代わりに文書に挿入される。
  3. 生成されたCDATAは,再評価される。

HTML文書は,いかなるSCRIPT要素を処理する前及び後の両方で,HTML DTDに適合するように制約される。

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

 <TITLE>Test Document</TITLE>
 <SCRIPT type="text/javascript">
     document.write("<p><b>Hello World!<\/b>")
 </SCRIPT>

これは,次のHTMLマーク付けと同じ効果をもつ。

 <TITLE>Test Document</TITLE>
 <P><B>Hello World!</B>

18.3 スクリプトをサポートしない利用者エージェントのための文書設計

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">
 ...some Tcl script to insert data...
</SCRIPT>
<NOSCRIPT>
 <P>Access the <A href="http://someplace.com/data">data.</A>
</NOSCRIPT>

18.3.2 利用者エージェントからのスクリプトデータ隠ぺい

SCRIPT要素を認識しない利用者エージェントは,その要素の内容をテキストとしてレンダリングしようとする。JavaScript, VBScript及びTclのスクリプト言語のものを含むスクリプトエンジンは,スクリプト文をSGML注釈で囲むことができる。したがって,SCRIPT要素を認識しない利用者エージェントは,この注釈を無視するが,高機能のスクリプトエンジンは,注釈の中のスクリプトを実行した方がよいと理解する。

問題を解決する他の方法としては,スクリプトを外部文書に保持しておき,src属性を用いてそれらを参照する方法がある。

JavaScriptにおけるスクリプトの注釈化。
JavaScriptエンジンは,文字列"<!--"をSCRIPT 要素の始めに発生させ,行の終了までの更なる文字を無視することができる。JavaScriptは,現在の行の終了まで続く注釈を開始するものとして"//"を解釈する。これは,文字列"-->"を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"を使用するなど,関係演算子及びシフト演算子に対してオペランドを入れ換えたり,又は">"に対してスクリプト言語依存の別扱い表記を使用することができる。