Help:维基用户脚本开发指南

维基百科,自由的百科全书
跳转至: 导航搜索

这份指南介绍在维基百科上开发用户脚本的基本方法。维基用户脚本是用JavaScript(JS)编写的,但本文不会介绍JS的语法。

内置脚本[编辑]

所有维基百科页面都有MediaWiki生成的JS代码。浏览网页时,你的用户脚本可以访问这些内置代码生成的方法和变量。具体哪些页面可用哪些方法和变量,请参见en:Wikipedia:Catalogue of CSS classes#Stylesheets and JavaScript

用户脚本可以使用JQuery,这是MediaWiki自带的。JQuery的最重要的方法是JQuery()$(),用法说明请参考官方文档 (英文)

Of most interest are:

用户脚本的结构[编辑]

The personal "user" module (build from /common.js, /common.css and optionally the skin-specific files for the current skin) and gadgets are loaded on all pages.

大部分脚本都需要访问页面上的HTML元素,因此需要在页面加载完成后再运行。(which may not be the case at the time the modules are loaded).

function myScript() {
  // ... 
};
 
// 在文档加载完成后执行myScript方法。
jQuery( myScript );

也可以内联myScript。

jQuery( function () {
  //... code ...
} );

编辑和加载用户脚本[编辑]

预览用户脚本[编辑]

你可以直接在/common.js编写脚本,“显示预览”时,代码就会执行。

保存用户脚本[编辑]

如果你的脚本的工作页面与预览页面不同,比如你想开发一个针对分类的脚本,那么你就要保存脚本,然后去目标页面调试。

这种方法极为不便,也会在维基上产生大量的编辑历史。

本地HTML文件[编辑]

  • 用浏览器将欲调试的维基页面(HTML)连同该页面调用的CSS和JS保存到本地。
  • 用编辑器打开HTML,插入你正在开发的JS代码。
  • 用浏览器打开HTML,查看代码的运行情况。

这种方法很节省网络流量,但有以下的缺点:

  • 浏览器一般不会允许你从本地向外地(zh.wikipedia.org)发起Ajax
  • you have to save different pages depending on exactly which page (history, etc.) is needed for testing
  • you have to periodically re-save all .js files to synchronize with MediaWiki changes
  • 需要保存HTML、CSS、JS。如果你只是对别人的脚本进行小修改,这个“前期准备”工作可能有些烦人。

推荐:从本机服务器上加载用户脚本[编辑]

推荐的方法是从本机服务器上加载用户脚本,而你需要搭建一个本机服务器。在/common.js加入代码

mw.loader.load( 'http://localhost/wikipediatest.js' );

然后在你的电脑上运行网页服务器,创建wikipediatest.js。于是,每次刷新维基百科页面时,本机服务器上的wikipediatest.js就会运行,如同维基用户脚本。

至于如何编辑wikipediatest.js,大家就可以八仙过海各显神通了,比如用简单的记事本、Vim,甚至Visual Studio。如果你的网页服务器设置的好,每次修改wikipediatest.js后,再刷新维基百科,修改就能自动反映出来,甚至不需要刷新缓存

TinyWeb是个不错的网页服务器,不到100KB,也不需要安装。 Save and unzip tinyweb.zip for example into c:\Program Files\Tinyweb, create a shortcut to tiny.exe, and add an argument in shortcut properties — path to your folder with wikipediatest.js and any file index.html (required). Start TinyWeb with this shortcut; unload it with Task Manager.

Opera自9.50版起加强了安全限制,这个方法对Opera不起作用。参见Opera 9.50 for Windows changelog: “本地服务器可以调用远程资源,但远程服务器不能调用本地资源”(Local servers can use remote resources, but not vice versa)。

Browser-specific[编辑]

有些浏览器(或浏览器插件)允许你浏览网页时执行你自己设置的JS。我们可以利用这个特性来开发维基用户脚本。

最有名的是火狐浏览器的扩展Greasemonkey(油猴子),Scriptish英语也相当不错。en:Greasemonkey#Greasemonkey compatibility and equivalents for other browsers列出了Greasemonkey的类似软件。

然而,在浏览器或浏览器插件里能运行不代表能作为维基百科用户脚本运行。

Opera用户注意:

  • Placing your script in a corresponding folder as <name>.js file should work for many user scripts.
  • Opera约9.50版本以前不支持UTF-8编码的本地脚本, meaning you could only use Latin characters.

代码片段[编辑]

你可以在浏览网页时运行代码片段,如在浏览器地址栏输入javascript: var s = document.title; alert(s); void 0并回车。但在浏览器地址栏里不能输入大段代码。

你可以使用bookmarklet JavaScript Shell。它可以打开一个新窗口,在这个窗口里编写并执行的JS代码可以访问原页面。

当然,用一个成熟的JavaScript调试器会更加方便。

CSS文件[编辑]

用户脚本可以使用CSS代码,甚至可以只用CSS。那么你就需要把JS和CSS一起调试。That can be done in your /common.css, but it is slow and messy.

你应该在本地服务器里放置你的CSS文件(见上节),然后从/common.css里用

@import "http://localhost/wikipediatest.css";

导入。注意,@import语句要写在其他CSS语句之前。

An alternative way is to put this line anywhere in your css instead:

mw.loader.load( 'http://localhost/wikipediatest.css', 'text/css' );

Publishing a CSS file[编辑]

Once you have finished the CSS code, you either need to paste it into your /vector.css if it is only for personal use. Or if it is for use by others then you should upload it to for instance User:Yourname/yourscript.css. Then other users can import it by putting the following line in their /common.js file. Note, that is in their ".js", not their ".css".

importStylesheet( 'User:Yourname/yourscript.css' );

If the CSS should be used together with a user script written in JavaScript then you can make it easy for the users. Simply put the line above in the JavaScript code for your user script, then the users only need to "install" your JavaScript.

For completeness, in case someone wonders, users can import your User:Yourname/yourscript.css from their /common.css too. This of course has the advantage that it works even if the user has JavaScript disabled. Although it takes this slightly complex line of code:

@import "/w/index.php?title=User:Yourname/yourscript.css&action=raw&ctype=text/css";

软件[编辑]

编辑器[编辑]

Windows用户可以使用Notepad++,它可以

  • 高亮JavaScript代码
  • 快速插入JavaScript关键字和方法。快捷键是 Ctrl+ Enter
  • 查看所有JS方法,转到方法。
  • 代码折叠


Mac OS X用户可以使用免费的

或收费的

Linux用户可以用geditKate

调试器[编辑]

火狐浏览器:Firefox按钮->Web开发者->Web控制台。Firebug提供类似的功能。

Google ChromeChromium:菜单->工具->开发者工具。Firebug提供类似的功能。

Internet Explorer:按F12键打开开发者工具。

For debugging in Safari, open up Safari → Preferences → Advanced and enable the "Show Develop menu in menu bar" option. Afterwards, you can use Develop → Show Web Inspector to open up the development tools.

For debugging in Opera, you can use Tools → Advanced → Error Console which shows all JavaScript and CSS errors. Dragonfly is strongly recommended for convenient debugging.

DHTML 方法[编辑]

检索元素[编辑]

Every HTML element is a node in a DOM model which allows scripts to access the element, for example, on the following HTML page.

<form name="frmname" id="frmid">
	<textarea name="txtname" id="txtid"></textarea>
	<input id="neighbor" />
</form>

We can find element textarea:

  • Using its id: $( '#txtid' )
  • In the array of all elements with the same tag: $( 'textarea' )
  • Using an element next to it: $( '#neighbor').prev()
  • As a child of its parent: $( '#frmid' ).children( 'form' )
  • As a form element, using name: $( '#frmid [name="txtname"]')

This example on jsFiddle

The jQuery documentation and jQuery API reference are excellent sources for documentation.

何时执行脚本[编辑]

很多脚本只在特定的维基页面工作。 You can check:

  • The page address
if ( mw.config.get( 'wgAction' ) === 'history' ) {
  //Continue only on history pages.
  • wg variables; many of them have the same meaning as Magic words
if ( mw.config.get( 'wgCanonicalNamespace' ) === 'User_talk') {
  //Continue only on User_talk pages.
  • Presence of elements (only in second and third parts of the script)
function func_start() {
   if ( $( '#editForm' ).length == 0  ) return; //No edit form  → exit
   // …

Portlets[编辑]

Usual places to add your own links — portlet blocks with these id's:

p-logo p-personal name My talk My preferences

p-search

 
p-cactions Article Discussion Read Edit History

p-navigation

 Main page …

p-interaction
  …


p-tb

Upload file


p-lang
(interwikis)

Portlet structure:

<div id="p-myname" class="portlet">
 <h5>Header</h5>
 <div class="body">
  <ul>
  <li id="…"> <a …>  //Links
  <li id="…"> <a …>
  … …

There is a special function in mediawiki.util.js that simplifies the process of adding your own links into portlets:
mw.util.addPortletLink (portlet, href, text, id, tooltip, accesskey, nextnode)

// Several examples of portlet links
 
// Adds a link to your js file to the toolbox
mw.util.addPortletLink ( 'p-tb', mw.util.wikiGetlink( 'Special:MyPage/common.js' ),
	'My JS', 'pt-myvector', 'Visit your js file');
 
// Add a link to the edit page for your Notes in your personal links
// Note: We assume that short/pretty URLs are in use with ?action, ideally you
// would check for that.
mw.util.addPortletLink ( 'p-personal', mw.util.wikiGetlink( 'Special:MyPage/Notes' ) + '?action=edit',
	'My notes', 'pt-mynotes', 'Edit your personal notes' );
 
// Adds a link to prefix index for the current page to the toolbox
mw.util.addPortletLink ( 'p-tb',
	mw.util.wikiGetlink( 'Special:Prefixindex/' + mw.config.get( 'wgPageName' ) ),
	'Prefixindex', 'tb-prefixindex');
 
// Adds a link to 
mw.util.addPortletLink ( 'p-personal',
	mw.util.wikiGetlink( 'Special:Log/' + mw.config.get( 'wgUserName' ) ),
	'My logs', 'pt-mylogs');

移除元素[编辑]

如想移动一个元素,可使用.append().prepend()

如想隐藏一个元素,使用.hide()

// 举例: remove special characters toolbar from edit page
$( '#editpage-specialchars' ).hide();
 
// 或通过jQuery改CSS
$( '#editpage-specialchars' ).css( 'display', 'none' );

或在您的CSS代码页加入:

#editpage-copywarn {
	display:none;
}

Edit page[编辑]

Text manipulation[编辑]

The most important element on the edit page is a <textarea> with the article text inside. You can reference it with

var $txt = $( '#wpTextbox1' );

You can add new text to the beginning: $txt.prepend( 'new phrase' ) or to the end: $txt.append( 'new phrase' ).

There is a function in mediawiki.action.edit.js that can add text to the cursor position:

// This surrounds the cursor with '<pre>' and '</pre>' and pre-fills the selection with 'Test!' highlighted.
mw.toolbar.insertTags( '<pre>', '</pre>', 'Test!' );

Toolbar[编辑]

The buttons above a text area are located inside <div id='toolbar'>.

Buttons are defined with mwEditButtons[] and mwCustomEditButtons[] arrays. Then the second part of your script is called by addOnloadHook. Only after that the buttons are created by the initialization of the mediawiki.action.edit module.

So the easiest way to modify buttons is to work with these arrays:

//Example: modify signature button.
if (mwEditButtons.length >= 10 && mwEditButtons[9].tagOpen == '--~~~~')
  mwEditButtons[9].tagOpen = ' — ~~~~';

Also see en:User:MarkS/Extra_edit_buttons.

Edittools[编辑]

There is another edit panel under textarea. Usually it's generated from MediaWiki:Edittools by Extension:CharInsert and consists of a lot of JavaScript links to the insertTags(). In the English Wikipedia, this approach was replaced by MediaWiki:Edittools.js.

//Example: adding your own quick insert to Edittools
var specialchars = document.getElementById ('editpage-specialchars');
specialchars.innerHTML +=
"<a onclick=\"insertTags('<div>','</div>','');return false\"
href='#'>&lt;div&gt;</a>";

There is no crucial difference between toolbar and edittools, you can insert your own custom links into both.

参考资料[编辑]