ブラウザとの対話

概要

Curl® 実行環境 のコンポーネント、Curl® プラグインは、Web ブラウザ内で Curl® 言語で書かれたアプレットを実行します。アプレットとブラウザのインタラクションや、ロードに使用された URL などのアプレットに関する情報を取得する場合がよくあります。Curl 言語には、アプレットがブラウザと対話できる方法がいくつかあります。

アプレットの表示

要約:
  • アプレットをそれ自体で表示したり、HTML ページ内に埋め込むことができます。
  • ブラウザが直接ロードしたアプレットは、ディスプレイ領域全体を占有します。
  • アプレットは、OBJECT タグで HTML ページに埋め込むことができます。
ブラウザで Curl アプレットを表示する際には、次の 2 つのオプションあります。
HTML ページから Curl アプレットへのリンクを作成する場合は、アプレットのメイン (.curl) ファイルにリンクを直接作成し、アプレットがブラウザのディスプレイ領域全体に表示されるようにすることができます。Curl® 言語で書かれたコンテンツを提供できるように Web サーバーが適切に構成されている限り (「Web サーバーの構成」参照)、ブラウザはアプレットをロードして、アプレットにディスプレイ領域全体のコントロールを与えます。
ディスプレイ領域内の既存フレームにアプレットを表示することもできます。この場合、ユーザーがクリックしてアプレットをロードできるようにリンク先にフレームの名前を指定します。

アプレットのドキュメント

アプレットが描写するコンテンツは Document で保持されます。これは、描写されるコンテンツを特定の方法で表示するメカニズムです。通常はドキュメントを作成する必要はなく、アプレット ファイルをブラウザにロードするときに自動的に作成されます。
ただし、アプレット ファイルで document-style を呼び出してドキュメントのスタイルを設定することは可能です。Document には次の 3 つのタイプ/スタイルがあります。


各 Document スタイル/タイプは、ブラウザで異なる種類のグラフィカル オブジェクトを表示します。ドキュメント機能へのアクセスが必要な場合は、アプレットの Applet.document プロパティを使って取得することができます。詳細は各ドキュメント タイプの API ドキュメントを参照してください。
ドキュメント スタイルが設定されていないアプレットでは、描写されるコンテンツの DefaultDocument を作成します。

HTML ページ内でのアプレットの埋め込み

HTML の <OBJECT ...> タグを使用して、HTML ページにアプレットを埋め込むことができます。他の埋め込みコンテンツと同様に、アプレットは HTML ページの四角い領域に表示されます。
HTML の <OBJECT ...> タグの部分的な構文は次のとおりです。
構文: <OBJECT DATA="applet URL" [HEIGHT= height] [WIDTH=width] [TYPE="mime type"]> </OBJECT>
説明:
applet URL Curl アプレットのメイン ファイルの URL です。
width プラグイン領域の幅です。ディスプレイ領域全体に対する幅のパーセント表示 (55% など)、またはピクセル数で指定します。
height プラグイン領域の高さをピクセル数で指定します。
mime type 埋め込まれているコンテンツの MIME タイプです。Curl コンテンツの場合、これは必ず "text/vnd.curl" になります。
要求されたプラグインのソースコードに URL を含めたい場合があります。 start.curl アプレット(HTML ファイルと同じディレクトリにある)を幅 700 ピクセル、高さ 500 ピクセルのスペースに埋め込むには、以下のものを HTML ファイルに挿入してください。
<OBJECT DATA="start.curl" TYPE="text/vnd.curl" HEIGHT=500 WIDTH=700>
    You need to install the
    <a href="http://www.curl.com/download/rte/">Curl RTE</a>
    to run this applet.
</OBJECT>
    
<OBJECT ...> タグの完全な構文については、HTML に関する包括的なマニュアルを参照してください。
Curl 統合開発環境 で HTML に埋め込まれたアプレット プロジェクトを作成することにより、HTML ページにアプレットを手動で埋め込む手間が省けます。新規プロジェクトには、新しいアプレット ファイルとそれを埋め込む HTML ページが含まれます。
OBJECT タグで、クライアントマシンに Curl RTE プラグインがインストールされているかどうか判定することができ、インストールされていない場合、ユーザーにアクションを示すことが出来ます。インストールされている RTE のバージョンが、ロードされようとしているアプレットが要求するものと異なる場合、RTE は、ユーザーに正しいバージョンをダウンロードするように促すダイアログを表示します。
アプレットが埋め込まれている HTML ページにスクリプトを追加することでより高度に RTE を判定することが出来ます。そのようなスクリプトのサンプルが以下の場所にあります。
d:\automated-build-temp\build\win32-atom\docs\default\examples\dguide\detect-plugin.zip
この .zip ファイルの使い方に関する情報は、拡張したサンプル をご覧ください。
このサンプルは、RTE の存在を確認し、アプレットが異なるバージョンを必要とする場合には、その事をユーザーに伝える為に RTE を使います。サンプルは、Curl RTE の判定に関する他の問題も示しています。RTE がインストールされている時に、アプレットの実行を妨げるので、RTE の判定を失敗したくありません。Internet Explorer には、RTE の判定をブロックする可能性があるセキュリティ設定項目があります。またユーザーはスクリプト言語の実行を停止している可能性もあります。このサンプルは、RTE 判定メカニズムのテストも含んでいます。
Curl RTE の特定のバージョンをチェックすることもできます。以下のコードは、バージョン識別の基本を示しています。この場合は、Curl 8.0 です。数字を変えて他のバージョンをチェックすることもできます。例えば、curl_7_0 は、Curl RTE 7.0 をチェックします。
<script language="JavaScript">
    curl = false
    curl_8_0 = false
  </script>

  <script language = "VBScript">
    on error resume next
    curl = NOT IsNULL(CreateObject("Curl.Surge"))
    curl_8_0 = NOT IsNULL(CreateObject("Curl.Surge.8.0"))
  </script>

    <script language = "JavaScript">
     if (navigator.mimeTypes && navigator.mimeTypes.length)
     {
       x = navigator.mimeTypes["text/vnd.curl"];
       if (x && x.enabledPlugin)
       {
         curl = true;
       }
       x = navigator.mimeTypes["text/vnd.curl.surge.8.0"];
       if (x && x.enabledPlugin)
       {
         curl_8_0 = true;
       }
     }
     else if (navigator.plugins && navigator.plugins.length)
     {
       x = navigator.plugins["Curl RTE 8.0 Plug-in"];
       if (x)
       {
         curl = true;
         curl_8_0 = true;
       }
     }

    </script>
また、埋め込まれた Curl アプレットがどのように親 HTML ページの中の Javascript 機能を呼び出すことができるか、および HTML ページがどのように埋め込まれたアプレットの中の Javascript 機能を呼び出すことができるかについて述べられている、「サブアプレットとJavascript サポート」のセクションも参考にしてください。外部ソースから Curl アプレットを埋め込む時にも注意してください。Curl アプレットは HTML ページ内の Javascript を実行することができます。それはアプレットがアクセスできないコンテンツにアクセスすることができるからです。

Curl 言語リンクとブラウザ

要約:
  • 他のコンテンツにリンクするには、link テキスト プロシージャを使用します。
  • link のオプションである target パラメータを使用し、新しいコンテンツのロード先を制御できます。
  • アプレット内のリンクをクリックすると、ブラウザの履歴に反映されます。
アプレットの内部から、HTML ページやブラウザで表示可能なその他のコンテンツ (イメージやテキスト ファイルなど) 、さらに他の Curl アプレットにリンクすることができます。リンクを作成するには、標準 link テキスト プロシージャを使用します。

例: Web サイトへのリンク
Here is a link to {link href={url "http://www.curl.com/"}, the Curl Web
                      site}.
既定では、ユーザーがリンクをクリックしたときにロードされるコンテンツによりアプレットが更新されます。アプレットが HTML ページに埋め込まれている場合、別のアプレットまたは HTML ページへのリンクは、アプレットが占める領域だけではなく、HTML ドキュメント全体を新しいコンテンツと置き換えます。
link プロシージャのオプションの target パラメータを使用し、新しいコンテンツのロード先を制御することができます。Curl 言語が認識可能なターゲットの詳細は、後述の「新しいページを開く」を参照してください。
リンク先となるドキュメント内の位置を識別する destination テキスト プロシージャを使って、アプレットにリンクを作成することができます。シャープ記号 (#) の後に URL としてリンク先の名前を挿入して、リンクを作成します。次に例を示します。
{destination name="top-of-document"}
{paragraph Welcome to my document...}

|| ... later in the same applet ...
{paragraph
    Go to {link href={url "#top-of-document"} the top of the
    document}.
}

プラグインがブラウザ履歴に与える影響

Web ブラウザは、ユーザーが最近訪問したページの履歴を保持します。ユーザーが新しいページを参照すると、そのページが履歴リストの最上位 (ゼロ番目の位置) に追加されます。同様に、Curl プラグインはアプレットを Web ブラウザの履歴リストに追加します。履歴の更新によって、HTML ページとアプレットを交互に参照している間も、ブラウザ上の [戻る] および [進む] ボタンは適切に動作します。したがって、HTML ページとアプレットの間を相互に移動できます。
アプレット内のリンクはブラウザの履歴に反映されません。このため、アプレット内で 1 つ以上のリンクをクリックしてからブラウザの [戻る] ボタンを押すと、アプレット内の最後のリンク先ではなく、アプレットをロードする前に訪問したコンテンツに戻ります。

アプレット クラス

要約:
  • Applet クラスの document および url アクセッサにより、アプレット自体の情報が得られます。
  • set-title および set-status メソッドを使用して、ブラウザのタイトル バーとステータス行を制御できます。
  • browse-url メソッドを使用して、新しいコンテンツをロードするようブラウザに指示します。
Applet クラスは、アプレットと 外部の世界 と間のインターフェイスを作成します。このインターフェイスを介して、アプレットはそれ自体の情報を取得したり、ロードしているブラウザと対話することができます。
注意: アプレットには、Applet クラスを定義するパッケージ CURL.IMPLICIT.APPLET が自動的にインクルードされます。他のパッケージには自動的にインクルードされません。したがって、パッケージで Applet クラスを使用する必要がある場合は明示的にインポートしてください。
アプレットは最初にそれ自体を表す Applet クラスのオブジェクトをインスタンス化する必要があります。次のように get-the-applet プロシージャを呼び出します。
{do
    let my-applet:Applet = {get-the-applet}
}
この Applet オブジェクトで、次のアクセッサを使ってアプレットに関する情報を取得します。
アクセッサ
目的
{Applet.document}
このアプレットの精巧なフォームの Document オブジェクトを返します。Document クラスでは、アプレットがどのように表示されるかをさまざまな方法で操作することができます。このクラスの使い方は、『API リファレンス』の Document の項目を参照してください。
{Applet.url}
現在実行しているアプレットのトップ レベル ファイルの URL を表す Url オブジェクトを返します。このアクセッサの実際の呼び出しがインクルードされたファイル内にある場合、インクルードされているファイルではなく、インクルード側のファイルの URL を返します。
Applet クラスには、アプレットを表示するブラウザとアプレットとの対話を可能にする以下のメソッドが含まれています。
メソッド
目的
{Applet.set-title title:String}
ブラウザのウィンドウ タイトルを title に設定します。
アプレットが HTML ページに埋め込まれている場合、このメソッドの効果はありません。
{Applet.set-status status:String}
ブラウザのステータス行に表示されるテキストを status に設定します。このメソッドを PointerEnter イベントと使用して、ユーザーがオブジェクトをクリックしたときに何が起こるかを表示することができます。(またはこのメソッドを使用して、ステータス行にスクロール メッセージを流しつづけることも可能です。)
{Applet.browse-url url:Url, target:String="_self"}
指定した url をブラウザでロードします。target キーワード引数が指定されている場合、url は指定されたウィンドウまたはフレームにロードされます。このパラメータの詳細については、「新しいページを開く」を参照してください。
以下のセクションで、これらのメソッドの使用方法を示します。

ウィンドウ タイトルおよびステータス行の設定

Applet.set-title および Applet.set-status メソッドを呼び出し、テキストをブラウザ ウィンドウのタイトル バーおよびステータス行に表示する方法を次の例で示します。これらのメソッドは、次の例の [Execute] ボタンをクリックして表示するダイアログ ウィンドウなどでは効果がありません。このダイアログ ウィンドウの代わりに、親ウィンドウのタイトルおよびステータス行が設定されることになります。View クラスを使用して開いたウィンドウのタイトルを変更するには、View.title メソッドを使用します。
この例では、[Set It] ボタンをクリックした場合にブラウザのタイトル バーおよびステータス行に表示されるテキストを入力できます。

新しいページを開く

ユーザーがアプレット間を移動できるように、標準 link テキスト プロシージャを使用してハイパー リンクを作成することができます。ただし場合によっては、ユーザーがリンクをクリックしなくても Curl アプレットが別のアプレットまたは他のコンテンツをロードできるような状況があります。たとえば、時間をずらして次々とアプレットが自動的にロードされるようなスライド ショーを作成したり、新しいアプレットを別のウィンドウで開くための CommandButton を挿入する場合などです。
Applet.browse-url メソッドは、link テキスト プロシージャと同様に Url とオプションの target キーワード引数を取ります。ただし、Applet.browse-url ではブラウザが新しいコンテンツを直ちにロードするという点で link とは異なります。target 引数は HTML リンクのターゲット属性と本質的に同じで新しいページのロード先を制御するものです。ターゲットは次のいずれかの文字列になります。
ターゲット名
説明
_blank
新しいウィンドウでページを開きます。
_parent
現在のファイルの親にあたる場所でページを開きます。現在のページがフレームセット内にある場合、新しいページはフレームセットを置き換えます。現在のページが最上位にある (フレームがない) 場合は、新しいページは現在のページを置き換えます。
_self
現在のページを新しいページで置き換えます。 現在のページがフレーム内にある場合は、そのフレームのみが更新されます。
_top
現在のブラウザのトップレベル ウィンドウでページを開きます。ブラウザ ウィンドウにあるすべてのフレームは新しいページで上書きされます。
Applet.browse-url の使用により、ユーザーがリンクをクリックするのと同じ効果が得られます。つまり、新しいコンテンツがブラウザの履歴の最上位に追加されます。このメソッドを呼び出した後は、新しいコンテンツがロードされる前にイベント ハンドラを実行しない限り (register-suspend-proc または on-applet-suspend を使用して作成)、アプレット内では何も起こりません。詳細は、後述の「アプレットの一時停止と再開」を参照してください。
次の例では、Applet.browse-url メソッドを使用して新しいコンテンツを表示しています。このメソッドには、TextField で指定された Urltarget パラメータが与えられます。メソッドを実行するにはコードをコピーして新しい .curl ファイルに貼り付けます。ファイルを保存してブラウザで開きます。
{curl 8.0 applet}

{value
    let url-text:TextField = {TextField value="http://www.curl.com/"}
    let target-text:TextField = {TextField width=3in, value="_blank"}

    let open-button:CommandButton =
        {CommandButton label = "Open",
            {on Action do ||Open the page
                let target-url:Url = {parse-url url-text.value}
                || Directly use the Applet object returned by {get-the-applet}
                {{get-the-applet}.browse-url
                    target=target-text.value,
                    target-url
                }

            }
        }
    ||Display the controls
    {VBox {HBox {text URL to display:}, url-text},
          {HBox {text Target:}, target-text},
          {HBox open-button}
    }
}

アプレットの一時停止と再開

ユーザーがアプレットから離れた場合 (リンクのクリック、アプレットによる他のコンテンツのロード、ブラウザの [戻る] または [進む] ボタンの使用など)、アプレットは一時停止状態になります。一時停止のアプレットは、ブラウザが新しいコンテンツをロードしたときの状態でフリーズしています。アプレットが使用していたリソースの一部はシステムに返されますが、アプレット自体はそのままです。このアプレットは、再開またはメモリから除去されるまで一時停止状態を続けます。
ユーザーがブラウザの履歴コマンドの 1 つ ([戻る] ボタンなど) を使ってアプレットに戻ると、アプレットが再開します。アプレットから離れた時点から再開されます。通常、アプレット自体は一時停止して再開したことを認識してません。
アプレットが停止した時に進行中の非同期 HTTP 操作がある場合、この操作は途中停止され、 HttpException の含まれているイベントが送信されます。 同期 HTTP 操作は、アプレットが request-browser-resident-http を呼び出さない限り、その操作が完了するまでアプレットの停止を遅らせます。 アプレットが request-browser-resident-http を呼び出す場合は HttpException がスローされます。 非同期の操作のイベントはアプレットが再開した時に処理されます。アプレットが停止している時に開いている HTTP ストリームはいずれも閉じられます。
ユーザーがブラウザを終了すると同時に、アプレットはメモリから除去されます。多数のアプレットが一時停止になっていた場合は、Curl 実行環境 も起動してアプレットをメモリから除去します。この操作により使用中のメモリを減らし、新しいアプレットが実行できるようにリソースを解放します。メモリから除去されたアプレットをユーザーが参照しようとすると、アプレットは最初からロードされ、古いアプレットの状態に関する情報は含まれていません。
メモリから除去される前にアプレットは警告を受けないため、除去前には何も実行できません。ただし、一時停止プロシージャ を使用して、一時停止または再開の直前にアプレットで操作を実行することができます。これによりアプレットは、データを保存してリソースを解放し、メモリからの除去に備えてその他の必要な操作を実行することができます。
一時停止プロシージャ内でアプレットが実行できない操作がいくつかあります。一時停止プロシージャが呼び出されたときにはアプレットはすでにブラウザに表示されていません。したがって、表示に関する変更は実行できません。アプレットは、ファイルまたはネットワークの非同期アクセスのような非同期のアクションも実行できません。これは、アプレットが一時停止プロシージャを実行した後ではアクションを実行できないからです。アプレット自体が一時停止状態を回避する方法はありません。
一時停止プロシージャの一番簡単な作成方法は、on-applet-suspend の使用です。
{on-applet-suspend do
    || perform actions the applet needs to do before suspension
}
       
アプレットが一時停止される前に、on-applet-suspend 内のコードが呼び出されます。on-applet-suspend を複数回呼び出し、複数の一時停止プロシージャを登録することもできます。これらのプロシージャは、追加された順番の逆 (最後に追加されたものが一番先) で呼び出されます。
一時停止プロシージャと同様に、アプレット再開時に呼び出すプロシージャの登録には、 on-applet-resumeregister-resume-proc の二種類の方法があります。 これらは本質的には一時停止プロシージャと同じですが、追加された順序で呼び出される点が異なります。 register-resume-proc によって登録された再開プロシージャは、後で unregister-resume-proc を使って登録を解除できます。
ネットワーク接続のようなシステムリソースを、短い間使用しなければいけない場合があるとします。 アプレットがシステムリソースを使用している際に、アプレットが停止(再開する場合も含む)場合があります。 アプレットが停止している場合は、貴重なシステムリソースを無期限的に保持せずにリリースし、 再開した場合に再び獲得するのがよい方法です。これを達成するには、 停止または再開しているプロシージャが、リソースを随時リリースしそして再獲得 するよう、オブジェクトを使ってリソースを管理することが簡潔な方法です。 さらに、停止または再開しているプロシージャを登録することにより、 オブジェクトがガーベッジコレクトされなくなるため、 いつそのリソースを使用するのかを指摘する必要があります。 それには、リソースをリリースしそして再獲得するメソッドを明示的に呼び出すか、または、 コンストラクタでリリースを再獲得し、リソースの使用後に明示的に destroy を呼び出します。
以下の例では、オブジェクトが作成された時にリソースを獲得し、プロセスが停止した際にリリースし、 プロセスが再開した際に再獲得し、リソースが必要なくなった時に destroy メソッドを呼び出しています。
{define-class ResourceUser

  field constant suspend-proc:{proc-type {}:void}
  field constant resume-proc:{proc-type {}:void}

  || Put some fields here to track the resources.

  {method {acquire-resources}:void
    || Put some code here to acquire the resources.
  }

  {method {release-resources}:void
    || Put some code here to release the resources.
  }

  {method {destroy}:void
    {unregister-suspend-proc self.suspend-proc}
    {unregister-resume-proc self.resume-proc}
    {self.release-resources}
  }

  {constructor {default ...}

    set self.suspend-proc =
        {proc-type {}:void
            {self.release-resources}
        }
    {register-suspend-proc self.suspend-proc}

    set self.resume-proc =
        {proc-type {}:void
            {self.acquire-resources}
        }
    {register-resume-proc self.suspend-proc}

    {self.acquire-resources}
  }
}
register-exit-proc を使って、アプレットの終了時に呼び出すプロシージャを登録することもできます。 終了プロシージャは unregister-exit-proc により、後に登録を解除することができます。

複数アプレットの一時停止と再開

一時停止プロシージャと再開プロシージャはアプレット内で特定の順序で実行されますが、一時停止状態のアプレットの一時停止プロシージャが、再開されるアプレットの再開プロシージャの前に実行されるとは限りません。したがって、共有パーシスタント データとともにこれらを使用する場合は問題が発生する可能性があります (パーシスタント データの詳細は、「クライアント側パーシスタント データ」を参照してください)。
たとえば、アプレット A と B が同じ共有パーシスタント データ リポジトリを使用するとします。ユーザーがブラウザの [戻る] ボタン をクリックしてアプレット B からアプレット A に戻ると、アプレット B の一時停止プロシージャは一時停止前にパーシスタント データ リポジトリに加えられた変更をコミットします。さらに、アプレット Aの再開プロシージャにより共有パーシスタント データ リポジトリが再度読み込まれ、データの変更があったかどうかを調べます。ただし、アプレット B の一時停止プロシージャはアプレット A の再開プロシージャの前に実行されるとは限らないため、アプレット A はアプレット B が変更をコミットする前の古いデータをリポジトリから読み込む可能性があります。