| 表示のカスタマイズ |
|---|
| 外装(スキン) |
| カスタムCSS |
|
| カスタムJS(一覧) |
| MediaWiki |
ウィキペディアで各利用者が設定できるカスタムJavaScript(カスタムJS)について解説します。「ユーザースクリプト」のウィキペディア版なので、そうとも呼ばれます。これは各利用者が記述できるJavaScriptのコードで、登録利用者の利用者空間(利用者ページ)のサブページに置く(注意:公開されます)などすることで、そのウィキ(ウィキペディア日本語版といった範囲)でのページの表示時などに実行されるものです。様々な機能を実現することができます。
既存のカスタムJSを利用する場合はカスタムJSの一覧をご覧ください。ガジェットは共有されたJavaScriptで個人設定からクリックで導入できます。
mw.loader.load('//ja.wikipedia.org/w/index.php?title=利用者:ウィキ助/hoge.js&action=raw&ctype=text/javascript');
mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Example/bar.js&action=raw&ctype=text/javascript');
どのように編集してよいかよく分からないときは、ウィキペディア内で検索することで、他の利用者のJSを閲覧できます。まずそれを参考に編集していくと良いでしょう。
ブックマークレットとしてスクリプトの呼び出しをアドレスとしてブックマークしておくことで、使いたい時だけクリックなどして呼び出して使用できます。たとえば利用者:Hogehoge/hoge.js にあるスクリプトをブックマークする場合、以下のURLで登録します。
#"h-Greasemonkeyを使う方法-導入方法">Greasemonkeyを使う方法[編集]Firefoxを使用している場合、Greasemonkeyにスクリプトを登録しておくことで、適宜 有効・無効を切り替えてスクリプトを利用できます(Firefox Add-onsでの紹介ページ)。アドオンのインストール後、Firefoxのメニューから「ツール」->「Greasemonkey」->「新規ユーザスクリプト」を開き、各項目を埋めて登録します。登録の方法はGreasemonkey 作り方などで検索してください。
Chromeであれば、Tampermonkeyが互換性のある拡張機能として使用できます。
MediaWikiにはカスタムJS以外にJSを置く場所があります。
MediaWiki上でJavaScriptを動かす場合、次のような変数と関数を利用できます。
読み込まれるファイルの一覧は「en:Wikipedia:Catalogue of CSS classes(英語)」に記載されています。mw:ResourceLoader/Modulesには、MediaWikiの関数やjQueryについて説明されています。
$( /* 関数 */ ) - ページの読み込みが完了する前、DOMの構築が終わった後に関数を実行します。$( document ).ready( /* 関数 */ ) と同等です。DOMの構築完了時点ではなく、画像などがロード完了してから実行したい場合は、$(window).load( /* 関数 */ )などが使用できます。$(function(){/* ここに初期化コードを書く */});
他のページにあるJavaScriptのスクリプトをロードします。JavaScriptのロードは基本的に非同期に行われます。他のJavaScriptのスクリプトやモジュールに依存したコードを書きたい場合は、mw.loader.using( /* モジュール名 */ ).then( /* 関数 */ )や$.getScript( /* URI */ ).then( /* 関数 */ )を使用します。
mw.loader.load( /* URI */ ) - 任意のサイトの任意のページにあるJavaScriptソースを読み込みます(非同期)。URIで指定します。mw.loader.load('//en.wikipedia.org/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.wikipedia.org/w/index.php?title=User:foo/bar.js&action=raw&ctype=text/javascript').done(function(){/* 処理 */});
$.when($.ajax(...), $.ajax(...), ...).then(/* 処理 */) - 複数のファイルを読み込む場合、$.whenを使うことで、すべての読み込みが完了するまで処理待ちをすることができます。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で定義した内容を使用したりすることが出来ます。Place for Extensions Objects in JavaScriptによれば、第三者ライブラリはmw.libsを、拡張はmw.extを使用することが多いようです。
mw:Extension:WikiEditorで提供されている、改良型編集ツールバーは、カスタマイズが可能です。
カスタマイズをするにあたってのスニペット:
functionCustomizeEditform(){$(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);}});}});
$1などの置換パターンを使用できます。body.ns-talkやbody:not(ns-talk)などが使用できます。{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='+(newDate()).getUTCFullYear()+'年'+((newDate()).getUTCMonth()+1)+'月|',peri:'',post:'}}'}},},],},'myedit':{label:'編集',layout:'characters',characters:[{label:'改行削除',action:{type:'replace',options:{regex:/\r|\n/g,regexReplace:'',}},},],},},}}}
{section:'advanced',groups:{'(グループ名)':{label:'(名前)',}}}
{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へのリンクを作成するテンプレートについては「Template:Api」をご覧ください。 |
Mediawikiには各種のAPIが用意されています。APIを使用するメリットとして、各種の情報(投稿回数、カテゴリ一覧)を得られること、処理しやすい整形された情報が得られること、そして応答が早いこと、などが挙げられます。
APIへのアクセスはAjaxで行います。APIサンドボックスで、APIをテストすることが出来ます。他に、REST(Representational State Transfer)を使用するREST API(英語)も用意されています。
JavaScriptでAPIを使用するときは、mediawiki.apiモジュールを使用すると便利です。
mw.loader.using('mediawiki.api').then(function(){varapi=newmw.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(){varapi=newmw.Api();api.parse('== chapter ==').done(function(html){console.log(html);});});
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}functiondeepMerge(obj1,obj2){$.each(obj2,function(key,value2){if(keyinobj1){varvalue1=obj1[key];if(Array.isArray(value1)){if(Array.isArray(value2)){obj1[key]=value1.concat(value2);}else{value1.push(value);}}elseif(typeofvalue1==='object'){if(typeofvalue2==='object'){deepMerge(value1,value2);}else{obj1[key]=value2;}}else{obj1[key]=value2;}}else{obj1[key]=value2;}});returnobj1;}// 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)functioniterateQuery(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');returndeferred;}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);}});returndeferred.promise();}
例: 管理者一覧を取得
iterateQuery(newmw.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(){varapi=newmw.ForeignApi('https://en.wikipedia.org/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 を押すとデバッグ機能が表示されます。
アドオン(ブラウザ拡張機能)のJavaScript Debuggerもあります。追加してからFirefoxを再起動し、メニューから「ツール」->「JavaScript Debugger」をクリックすると、デバッガが立ち上がります。ブレークポイントの指定、変数のウォッチなどが可能です。
(パソコン版の場合)
表示されたペインの「Console」にエラーなどが表示されます。
画面上で右クリック->「要素を調べる」をクリック。表示されたペインで「Console」という所をクリックすると、デバッガが表示されます。
F12 を押すとウィンドウが表示されます。または、メニューから「ツール」->「F12 開発者ツール」でも同様です。ここで「スクリプト」という所をクリックすると、デバッガが表示されます。