(以前書いたことの再録です。)
e-Learning用のコンテンツを作っています。その中で、jsMathという数式を書くjavascriptを使っています。コンテンツごとに、このスクリプトを含めるのも無駄が多いので、特定の読み込み先を指定して、javascriptをそれぞれのコンテンツから分離したいと考えました。コンテンツはどのサーバーで利用するか分からないので、コンテンツごとにjavascriptの読み込み先を切り替えなければなりません。
普通では、javascriptを読み込むときには、下記のように、HTMLの中に直接書きます。
<SCRIPT SRC="http://192.168.100.191/jsMath/jsMath.js"></SCRIPT>
これだと、コンテンツごとにHTMLの記述を書き換えることになります。でも、できればこのHTMLが起動時に読み込むコンフィグファイルのようなものに、読み込み先が記入してあって、その記述に従ってjavascriptの読み込み先を切り替えるようにしたいのです。つまりjavascriptでjavascriptを読み込むといった感じです。下記はスクリプト読み込みようの関数(loadJS)を定めて、その関数に、読み込み先を与えています(読み込み先は、下記の記述では固定ですが、変数としておいて、任意のURLとすることは可能ですね)。
function loadJS(src) { var script = document.createElement('script'); script.src = src; document.body.appendChild(script); } loadJS("http://192.168.100.191/jsMath/jsMath.js");
ただ、この記述はHTMLに直接記述したScriptタグとは異なって、読み込みが完了する前に、この下に記述したScriptが実行されていきます。そのため、jsMathに規定された関数を実行しようとするとundefinedとなってしまいます(良くあるパターン)。
Script読み込みの完了を待たないといけません。待ち時間を作るために、whileループなども考えてみたのですが、上手く利用できず、パソコンがハングアップしそうになります。結局、下記にあるように、jQueryのfadeInとfadeOutを利用しました。fadeInにはフェードインが終了したときに実行する関数が記述できます。下記では特に名前のついていない関数を実行します(外に記述した名前のついた関数では上手くいかなかったのです)。
最初に(関数としての?)変数kaeruを記述して、最後の方で実行(呼び出し)しています。jsMath.Setupという関数の準備ができているかどうか調べて、良ければ実行して、まだ完了していなければ、もう一度関数が自分自身を呼び出しています。このとき再びfadeOutとfadeInを繰り返すので、cpuに負担をかけずに、待ち時間ができます。
var kaeru = function matu() { $("#wait").fadeOut(10); $("#wait").fadeIn(2000,function() { if (typeof(jsMath.Setup) == 'undefined') { return matu(); } else { $("#wait").hide(); jsMath.Setup.Script("plugins/tex2math.js"); } }); } kaeru();
今のところ、これで上手くいっています。
以下,追記です。下記は,多少開発の事情を知らないと分からない文章です。
以前はjsmathを利用するという計画で,上記のようなコードを書いていたのですが,これだとクロスドメインリクエストで問題が生じました。windowsのIEでクロスドメインリクエストをするには,両方のサーバーがhttpかhttpsで一致していないといけないことが判明しました。大学のサーバーがhttpsなので,こちらで用意する採点サーバーをhttpsにする必要がありました。これは多少手間がかかることと,自分の実力からみて時期尚早だと判断して,数式表示用のスクリプトをmathjaxに変更することにしました。mathjaxはhttpsのサイトが用意されています。これは公開されていて,誰でも利用できます。スクリプトのあるサイトが固定されますので,動的に読み込み先を変更する必要がありません。
ただ,スクリプトに限らず,読み込みの待ち時間は作る必要があります。こちらで用意する採点のサーバーと通信するには,やはりhttpsとhttpとの間でのクロスドメインリクエストをする必要がありました。採点サーバーの返信のヘッダーを修正することで対応できるブラウザもありますが,windowsのIEの場合には,それでは実現しなかったので他の方法を採用しました。flashを読み込んで,このflashに通信機能を持たせておいて,flash経由で通信をしています。そのため,ブラウザがIEであると判断したら,コンテンツはflashを読み込みます。このときにやはり待ち時間を作る必要があります。flash自体はコンテンツに含めているので,それほど読み込みに時間はかからないのですが,何らかの工夫は必要になります。