DokuWiki

It's better when it's simple

ユーザ用ツール

サイト用ツール


ja:devel:javascript

JavaScript

DokuWikiは、ユーザーエクスペリエンス(機能や操作性)を向上させるため、JavaScriptを利用しています。すべてのJavaScriptのファイルはHTTPリクエストを最小限に抑えるために、ひとつのディスパッチャを通してクライアントへ送られます。この方法はstylesheetsと同様で、まとめられたファイルはキャッシュ・圧縮(minify)されます。

このページではDokuWikiコアやプラグインテンプレートでどのようにJavaScriptがロードされるかについて概要を説明します。また、DokuWiki内でのJavaScriptをコードする際の、イベント処理やコーディングスタイルについても説明します。

JavaScript のロード

すべてのJavaScriptはlib/exe/js.phpで集められ、クライアントへ送信されます。このスクリプトはすべてのファイルを繋ぎ、空白を除去して圧縮し(圧縮する 設定の場合)、できたファイルをキャッシュします。また、ヘッダ情報によってブラウザにキャッシュするように指示するので、もし新しいJavaScriptを書いた場合にはその都度、ブラウザのキャッシュを更新する必要があります。(Shift+F5やShift+CTRL+Rなど)

DokuWikiはつぎの場所からJavaScriptを集めます。

  • 自動生成されたJavaScript (language strings, config settings, toolbar)
  • lib/scripts/*.js 1)
  • lib/plugins/*/script.js
  • lib/tpl/<現在のテンプレート名>/script.js
  • conf/userscript.js

このように、あなたのJavaScriptをDokuWikiで使うには、個々のtemplatespluginsディレクトリにscript.jsという名前で保存するか、conf/userscript.js内に挿入します。

また、lib/tpl/<現在のテンプレート名>/main.phpのHTMLコードの<head></head>内に直接挿入することもできます。

Include Syntax

DokuWikiのJavaScriptディスパッチャは、特別なJavaScriptコメントを使って他のスクリプトファイルをincludeすることができます。これはテンプレートやプラグインなどのように、ひとつのJavaScript(script.js)しかパースされない場合には便利です。

:!: includeされたファイルはキャッシュロジックでチェックされません。もとのファイルをtouchしてキャッシュを更新させる必要があります。

:!: Includeは循環参照を避けることができません。

:!: Includeパスは半角英数、アンダースコア、スラッシュ、ピリオドのみ使用してください。

include

/* DOKUWIKI:include somefile.js */

この文法は指定されたJavaScriptファイルをコメント部分にincludeします。ファイル名はこのinclude文のあるファイルパスからの相対パスです。スラッシュで始まる場合はファイルシステム上の絶対パスとなります。

include_once

/* DOKUWIKI:include_once common_library.js */

この文法は指定されたJavaScriptファイルをコメント部分にincludeします。ファイル名はこのinclude文のあるファイルパスからの相対パスです。スラッシュで始まる場合はファイルシステム上の絶対パスとなります。

すでにinclude_onceによって同じ名前のファイルが読み込まれている場合はロードされません。この名前はすべてのスクリプトファイル(すべてのプラグインも含めて)で共有されるので、名前の付け方には注意して意味のあるファイル名にしなければいけません。

この文法は、同一のJavaScriptライブラリを別々のプラグインで使う場合に役に立つでしょう。同じ名前(basename)を使ってinclude_onceでincludeすることで、あなたのプラグインが複数インストールされていても一回だけロードされるからです。

コーディングガイドライン

DokuWiki内で使うJavaScriptを書くときには、2,3のルールに従わなければいけません。JavaScriptの性質上、あなたのスクリプトだけなく、すべてのDokuWikiスクリプトが壊れるかもしれません。

1. 文法が正しいか確かめる

上でも述べたように、DokuWikiはデフォルトのcompress設定によってJavaScriptを小さくまとめます。文法エラーが入り込まずにまとめるために、圧縮しない場合よりも厳しくチェックしなければいけません。

オンラインサービスのJSLintなどを使ってください。

  • compressを無効にしてデバッグします。
  • compressを有効にしても動くか確かめます。

2. 控えめなJavaScriptにする

DokuWikiの新しい機能を追加する場合、すべての人々がJavaScriptを使っていると思ってはいけません。万が一JavaScriptが利用できない環境でも通常のページ表示ができるようにする必要があります。

DokuWikiには定義済みの関数や変数が用意されています。Event Handling

3. 不適切に混ぜない

HTMLに直接JavaScriptを埋め込むやり方は古くからあります。しかし、JavaScriptと(X)HTMLは混ぜるべきではありません。実際、DokuWikiでは混ぜられないケースが多くあります。ここでは「不適切に混ぜるやりかた」の例を挙げます。2)

<body onload="refreshPage()">
 
<p>some html</p>
 
<script language="JavaScript">
  doSomethingHere();
</script>
 
<p>more <a href="http://example.com" onclick="doSomethingElse()">HTML</a></p>
 
</body>

これは哲学的に問題があるのではなく、JavaScriptが動きません。上の例では、DokuWikiと<body>タグどちらもがページのonloadに別々の関数でアサインしようとしています。ブラウザはこの衝突を正しく処理できないし、結果が予測不能です。

厳密に言えば、HTML内にJavaScriptを埋め込むことは可能ですが、DokuWikiで動いているJavaScriptとコンフリクトしないことをあなたが十分に知っている必要があります。DokuWikiの実装に関する知識を必要としますし、DokuWikiの実装自体が変わる場合もあるので、不用意にJavaScriptを埋め込むのはやめた方が良いでしょう。

4. IDを使用する

DOMオブジェクトを変更するために、JavaScriptはオブジェクトを認識できなければいけません。もっとも簡単な方法はHTMLタグをIDで指定することです。このIDは正確に正しいDOMオブジェクトを参照できるように、ページ内のすべてのIDの間でユニークな値でなければなりません。

HTMLを生成するときに(たとえばテンプレートやプラグインから)、それはあとからJavaScriptがアクセス出来るようにしておくべきです。また、すでに存在するIDとかぶらないように確かめなければいけません。特に、自動的に指定される見出しのヘッダなどとコンフリクトしてはいけません。あなたの生成するオブジェクトのIDを2つのアンダースコア(__)を使うのが最も簡単な方法です。見出しのIDはいつもpagenamesのはずなので、2つのアンダースコアを持たないことが保証されているからです。

5. インラインスクリプト

JavaScriptとXHTMLを混ぜないように、というルールはもう述べました。しかし、どうしてもインラインJavaScriptを使わなければいけない場合、次のように括ってください。

<script type="text/javascript"><!--//--><![CDATA[//><!--
...
//--><!]]></script>

この方法は最も互換性高くスクリプトが動作するやり方です。これに関する情報は、 XHTML 1.0: Script and Style elements仕様や、CDATA section interface定義を参照してください。

もし、インラインJavaScriptを<head>セクションに追加しなければならない場合は、action_pluginを書いてTPL_METAHEADER_OUTPUTイベントを捕捉してください。

DokuWiki JavaScript ライブラリ

DokuWikiはPrototype,Dojo,JQueryといった大きなライブラリを使用していません。その代わり、DokuWiki用のJavaScriptコードを書くために便利なクラスや関数を集めた小さなライブラリを持っています。

イベント処理

3. 不適切に混ぜないで述べたように、イベントハンドラーはHTMLコードに混ぜてはいけません。イベントハンドラーはDocument Object Model (DOM)がロードされた時に指定されるべきです。DOMはHTMLをツリー構造で表現したもので、JavaScriptスクリプトで参照できます。あなたのJavaScriptはどのオブジェクトがどの関数と結びついているか、また、どの関数がどのオブジェクトに結びついているかを把握できていなければなりません。

どのブラウザでも動くように関数をDOMオブジェクトに結びつけるために、addEvent()関数が用意されています。これはDOMオブジェクト、イベント名('click'等)、コールバック関数(ハンドラー)を引数にとります。この関数は、同一のDOMオブジェクトのイベントに、複数のプラグインが登録することもサポートします。

なお、AddEvent()はInternet Explorerでのイベントにおけるプロパティやメソッドを変えます。そのため、targetプロパティを使えますし、preventDefault()stopPropagation()メソッドを呼び出すことができます。

不幸なことに、script.jsのJavaScriptはHTMLのロード終了前、つまりDOMツリーが出来ていない段階でロードされてしまいます。JavaScriptが必要とするオブジェクトが存在しないのです。(script.jsロード時にDOMを参照しないJavaScriptなら、実行することはできます。)

この問題を解決するため、DokuWikiはaddInitEvent()関数を用意しています。この関数は、DOMが準備できた直後に実行するコールバック関数を登録します。

以上の関数の例 (summary_enforcement tip)

function enforceSummary() {
    /*...*/
}
 
function installSummaryEnforcement()
{
    var summary_input = document.getElementById('edit__summary');
    if(summary_input !== null)
    {
        /*...*/
        addEvent(summary_input, 'change', enforceSummary);
        addEvent(summary_input, 'keyup', enforceSummary);
    }
}
 
addInitEvent(installSummaryEnforcement);

この例では、summary input fieldのためにenforceSummary()関数をonchangeonkeyupイベントハンドラーに結びつける必要があります。installSummaryEnforcement()がこれを受け持っています。

addInitEvent()の呼び出しでinstallSummaryEnforcement()関数がDOMロード直後に実行されるように登録されます。

installSummaryEnforcement()自体がどのように動作しているか見てみましょう。まず1番目に、この関数はIDによるDOMオブジェクトを取得します(他のやり方もありますが)。この場合、ページの編集時にsummaryフィールドだけが表示されてからこのオブジェクトは存在しないかもしれません。だからこの関数は最初にオブジェクトを参照できるか確かめるテストをしています。もしあればaddEvent()を呼び出してイベントハンドラーをenforceSummary()へ結びつけます。

このDokuWikiイベント処理群のオリジナルはDean Edwards (herehere)によって作成されました。

  • イベントシステムについてより深く知りたい場合は、ソースを参照してください。

定義済みのグローバル変数

あなたのスクリプト内でも利用できる定義済みJavaScript変数

  • DOKU_BASE – DokuWikiルートディレクトリのフルパス
  • DOKU_TPL – 使用されているTemplateのフルパス
  • LANG – 言語文字列の配列

SACK (AJAX) Library

DokuWikiはGregory Wild-SmithによるSACKと呼ばれるAJAXライブラリを持っています。

$()

$()関数は、よく使われるDOMのdocument.getElementById()の代替関数です。DOM関数と同様、これは引数にIDをとり、要素オブジェクトを返します。DOM関数と異なるのは、1つ以上のidを渡してオブジェクトの配列を得られることです。

その他の関数

DokuWikiは他にもいろいろなメソッドを用意しています。特に、あなたの開発を助けてくれるのは次のようなものでしょう:isset, getElementsByClass, findPosX, findPosY, jsEscape, prependChild.

1)
edit.jsとmedia.jsはeditモードとmediaポップアップモードでのみロードされます。不要なときにロードさせないためです。
2)
scriptタグにはlanguage属性なんてありません!正しく規格に準拠するにはtype=“text/javascript”です。
ja/devel/javascript.txt · 最終更新: 2014-02-27 17:19 by Klap-in

特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki