18 スクリプトScripts

この章の目次

  1. スクリプト概説(Introduction to scripts)
  2. スクリプト対応ユーザエージェントのための文書設計(Designing documents for user agents that support scripting)
    1. SCRIPT要素(The SCRIPT element)
    2. 使用スクリプト言語の明示(Specifying the scripting language)
    3. 内在イベント(Intrinsic events)
    4. 文書内容の動的変更(Dynamic modification of documents)
  3. スクリプト非対応ユーザエージェントのための文書設計(Designing documents for user agents that don't support scripting)
    1. NOSCRIPT要素(The NOSCRIPT element)
    2. スクリプトデータそのものが表示されてしまわないようにする(Hiding script data from user agents)

18.1 スクリプト概説Introduction to scripts

クライアント側スクリプトというのは、HTML文書に対して外部から協調して作業をしたり、あるいはHTML文書中に埋め込まれていたりするプログラムのことです。このプログラムは、当該文書が読み込まれた時点、あるいはリンクがアクティブにされたときなど何か他のタイミングで起動します。HTMLのスクリプト機能は、スクリプト言語の種別は問いません。

スクリプトを使うと、動きのあるHTML文書や、読み手に反応する文書を作成できます。例えば次のように。

HTML文書に添付できるスクリプトには、次の2つの型があります。

注。 スクリプト関連では、附記B.7に、スクリプトマクロに関する注記があります。

Designing documents for user agents that support scripting

この節では、スクリプトに対応しているユーザエージェントに関係する内容を記します。

The SCRIPT element

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

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

属性の定義

src = uri [CT]
外部スクリプトデータの所在を示します。
type = content-type [CI]
文書全体にとっての既定値であるスクリプト言語種を上書きし、この要素内で使用するスクリプト言語の種類を指定します。スクリプト言語種はMIMEタイプで(例えば"text/javascript"のように)記します。この値は必ず記さねばなりません。この値そのものには既定値はありません。
language = cdata [CI]
非推奨。 スクリプト言語種を指定するものです。属性の値は言語種の識別子ですが、標準規格としては確立しなかったので、上記typeを利用することを奨め、こちらは非推奨とします。
defer [CI]
この論理型属性を設定すると、ここで記されているスクリプトが文書の本文を生成するプログラムを含まないことをユーザエージェントに知らせることができます。(例えば「JavaScriptにおいて "document.write" を使用していない、など。)そこで、ユーザエージェントは、スクリプトの実行を待たずに、本文データをそのまま検定・表示していくことができるようになります。

他に使用可能な属性

HEAD要素中、あるいはBODY要素中に、何回でも記すことができます。

スクリプトそのものは、SCRIPT要素の内容として記すこともできますし、外部ファイルとして参照することもできます。src属性の設定がない場合、ユーザエージェントは「SCRIPT」要素の内容を、ここで扱うべきスクリプトであると解釈する必要があります。src属性の値がURIだった場合、ユーザエージェントは「SCRIPT」要素の内容を無視して指定先URIのファイルを参照する必要があります。charset属性で指定されている符号化方法は、src属性が指定する参照先ファイルの符号化方法を指定したものであって当該SCRIPT要素の符号化方法とは無関係であることに注意して下さい。

スクリプトは、ユーザエージェントに登録されている実行環境<script engines>によって検定・実行されます。

個々のスクリプトデータの記し方は、使用するスクリプト言語の文法に従うことになります。

18.2.2 使用スクリプト言語の明示Specifying the scripting language

HTMLには専属のスクリプト言語がありませんから、スクリプトを書く場合にはどのスクリプト言語を使用するかをユーザエージェントに明示する必要があります。明示する方法は、使用する基本スクリプト言語を一回宣言する方法と、文書中で逐一宣言する方法の2通りがあります。

基本スクリプト言語を示すThe default scripting language

ある文書中にスクリプトを利用する場合、使用するスクリプト言語をHEAD要素中でMETA宣言によってまとめて宣言しておくべきです。

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

上記の "type" の部分にスクリプト言語名をMIMEタイプで記します。例えば、 "text/tcl"、 "text/javascript"、 "text/vbscript" のように。

META宣言がなされていない場合、当該文書の基本使用スクリプト言語は、HTTPヘッダの「Content-Script-Type」によっても判定できます。

    Content-Script-Type: type

上記の "type" の部分にMIMEタイプでスクリプト言語名が記されます。

ユーザエージェントは、基本使用スクリプト言語が何であるかを、次の優先順位で判断する必要があります。

  1. META宣言によって「Content-Script-Type」が設定されていた場合、(列記されている)最後の型を基本スクリプト言語とする。
  2. 「META」宣言が無い場合、「HTTP」ヘッダにもし「Content-Script-Type」が設定されていれば、(列記されている)最後の型を基本スクリプト言語とする。

ベースとなるスクリプト言語を指定していないHTML文書で内在イベントが記されているものがあれば、それは文法的に正しくない文書です。ユーザエージェントはそのような文書のスクリプトも解釈しようと試みるでしょうが、仕様準拠基準として解釈が要請されているわけではありません。また、オーサリングツールはこのような文書を吐き出さないようにし、常に基本スクリプト言語の設定を行う必要があります。

スクリプト片ごとに言語種を宣言するLocal declaration of a scripting language

当該文書中に現れる全てのSCRIPT要素で、type属性を通じた使用言語の設定が必要なわけですが、基本スクリプト言語が宣言されていた場合、各SCRIPT要素での設定は基本使用言語を上書きします。

下の例では、基本スクリプト言語が「text/tcl」に設定されており、ヘッド部にあるSCRIPT要素は「text/vbscript」による外部スクリプトを参照するようになっています。ボディー部のスクリプトは「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="/someplace.com/progs/vbcalc">
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT type="text/javascript">
...JavaScriptのプログラム...
</SCRIPT>
</BODY>
</HTML>

スクリプト中から文書内の各要素を参照するReferences to HTML elements from a script

各スクリプト言語は、スクリプト中からHTML要素を参照するための手法を持っています。ただしこの仕様書ではその標準手法を定義したりはしません。

けれども、要素の参照は、その要素の固有名を目印にして行われるようにすべきだということは記しておきます。スクリプト実行環境<scripting engines>は、各要素の特定を行う場合、次の手順を踏んで下さい。目的となる要素にまずname属性とid属性の両方が設定されている場合はname属性の方を優先すること。片方しか設定されていない要素の場合は設定されている方を使うこと。

18.2.3 内在イベントIntrinsic events

注。 スクリプト機能を利用したい方へ。内在イベント絡みの規格は頻繁に変更され得ます(例えばスクリプトとイベントの結合方法など)。内在イベント絡みの話題はW3C Document Object Model Working Groupによって随時フォローされます。(詳しくはW3Cのサイト http://www.w3.org/ をご覧下さい。)

属性の定義

onload = script [CT]
onloadイベントは、ユーザエージェントが当該文書ウインドウ全体、あるいはFRAMESET文書中の全てのフレームの読み込みを終了した時点で発生します。この属性はBODY要素かFRAMESET要素に設定できます。
onunload = script [CT]
onunloadイベントは、ユーザエージェントが当該のウインドウやフレーム内の文書を消去する時点で発生します。この属性はBODYFRAMESET要素に設定できます。
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イベントは、表示中の当該要素がポインティングデバイスやタブキー移動によってフォーカスを受けた時に発生します。この属性は、A、AREA、LABELINPUTSELECTTEXTAREABUTTON要素に限り設定できます。[訳注。正誤表に基づき訂正済み。]
onblur = script [CT]
onblurイベントは、当該要素がポインティングデバイスやタブキー移動によってフォーカスを失った時に発生します。上記と同じ要素に設定できます。
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イベントは、コントロールがフォーカスを失った時点で、フォーカスを受けた時と比べて値が変化していた時に発生します。INPUTSELECTTEXTAREA要素にのみ設定可能です。

読み手がユーザエージェントを通して反応してくれることに対して、複数のイベントを連結させて1つの動作が起こるような文書を作成することも可能です。上に掲げた全内在イベントの値はスクリプトであり、それらのスクリプトは、イベントが発生する毎に動作を始めます。スクリプトの記述方法は各スクリプト言語の文法に依存します。

フォームのコントロールを表すINPUTSELECTBUTTONTEXTAREALABEL要素は、各々固有の内在イベントを発生させます。これらの要素をフォーム以外の部分で使用し、当該HTML文書のグラフィカルなユーザインタフェースとして機能させるような使い道もあり得ます。

例えば、フォームを送信する目的でなく、何か違う目的でサーバにデータを送ってもらうために文書中に押しボタンを設けたいという場合もあるでしょう。

ここで、内在イベントに基づいたユーザインターフェイス機能を実現可能なコントロール要素をいくつか例示します。

次の例では、テキスト入力窓「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 文書内容の動的変更Dynamic modification of documents

文書の読み込みと同時に動作するスクリプトは、文書の内容を動的に変更することが可能です。その能力はスクリプト言語自体に依存します。(例えば命令文「document.write」は、複数のベンダーがサポートしています。)

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

  1. 全てのSCRIPT要素が、文書の読み込み時に評価<evaluate>される。
  2. 読み込まれたSCRIPT要素でSGML CDATAを生成するようなスクリプトが、評価される。生成された文章は、文書中における当該SCRIPT要素の位置に挿入される。
  3. 生成されたCDATAが、再度評価される。

こうしたSCRIPT要素の処理の前後どちらにおいても、当該HTML文書は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 スクリプト非対応ユーザエージェントのための文書設計Designing documents for user agents that don't support scripting

この節では、スクリプトをサポートしないユーザエージェントでも理解可能な文書の設計方法について記します。

The NOSCRIPT element

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

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

このNOSCRIPT要素は、スクリプトが実行されない環境での代替物となる文章を記すために利用します。NOSCRIPT要素の内容は、スクリプトに対応するユーザエージェントにおいては、次の場合にのみ表示されることとなります。

クライアント側スクリプトをサポートしていないユーザエージェントは、「NOSCRIPT」要素の内容を表示する必要があります。

次の例文のような文書を読み込むと、SCRIPT要素の内容を実行できるユーザエージェントの場合は文書を動的に生成し、実行できないユーザエージェントの場合はリンクを表示し、リンクを辿ってデータを読んでもらうことになります。

<SCRIPT type="text/tcl">
 ...本文中にデータを追加するようなTclスクリプト...
</SCRIPT>
<NOSCRIPT>
 <P>Access the <A href="http://someplace.com/data">data.</A>
</NOSCRIPT>

18.3.2 スクリプトデータそのものが表示されてしまわないようにするHiding script data from user agents

SCRIPT要素に対応していないユーザエージェントの場合、その内容であるスクリプトデータそのものを普通の文章と一緒に表示してしまいがちです。JavaScript、VBScript、Tclを初めとするスクリプト実行環境は、スクリプトそのものをSGMLのコメントとして記せるような仕組みを備えています。そこで、コメントとして記しておけば、SCRIPT要素に対応していないユーザエージェントの場合はスクリプト内容を無視し、コメント式記法に対応しているスクリプト実行環境においてはスクリプト内容が実行されることとなります。

スクリプト内容を非対応ユーザエージェントから隠すための別の方法は、全スクリプトを外部データとして提供し、src属性による参照によって実行させる形をとることです。

JavaScriptでのコメント式記法
JavaScriptでは、「SCRIPT」要素の開始タグ直後の行頭に「<!--」が記してあれば、その行に書かれている内容を無視するお約束となっています。JavaScriptの言語体系でのコメントは、行頭に「//」を記した1論理行で表します。[スクリプト全体を非対応ユーザエージェントから隠すためにSGMLコメントとして記す場合] 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のコメントとなります。前記の伝で、SGMLコメントを閉じる部分は単引用符から始まる文として記します。

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

TCLでのコメント式記法

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>

注。 ユーザエージェントによっては 、[HTMLの] コメントが、[<-- に続くテキストデータの中で] 最初の「>」が現れた時点で閉じられていると解釈するものがあります。そこで、そのような [間抜けな] ユーザエージェントからスクリプトデータを隠すためには、命令の表記などを書き換えたり(例えば「x > y」と書く代わりに「y < x」と書くとか)、各スクリプト言語の流儀で「>」を置き換える方法を採るなどの必要があります。