FOT.load(ライブラリ読み込み) - fairy.ouchi.to


ソース


警告

この取説は現状の FOT.load 及び FOT.param の仕様に基づくものです。
今後 FOT.load, FOT.param の仕様が変更される可能性があります。


概要

FOT.load
引数で渡したFOTライブラリを読み込んで、完了後にコールバック関数を実行します。

FOT.param
location.href または document.currentScript のパラメータを返します。


基本的な使い方


# /js/fot/ にFOTライブラリ load.js, task.js, elm.js, event.js, event.css
# /js/ に実行するスクリプト user.js

<!-- HTML ここから -->

<script src="/js/fot/load.js"></script>
<script src="/js/user.js?id=tag_a&number=2"></script>

<!-- HTML ここまで -->

//===  user.js ここから ======

// "/js/user.js" のパラメータの読み込み
let param = FOT.param("script"); // param.id = "tag_a", param.number = "2"

// task.js, elm.js, event.js の読み込み終了後に main() を実行
FOT.load(main, "task,elm,event");

function main(error)
{
    if (error)
    {
        console.log("ライブラリ読み込み失敗:" + error.join(","));
        return;
    }

    // FOT.task, FOT.elm, FOT.event, FOT.Dialog が準備完了
    // ここからメイン処理
}

//=== user.js ここまで ======


関数一覧

ライブラリ読み込み
FOT.load
パラメータ読み込み
FOT.param

他の関数はありません。


ライブラリ読み込み

FOT.load

引数で指定したライブラリを読み込んでからコールバック関数を実行する。

FOT.load( function execute, string library_list );

execute:読み込み終了後に実行する関数。

library_list:ライブラリ名のカンマ区切り文字列

戻り値はありませんが、コールバック関数 execute に引数が渡されます。
全てのライブラリの読み込みに成功した場合、execute は引数なしで実行されます。
読み込みに失敗したライブラリがある場合、失敗したライブラリ名の配列が渡されます。


パラメータ読み込み

FOT.param

location.href または document.currentScript のパラメータを返す。

hash param = FOT.param( [ "script" ] );

"script":引数に "script" を渡した場合は document.currentScript が対象。
それ以外の場合は location.href が対象。

戻り値:対象のURLの ?key_a=val_a&key_b=val_b を { key_a : val_a, key_b : val_b } にしたオブジェクト。
対象が未定義の場合は undefined

参考:イベントハンドラなどから呼ばれたコールバック関数では document.currentScript は未定義となります。


仕様や設計方針などについてのあれこれ

このライブラリを使用する際に留意しておくべき事柄など。


FOT.load の動作

<script> 要素を作って src に引数のライブラリ名を設定して <head> に突っ込んで、 load イベントと error イベントを捕まえてます。で、全部返ってきたらコールバック関数を実行します。
付随するCSSがある場合(event.js + event.css)は、CSSも読み込みます。こっちはエラーなど無視して要素を突っ込むだけです。

複数のプログラムで連続して FOT.load を実行したり、同じライブラリを何度も読み込んだり、 load.js 自体を読み込んだりしても大丈夫なはずです。重複は単に無効になります。

ライブラリのバージョン管理とか、ハンドル FOT にちゃんと設定されたかとか、 そういった面倒なことは一切やってないので、FOTライブラリ以外も普通に読み込みできるはずですが、 ファイルを load.js と同じ場所に置かなければならないのでオススメはしません。


FOT.param の動作

標準クラスのURL()に引数で指定された対象のURLを渡して URL.searchParams で取り出してます。

searchParams をそのまま返さないのは、param.get("id") より param.id の方がいいので :-)
一応、コンテナは Object.create(null) で作ってますが、 ライブラリ自体が Object を直接いじるようなプログラムとの併用を前提にしてないので単なる気休めです。


共存の理由

動作そのものは FOT.load と FOT.param でそれぞれ完全に独立しています。
load.js と param.js で別ファイルにしてそれぞれ個別に使っても動作はします。

問題は、documemt.currentScript をコールバック関数から呼び出した場合に未定義になることで、 この仕様がある以上、FOT.param("script") は必ず FOT.load() より前に実行する必要があります。
そうすると、load.js の前に param.js を読み込む必要があることになり、 それでは load.js の意味がないので1つのファイルにしています。


ソース

何やってるか知りたい人なら、中身を見れば分かる程度には単純なはずですが、 クロージャの挙動に慣れてないと流れが把握しにくいかもしれません。

FOT.load では「関数が呼ばれるたびにクロージャを作って配列に保存することで、 複数のクロージャを作ってそれをイベントハンドラから実行する」という、 JavaScriptや同種の言語をよく知らない人には、見ただけでは何やってるんだか分からないことをしています。
作ったわたし自身、作って試して動作の意味を考え直して、 それでようやく「あ、これでいいんだ」と理解したぐらい。


何で作ったの?

このサイトのプログラムが大きくなってきて、共通関数をちょこちょこ切り離してライブラリ化していたものの、 複数ファイルに分割すると <head> 内に <script> を列挙することになるし、 ページごとに使うライブラリが違うとなれば判別する必要もあるわけで、邪魔くさいなと。
そういうことを管理する仕組みをPHP側に仕込んだこともありましたが、 そもそもJavaScriptのどのライブラリを使うかなんてのは、 それを利用するJavaScriptのプログラム自身に書いてあるべきなので、それで済むように作った次第。

FOT.param を作ったのは "script" オプションのためです。
プログラムの実行でHTML側の特定の要素を指定する必要があってidを設定したものの、 設定したidをプログラム側にベタ書きするのは気持ち悪い。
だったらidをHTML側で <script src="/js/user.js?id=tag_a"> として、 プログラム側でそれを読めばいいと。

なので、この2つは機能は全く別ですが、本質的には全く同じ目的で作ったものです。
プログラムの都合で変わること(=使うライブラリ)は、プログラム内の記述だけで完結させる。
HTML側の都合で変わること(=設定したid名)は、HTML側の記述だけで完結させる。
どちらかを変更しても、その影響でもう一方に変更箇所が発生しないように、切り離して独立させるための機能です。