Wikipedia:カスタムJS
表示のカスタマイズ |
---|
外装(スキン) |
カスタムCSS |
|
カスタムJS(一覧) |
MediaWiki |
ウィキペディアで各利用者が設定できるカスタムJavaScript(カスタムJS)について解説します。「ユーザースクリプト」のウィキペディア版なので、そうとも呼ばれます。これは各利用者が記述できるJavaScriptのコードで、登録利用者の利用者空間(利用者ページ)のサブページに置く(公開する)などすることで、そのウィキ(ウィキペディア日本語版といった範囲)でのページの表示時などに実行されるものです。様々な機能を実現することができます。
既存のカスタムJSを利用する場合はカスタムJSの一覧をご覧ください。ガジェットは共有されたJavaScriptで個人設定からクリックで導入できます。
導入方法
[編集]標準の方法
[編集]- この場合、カスタムJSを使用するには、まずアカウントを取得してログインします。
- 各スキン共通の各利用者用のcommon.jsを開きます。あるいは、各スキンでだけ使うには、標準のベクター2022年版スキン用には各利用者のvector-2022.jsを、ベクタークラシックスキン用には各利用者のvector.jsを使います。異なるスキンを使っている場合、特別:個人設定の「表示」タブから、使用しているスキンの「カスタムJS」を開きます。これらの js のページは、本人だけが編集できます。
- 上記の通り開いた common.js などの js のページに、使いたいコードを記述し保存します。既存のカスタムJS一覧の中からウィキペディア日本語版の利用者:ウィキ助/hoge.js に置かれているコードを使用する場合、次のように書いて保存します。他言語版または他プロジェクトに置かれているコードを使用する、例えば英語版の User:Example/bar.js (実際にはありません)に置かれているコードを使用する場合は、次のように記述します。
mw.loader.load('//ja-two.iwiki.icu/w/index.php?title=利用者:ウィキ助/hoge.js&action=raw&ctype=text/javascript');
mw.loader.load('//en-two.iwiki.icu/w/index.php?title=User:Example/bar.js&action=raw&ctype=text/javascript');
- キャッシュを消します。これで、各ページにて保存したスクリプトが実行されるようになります。
見本
[編集]どのように編集してよいかよく分からないときは、ウィキペディア内で検索することで、他の利用者のJSを閲覧できます。まずそれを参考に編集していくと良いでしょう。
ブックマークレットを使う方法
[編集]ブックマークレットとしてスクリプトのアドレスをブックマークしておくことで、使いたい時だけクリックして使用できます。たとえば利用者:Hogehoge/hoge.js にあるスクリプトをブックマークする場合、以下のURLで登録します。
javascript:(function(){mw.loader.load('//ja-two.iwiki.icu/w/index.php?title=User:Hogehoge/hoge.js&action=raw&ctype=text/javascript');})()
Greasemonkeyを使う方法
[編集]Firefoxを使用している場合、Greasemonkeyにスクリプトを登録しておくことで、適宜 有効・無効を切り替えてスクリプトを利用できます(Firefox Add-onsでの紹介ページ)。アドオンのインストール後、Firefoxのメニューから「ツール」->「Greasemonkey」->「新規ユーザスクリプト」を開き、各項目を埋めて登録します。登録の方法はGreasemonkey 作り方などで検索してください。
Chromeであれば、Tampermonkeyが互換性のある拡張機能として使用できます。
カスタムJS以外のJavascript
[編集]MediaWikiにはカスタムJS以外にJSを置く場所があります。
- Wikipedia:ガジェット - 共有されたJavaScriptのコードです。特別:個人設定からワンクリックで使用のオン・オフを切り替えることができます。ログイン・ユーザーのみ。
- Mediawiki:common.js - サイトの閲覧者全員に適用されます。ログインの有無は関係なし(プロジェクト:ウィキ技術部/共通スクリプトを参照)。
独自の変数と関数
[編集]MediaWiki上でJavaScriptを動かす場合、次のような変数と関数を利用できます。
読み込まれるファイルの一覧は「en:Wikipedia:Catalogue of CSS classes 」に記載されています。mw:ResourceLoader/Modulesには、MediaWikiの関数やjQueryについて説明されています。
初期化
[編集]$( /* 関数 */ )
- ページの読み込みが完了する前、DOMの構築が終わった後に関数を実行します。$( document ).ready( /* 関数 */ )
と同等です。DOMの構築完了時点ではなく、画像などがロード完了してから実行したい場合は、$(window).load( /* 関数 */ )
などが使用できます。
$(function() { /* ここに初期化コードを書く */ });
ロード
[編集]JavaScriptのロード
[編集]他のページにあるJavaScriptのスクリプトをロードします。JavaScriptのロードは基本的に非同期に行われます。他のJavaScriptのスクリプトやモジュールに依存したコードを書きたい場合は、mw.loader.using( /* モジュール名 */ ).then( /* 関数 */ )
や$.getScript( /* URI */ ).then( /* 関数 */ )
を使用します。
mw.loader.load( /* URI */ )
- 任意のサイトの任意のページにあるJavaScriptソースを読み込みます(非同期)。URIで指定します。
- 例:
mw.loader.load('//en-two.iwiki.icu/w/index.php?title=User:Foo/bar.js&action=raw&ctype=text/javascript');
mw.loader.load( /* モジュール名 */ )
- mw:ResourceLoader/Core modulesに記載されているJavaScriptのモジュールを読み込みます(非同期)。配列にすることで複数同時に読み込めます。モジュールを読み込んでから、依存する処理を行いたい場合はmw.loader.using( /* モジュール名 */ ).then( /* 関数 */ )
を使用して下さい。mw.loader.using( /* モジュール名 */ ).then( /* 関数 */ )
- mw:ResourceLoader/Core modulesに記載されているJavaScriptのモジュールを読み込んでから処理を行います。配列にすることで複数同時に読み込めます。
- 例:
mw.loader.using( 'mediawiki.util' ).then( function() { alert(mw.util.wikiUrlencode("ほげ")); } );
$.getScript( /* URI */ ).then( /* 関数 */ )
- 任意のサイトの任意のページにあるJavaScriptソースを読み込んでから処理を行います。URIで指定します。リクエストがキャッシュされないため、下記の$.ajax
を用いた方がよいでしょう。$.ajax( { dataType: "script", cache: true, url: /* URI */ } ).then( /* 関数 */ )
- 任意のサイトの任意のページにあるJavaScriptソースを読み込んでから処理を行います。URIで指定します。キャッシュを有効にしています。
- 関数化すると使いやすくなるでしょう。:
jQuery.getScriptWithCache = function(url, options) { return $.ajax($.extend(options || {}, { dataType: "script", cache: true, url: url, })); }; $.getScriptWithCache('//en-two.iwiki.icu/w/index.php?title=User:foo/bar.js&action=raw&ctype=text/javascript').done(function() { /* 処理 */ });
$.when($.ajax(...), $.ajax(...), ...).then(/* 処理 */)
- 複数のファイルを読み込む場合、$.when
を使うことで、すべての読み込みが完了するまで処理待ちをすることができます。
CSSのロード
[編集]mw.loader.load( /* URI */, 'text/css' )
- 任意のサイトの任意のページにあるCSSを読み込みます。URIで指定します。
ページ情報の取得
[編集]mw.config.get
の引数に以下の変数名を渡すことで、システムや記事に関する情報を得ることが出来ます。例えば、wgPageName
の場合、mw.config.get( 'wgPageName' )
と記述します。
変数名と同名のグローバル変数が用意されていますが、これを直接呼び出すことは現在は非推奨となっています。
以下に主なものを示します。
変数 | 値の例 | 説明 |
---|---|---|
システム全体 | ||
wgArticlePath | '/wiki/$1' |
$1 を記事名で置き換える (mw.config.get('wgArticlePath').replace('$1', '記事名') ) ことで、パスを生成できます。より簡潔なmw.util.getUrl('記事名') が用意されています。
|
wgScript | '/w/index.php' |
index.phpのパスを取得します。index.phpはソースの取得などに使用できます。mw:Manual:Parameters to index.php/jaを参照して下さい。 |
wgFormattedNamespaces |
|
番号から名前空間の名称を得るためのマッピング。 |
wgNamespaceIds |
|
名前空間の名称から番号を得るためのマッピング。 |
wgContentNamespaces | [0] |
記事の名前空間 |
wgContentLanguage | 'ja' |
言語設定 |
記事ごと | ||
wgPageName | 'Wikipedia:カスタムJS' |
この記事の名前空間を含めた名前(スペースはアンダースコアで置き換え) |
wgTitle | 'カスタムJS' |
この記事の名前空間を含まない記事名(スペースを含み、アンダースコアは含まない) |
wgNamespaceNumber | 4 |
この記事の名前空間の番号 |
wgCanonicalNamespace | Project |
正規化された名前空間名(例えば"Wikipedia"名前空間は"Project"、"利用者"名前空間は"User") |
wgArticleId | 2276878 |
記事ID(特別なページや存在しないページでは0になる) |
wgRevisionId | 66050435 |
現在見ているリビジョンのID |
wgCurRevisionId | 66050435 |
その記事の最新版のリビジョンのID |
wgCategories | ['ウィキペディア用ツール'] |
カテゴリ一覧(隠しカテゴリを区別しないので注意) |
wgAction | 'view' |
アクション(mw:Manual:Parameters to index.php/ja#Actionsを参照) |
wgPageContentLanguage | 'ja' |
記事の言語 |
ユーザごと | ||
wgUserId | (ユーザのID) | ユーザのID |
wgUserEditCount | (ユーザの編集回数) | ユーザの編集回数 |
wgUserName | (ユーザ名) | ユーザ名 |
wgUserGroups | (ユーザのグループ) | ユーザのグループ |
wgUserLanguage | 'ja' |
ユーザの言語 |
skin | 'vector' |
現在使っているスキンの名前 |
ユーザ設定の取得
[編集]mw.user.options.get(/* オプション名 */)
-mw.config.get
と同様に、ユーザ設定を取得します(user.optionsモジュールの読み込みが必要です)。
要素の取得
[編集]document.editform.wpTextbox1
- 編集画面で、編集領域のテキストボックスを取得します。mw.util.$content
- 記事の領域のDivエレメントをjQueryオブジェクトで取得します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。
ユーティリティ
[編集]mw.util.addCSS
- CSSの定義を追加します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。mw.util.addPortletLink
- 各種ツールバーにリンクを追加します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。
mw.util.getParamValue
- ページのURLのパラメータを取得します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。mw.util.getUrl
- 記事名に対して、そのURLを取得します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。
- 例:
mw.util.getUrl('Wikipedia:カスタムJS/一覧'); // => "/wiki/Wikipedia:%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0JS/%E4%B8%80%E8%A6%A7"
mw.util.wikiScript
- スクリプトのパスを取得します。引数に何も指定しない場合は、index.phpのパスを返します(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。
- 例:
mw.util.wikiScript(); // => "/w/index.php" mw.util.wikiScript('api'); // => "/w/api.php"
mw.util.wikiUrlencode
- 文字列を、URLエンコードします(mediawiki.util
をmw.loader.using
でロードして使用して下さい)。
- 例:
mw.util.wikiUrlencode('Wikipedia:カスタムJS/一覧'); // => "Wikipedia:%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0JS/%E4%B8%80%E8%A6%A7"
ローカルストレージ
[編集]mw.storage
- ブラウザのLocalStorageをget, set, remove で使用します(mediawiki.storageモジュールの読み込みが必要です)。mediawiki.storage
を参照してください。既存のライブラリのLocalStorageの使用については、MediaWikiのJavaScriptのコーディング規約を確認して下さい。
コーディング規約
[編集]カスタムJSには特にコーディング規約は定められていませんが、MediaWikiのJavaScriptのコーディング規約などを参考にすると、わかりやすいコードを書くことが出来ます。
グローバル変数によるカスタムJS外とのやりとり
[編集]グローバル変数を使用することにより、カスタムJSに設定を渡したり、カスタムJSをロード後に、カスタムJSで定義した内容を使用したりすることが出来ます。
Place for Extensions Objects in JavaScriptによれば、第三者ライブラリはmw.libs
を、拡張はmw.ext
を使用することが多いようです。
改良型編集ツールバーの拡張
[編集]mw:Extension:WikiEditorで提供されている、改良型編集ツールバーは、カスタマイズが可能です。
カスタマイズをするにあたってのスニペット:
function CustomizeEditform() {
$(document.editform.wpTextbox1).wikiEditor('addToToolbar', {
// ... ここにObjectで設定を書く
});
}
$(function () {
if (document.editform) {
mw.loader.using('user.options').then(function () {
if (mw.user.options.get('usebetatoolbar') == 1) {
mw.loader.using('ext.wikiEditor.toolbar').then(CustomizeEditform);
}
});
}
});
構成
[編集]- 改良型編集ツールバーの上段の、ボタン (main) や「上級」(advanced) 「特殊文字」(characters) 「ヘルプ」(help) と並んでいる欄をsectionと呼びます。
- 「上級」(advanced) をクリックしたときに表示される領域や、main sectionをtoolbarと呼びます。
- toolbarの縦棒で区切られた領域 group でできています。
- groupには、buttonまたはselect(プルダウン)が並んでいます。
- 「特殊文字」(characters) や「ヘルプ」(help) をクリックしたときに表示される領域をbookletと呼びます。
- bookletの左側はpagesからできており、各pageはbookletの右側のtable(「ヘルプ」(help) の場合など)またはcharacters(「特殊文字」(characters) の場合の各ボタン)からできています。
- 各ボタン (button、charactersなど) の動作は、actionで記述できます。
- actionのtypeで、動作種別をencapsulate, replace, callback, dialogから選択します。
- actionのoptionsで、動作種別がencapsulate, replaceの場合の動作を記述します。
- pre: カーソル位置またはテキスト選択の前に置かれます。
- peri: テキストを選択していないときにカーソル位置に置かれます。
- post: カーソル位置またはテキスト選択の後に置かれます。
- regex: 置換の正規表現。
- regexReplace: 置換後の置き換える文字列、
$1
などの置換パターンを使用できます。
- actionのexecuteで、動作種別がcallbackの場合に、contextを引数に持つコールバック関数を記述します。戻り値は無視されます。編集内容を変更するには、直接wpTextbox1のvalueなどを変更する形で使います。
- filtersオプションにCSSセレクターを記述することで、そのCSSセレクターを含むページでのみに表示を限定することができます。特に、bodyのクラスに対するセレクタ
body.ns-talk
やbody:not(ns-talk)
などが使用できます。 - 既存のボタン・ツールバーの動作はjquery.wikiEditor.toolbar.configをご覧ください。
カスタマイズ
[編集]- sectionに新しくbookletを追加する場合:
{ sections: { '(新しいツールバー名)': { type: 'booklet', label: '(表示名)', pages: { '(ページ名)': { label: '(表示名)', layout: 'characters', characters: [ '<br/>', { label: '(表示名)', action: { type: 'encapsulate', options: { pre: '[[', peri: '', post: ']]' } }, }, // ... ] }, // ... }, } } }
- 例:
{ sections: { 'mytools': { type: 'booklet', label: 'ツール', pages: { 'mysnippet': { label: 'スニペット', layout: 'characters', characters: [ '<br/>', { label: '{{要出典範囲}}', action: { type: 'encapsulate', options: { pre: '{{要出典|date=' + (new Date()).getUTCFullYear() + '年' + ((new Date()).getUTCMonth() + 1) + '月|', peri: '', post: '}}' } }, }, ], }, 'myedit': { label: '編集', layout: 'characters', characters: [ { label: '改行削除', action: { type: 'replace', options: { regex: /\r|\n/g, regexReplace: '', } }, }, ], }, }, } } }
- 既存のsectionにgroupを追加:
{ section: 'advanced', groups: { '(グループ名)': { label: '(名前)', } } }
- 既存のgroupにbuttonを追加:
{ section: 'advanced', group: 'heading', tools: { '(ボタン名)': { label: '(名前)', type: 'button', icon: '//upload.wikimedia.org/wikipedia/commons/thumb/3/36/Help-content.svg/22px-Help-content.svg.png', action: { type: 'encapsulate', options: { pre: '', } } }, // ... } }
API
[編集]Mediawikiには各種のAPIが用意されています。APIを使用するメリットとして、各種の情報(投稿回数、カテゴリ一覧)を得られること、処理しやすい整形された情報が得られること、そして応答が早いこと、などが挙げられます。
APIへのアクセスはAjaxで行います。APIサンドボックスで、APIをテストすることが出来ます。他に、REST(Representational State Transfer)を使用するREST API も用意されています。
mediawiki.api モジュール
[編集]JavaScriptでAPIを使用するときは、mediawiki.api
モジュールを使用すると便利です。
mw.loader.using('mediawiki.api').then(function () {
var api = new mw.Api();
api.get({
action: 'query',
prop: 'revisions',
pageids: '2276878',
rvprop: 'user|content'
}).done(function (data) {
console.log(data.query.pages);
});
});
mediawiki.api
モジュールには各種プラグインがあり、例えばmediawiki.api.parse
を使用すると、WikiテキストからHTMLへの変換を簡単に行うことができます。
mw.loader.using('mediawiki.api.parse').then(function () {
var api = new mw.Api();
api.parse('== chapter ==').done(function (html) {
console.log(html);
});
});
Query アクションとcontinue
[編集]Query アクションは、Wikiの情報や一覧を取得するために使用するアクションです。
Query アクションの結果が、1回のAPIで取得できる件数の上限を超えた場合、APIの結果にcontinue
が追加されます。
APIのリクエストのパラメータにcontinueの要素をマージすることで、APIの結果を継続して取得することができます。
以下のような関数を作成しておくとよいでしょう。
// overwrites obj1
// deepMerge({a: {b: [2], c: 3}, d: {e: {f: [4, 5]}}, g: 6}, {a: {b: [7], c: 8}, d: {e: {f: [9, 10]}}, h: 11})
// => {a: {b: [2, 7], c: 8}, d: {e: {f: [4, 5, 9, 10]}}, g: 6, h: 11}
function deepMerge(obj1, obj2) {
$.each(obj2, function (key, value2) {
if (key in obj1) {
var value1 = obj1[key];
if (Array.isArray(value1)) {
if (Array.isArray(value2)) {
obj1[key] = value1.concat(value2);
} else {
value1.push(value);
}
} else if (typeof value1 === 'object') {
if (typeof value2 === 'object') {
deepMerge(value1, value2);
} else {
obj1[key] = value2;
}
} else {
obj1[key] = value2;
}
} else {
obj1[key] = value2;
}
});
return obj1;
}
// iterate getting query api if request returned continue
// api: mw.Api
// options: Object, get options
// maxTry: integer, nullable (default 10), max of iterates count
// interval: integer, nullable (default 1000), milliseconds to sleep between each query
// deferred: jQuery.Deferred, nullable
// currentResult: Object, nullable, current query result
// returns deferred object
// deferred return value: query result (data.query)
function iterateQuery(api, options, maxTry, interval, deferred, currentResult) {
if (typeof (maxTry) !== 'number') {
maxTry = 10;
}
interval = interval || 1000;
deferred = deferred || $.Deferred();
currentResult = currentResult || {
};
if (maxTry === 0) {
deferred.reject('maxTry is 0');
return deferred;
}
api.get($.extend({
action: 'query',
}, options)).done(function (data) {
currentResult = deepMerge(currentResult, data.query);
if (data.continue ) {
setTimeout(function () {
iterateQuery(api, $.extend(options, data.continue ), maxTry - 1, interval, deferred, currentResult);
}, interval);
} else {
deferred.resolve(currentResult);
}
});
return deferred.promise();
}
例: 管理者一覧を取得
iterateQuery(new mw.Api(), {
list: 'allusers',
augroup: 'sysop',
aulimit: '20',
}).then(function(query){
console.log(query.allusers);
});
別ドメインへのアクセス
[編集]JavaScriptでMediaWikiAPIを使用する際のひとつの制約として、JavaScriptが持つ同一生成元ポリシー(別ドメインの情報に直接アクセスできない)により、そのままでは多言語版やウィキデータなどの他プロジェクトへのアクセスは出来ません。多言語版や他プロジェクトにアクセスするには、en:Cross-Origin Resource Sharing (CORS) を使います。mediawiki.ForeignApi
モジュールを使用することで、CORSを簡単に実現できます。
mw.loader.using('mediawiki.ForeignApi').then(function () {
var api = new mw.ForeignApi('https://en-two.iwiki.icu/w/api.php');
api.get({
action: 'query',
list: 'recentchanges',
}).done(function (data) {
console.log(data);
});
});
デバッグ
[編集]最も原始的なデバッグの方法はアラートとコメントアウトを使う方法です。
アラートとコメントアウト
[編集]アラート
[編集]アラートを使う方法は問題が起きていそうな場所に次のようなコードを入れて実行することです。
alert(変数名);
これにより変数がどういう値を取っているか、またif文などの分岐を含む文であればその場所が実行されているかが、ポップアップの有無とその内容により分かります。
コメントアウト
[編集]コメントアウトを使う方法も単純です。問題が起きていそうな場所で、行の先頭にスラッシュ二つを入れるか、または/* */で囲みます。
//abc = hoge.IndexOf('foo');
/*
abc = hoge.IndexOf('foo');
x = abc;
*/
こうした一部分のコメントアウトで今まで動かなかったコードが動き出したら、問題はコメントアウトした部分の周辺にあることが分かります。
ブラウザ別のデバッグ機能
[編集]現在は多くのパソコン向けブラウザで、ファンクションキーのF12 を押すとデバッグ機能が表示されます。
Firefox
[編集]- ⎈ Ctrl と ⇧ Shift を押しながら K を押します。
- あるいは、ウィンドウ右上の「三」のようにみえるマーク(いわゆるハンバーガーメニュー)を押す。メニューから「開発ツール」->「WEBコンソール」をクリックします。
アドオン(ブラウザ拡張機能)のJavaScript Debuggerもあります。追加してからFirefoxを再起動し、メニューから「ツール」->「JavaScript Debugger」をクリックすると、デバッガが立ち上がります。ブレークポイントの指定、変数のウォッチなどが可能です。
Chrome
[編集](パソコン版の場合)
- CTRL と ⇧ Shift を押しながら I (アイ)を押します。
- あるいはウィンドウ右上の「三」のようにみえるマークを押す ->「その他のツール」->「デベロッパーツール」をクリック。
表示されたペインの「Console」にエラーなどが表示されます。
Opera
[編集]画面上で右クリック->「要素を調べる」をクリック。表示されたペインで「Console」という所をクリックすると、デバッガが表示されます。
Microsoft Edge / Internet Explorer
[編集]F12 を押すとウィンドウが表示されます。または、メニューから「ツール」->「F12 開発者ツール」でも同様です。ここで「スクリプト」という所をクリックすると、デバッガが表示されます。
関連項目
[編集]- Wikipedia:カスタムJS/一覧
- JavaScript
- Wikipedia:ガジェット
- Help:カスタムCSS
- jQuery (MediaWikiのサイトのWiki)
- mediawikiwiki:Help:Extension:GlobalCssJs/ja と meta:Global user pages/ja - メタウィキメディアの利用者ページ内に置いた自己紹介やカスタムなどの内容は、各ウィキで上書きしなければ、グローバルアカウントが有効な各ウィキで共有されます。