LLWiki正在建設中,歡迎加入我們!
「LLWiki:管理员技术手册」修訂間的差異
小 (→全站CSS) 標籤:流動版網頁編輯 流動版編輯 |
(使用页面/文本对比查看器快速编辑) |
||
第46行: | 第46行: | ||
| wgAction || index.php的action参数<ref>[[mw:Manual:Parameters_to_index.php/zh|完整参数列表]]</ref> || 相比于桌面版,手机版由于添加了[[Special:历史]]而少了“history”这个可能值 |
| wgAction || index.php的action参数<ref>[[mw:Manual:Parameters_to_index.php/zh|完整参数列表]]</ref> || 相比于桌面版,手机版由于添加了[[Special:历史]]而少了“history”这个可能值 |
||
|- |
|- |
||
| wgArticleId || 内容页面编号,不存在时值为0,可以用于判断是否是内容页面且页面是否已建立 || 需要注意查看[[special:历史|历史]]和[[special:移动版差异| |
| wgArticleId || 内容页面编号,不存在时值为0,可以用于判断是否是内容页面且页面是否已建立 || 需要注意查看[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]时值为0 |
||
|- |
|- |
||
| wgCanonicalSpecialPageName || 标准化的特殊页面名,也可被wgPageName取代,主要用于不同MediaWiki站点间的代码通用,非必需 || 可用,而且多了“History”和"MobileDiff"等可能的取值<ref>[[mw:Extension:MobileFrontend/zh|移动前端的扩展说明]]</ref> |
| wgCanonicalSpecialPageName || 标准化的特殊页面名,也可被wgPageName取代,主要用于不同MediaWiki站点间的代码通用,非必需 || 可用,而且多了“History”和"MobileDiff"等可能的取值<ref>[[mw:Extension:MobileFrontend/zh|移动前端的扩展说明]]</ref> |
||
第52行: | 第52行: | ||
| wgCategories || 当前阅读的历史版本所属的分类,不含名字空间,下划线显示为空格,且总是包含隐藏分类。繁简规则一般遵从实际分类页面,但似乎偶有例外 || 除非已执行[[mediawiki:gadget-MobileCategories.js|MobileCategories小工具]],否则不可用。另外桌面版的空值为<code>[]</code>,手机版的空值为<code lang="js">null</code>,注意可能的bug |
| wgCategories || 当前阅读的历史版本所属的分类,不含名字空间,下划线显示为空格,且总是包含隐藏分类。繁简规则一般遵从实际分类页面,但似乎偶有例外 || 除非已执行[[mediawiki:gadget-MobileCategories.js|MobileCategories小工具]],否则不可用。另外桌面版的空值为<code>[]</code>,手机版的空值为<code lang="js">null</code>,注意可能的bug |
||
|- |
|- |
||
| wgCurRevisionId || 页面最新的版本编号,不存在时值为0 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgCurRevisionId || 页面最新的版本编号,不存在时值为0 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgIsArticle || 是否是内容页面(包含由某个页面的Wikitext源代码解析生成的HTML,可能是历史页面和差异下方的历史页面) || 由于[[special:移动版差异| |
| wgIsArticle || 是否是内容页面(包含由某个页面的Wikitext源代码解析生成的HTML,可能是历史页面和差异下方的历史页面) || 由于[[special:移动版差异|{{int:diff}}]]页面不可同时显示历史页面,此时不可用 |
||
|- |
|- |
||
| wgIsRedirect || 最新版本是否是重定向页面 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgIsRedirect || 最新版本是否是重定向页面 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgIsProbablyEditable || 是否可能可以编辑 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgIsProbablyEditable || 是否可能可以编辑 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgNamespaceNumber || 名字空间编号 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgNamespaceNumber || 名字空间编号 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面会显示为-1 |
||
|- |
|- |
||
| wgPageContentModel || 页面内容模型,特殊页面为“wikitext” || 由于[[special:历史|历史]]和[[special:移动版差异| |
| wgPageContentModel || 页面内容模型,特殊页面为“wikitext” || 由于[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]是特殊页面,会错误地显示为“wikitext” |
||
|- |
|- |
||
| wgPageName || 页面名称,空格显示为下划线 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgPageName || 页面名称,空格显示为下划线 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgRedirectFrom || 跳转自重定向时为对应的重定向页,空格显示为下划线 || 可用 |
| wgRedirectFrom || 跳转自重定向时为对应的重定向页,空格显示为下划线 || 可用 |
||
|- |
|- |
||
| '''wgRelevantPageName''' || 关联的页面名称,空格显示为下划线 || 可以用于[[special:历史|历史]]和[[special:移动版差异| |
| '''wgRelevantPageName''' || 关联的页面名称,空格显示为下划线 || 可以用于[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面,此时效果与桌面版一致 |
||
|- |
|- |
||
| '''wgRelevantArticleId''' || 关联的内容页面编号,不存在时值为0 || 可以用于[[special:历史|历史]]和[[special:移动版差异| |
| '''wgRelevantArticleId''' || 关联的内容页面编号,不存在时值为0 || 可以用于[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面,此时效果与桌面版一致 |
||
|- |
|- |
||
| wgRelevantUserName || 关联的用户名 || [[special:用户贡献| |
| wgRelevantUserName || 关联的用户名 || [[special:用户贡献|{{int:contributions}}]]页面不可用 |
||
|- |
|- |
||
| '''wgRelevantPageIsProbablyEditable''' || 关联的页面是否可能可以编辑 || 可以用于[[special:历史|历史]]和[[special:移动版差异| |
| '''wgRelevantPageIsProbablyEditable''' || 关联的页面是否可能可以编辑 || 可以用于[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面,此时效果与桌面版一致 |
||
|- |
|- |
||
| wgRestrictionEdit || 编辑保护,不存在的页面(含受保护的标题)或特殊页面为<code lang="js">null</code>,存在的内容页面受全保护时为<code lang="js">["sysop"]</code>,受半保护时为<code lang="js">["autoconfirmed"]</code>,未保护为<code>[]</code>;不包含名字空间保护和级联保护 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgRestrictionEdit || 编辑保护,不存在的页面(含受保护的标题)或特殊页面为<code lang="js">null</code>,存在的内容页面受全保护时为<code lang="js">["sysop"]</code>,受半保护时为<code lang="js">["autoconfirmed"]</code>,未保护为<code>[]</code>;不包含名字空间保护和级联保护 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用,另外未保护的内容页面为<code lang="js">["*"]</code> |
||
|- |
|- |
||
| wgRestrictionMove || 移动保护,不存在的页面或特殊页面为<code lang="js">null</code>,存在的内容页面受全保护时为<code lang="js">["sysop"]</code>,受半保护时为<code lang="js">["autoconfirmed"]</code>,未保护为<code>[]</code>;不包含名字空间保护和级联保护 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgRestrictionMove || 移动保护,不存在的页面或特殊页面为<code lang="js">null</code>,存在的内容页面受全保护时为<code lang="js">["sysop"]</code>,受半保护时为<code lang="js">["autoconfirmed"]</code>,未保护为<code>[]</code>;不包含名字空间保护和级联保护 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgRevisionId || 当前显示的页面版本的编号,不存在时值为0。注意和index.php的oldid参数可能不同 || 由于[[special:移动版差异| |
| wgRevisionId || 当前显示的页面版本的编号,不存在时值为0。注意和index.php的oldid参数可能不同 || 由于[[special:移动版差异|{{int:diff}}]]页面不可同时显示历史页面,此时不可用 |
||
|- |
|- |
||
| wgTitle || 不含名字空间的页面名称 || 在[[special:历史|历史]]和[[special:移动版差异| |
| wgTitle || 不含名字空间的页面名称 || 在[[special:历史|历史]]和[[special:移动版差异|{{int:diff}}]]页面不可用 |
||
|- |
|- |
||
| wgUserEditCount || 当前用户的编辑次数 || 可用 |
| wgUserEditCount || 当前用户的编辑次数 || 可用 |
||
第101行: | 第101行: | ||
|} |
|} |
||
;mw.hook() |
;mw.hook() |
||
:这个方法是LLWiki建立异步JS框架的重要一环。常用以下两个方法: |
|||
:*<code>mw.hook(hook).fire(data)</code>: 用于唤起一个Hook事件,其中data为传递给事件处理程序的可选参数。 |
|||
:*<code>mw.hook(hook).add(handler)</code>: 用于处理一个Hook事件,handler为该事件处理函数,参数传递自<code>mw.hook().fire()</code>方法。 |
|||
:这个方法应与jQuery的event delegation和各Promise对象结合使用,以在恰当的时机执行恰当的函数。以下列举LLWiki常用的Hook事件。 |
|||
{| class="wikitable" |
|||
! Hook名称 !! 说明 |
|||
|- |
|||
! colspan=2 | MediaWiki预定义的Hook |
|||
|- |
|||
| postEdit || 一次非空编辑提交成功,一般发生在自动重载页面后,可以搭配<code lang="js">mw.config.get( 'wgPostEdit' )</code>。需要注意各类编辑小工具提交编辑后的页面重载均未适配这个事件 |
|||
|- |
|||
| structuredChangeFilters.ui.initialized || [[special:recentchanges|{{int:recentchanges}}]]、[[special:recentchangeslinked|{{int:recentchangeslinked}}]]和[[special:watchlist|{{int:watchlist}}]]页面的过滤器加载完成,一般至多发生一次 |
|||
|- |
|||
| wikipage.categories || 页面下方的<code lang="css">div#catlinks</code>加载完成。特殊页面或没有添加任何分类时也能触发,因为此时<code lang="css">#catlinks</code>仍然存在只是隐藏起来 |
|||
|- |
|||
| wikipage.collapsibleContent || 某个或某组<code>mw-collapsible</code>类的元素添加折叠JS完成 |
|||
|- |
|||
| wikipage.content || 最常用的Hook,表示页面内容(一般即<code lang="css">div#mw-content-text</code>)加载完成,几乎无处不在,与<code>$.ready</code>最大的区别在于这个事件可能多次触发 |
|||
|- |
|||
| wikipage.diff || 差异(一般即<code lang="css">table.diff</code>)加载完成 |
|||
|- |
|||
| wikipage.editform || 编辑区加载完成,需要注意此时[[mw:extension:wikiEditor/zh|WikiEditor]]的工具栏可能尚未加载完成 |
|||
|- |
|||
| codeEditor.configure || 切换至[[mw:extension:codeEditor/zh|CodeEditor]] |
|||
|- |
|||
! colspan=2 | LLWiki定义的Hook |
|||
|- |
|||
| code.prettify || 代码高亮完成 |
|||
|- |
|||
| codemirror.config || CodeMirror扩展的设置下载完成 |
|||
|- |
|||
| hotcat.ready || HotCat小工具加载完成 |
|||
|- |
|||
| local.comments || 签名时间替换为本地时区 |
|||
|- |
|||
| mobile.menu || 手机版的左侧主菜单加载完成 |
|||
|- |
|||
| transclusion.preview || 用于预览潜入页面的编辑区加载完成 |
|||
|- |
|||
| wikiplus.dialog || 打开Wikiplus小工具的对话框 |
|||
|} |
|||
;mw.loader |
;mw.loader |
||
;mw.notify() |
;mw.notify() |
||
第116行: | 第157行: | ||
====jquery==== |
====jquery==== |
||
jquery是任何页面都会预加载的两个环境模块之一,尤其在DOM操作和Ajax请求方面功能强大,非常推荐在JS编程之前预先熟悉[https://api.jquery.com/ API文档]。考虑到mw.loader已经集成了不少的常用Ajax方法,这里主要推荐熟练掌握DOM相关的内容,包括[https://api.jquery.com/category/events/ 事件]、[https://api.jquery.com/category/manipulation/ DOM操作]、[https://api.jquery.com/category/selectors/ 选择器]和[https://api.jquery.com/category/traversing/ 遍历]。特别需要提醒的是滥用htmlString有造成XSS的风险,因此请尽量使用如<code lang="js"><nowiki>$('<p>', {html: $('<a>', {text: '文字', href: 'https://llwiki.org'})})</nowiki></code>或<code lang="js"><nowiki>$('<p>').append( $('<a>').text('文字').attr('href', 'https://llwiki.org') )</nowiki></code>等语法进行规避。 |
jquery是任何页面都会预加载的两个环境模块之一,尤其在DOM操作和Ajax请求方面功能强大,非常推荐在JS编程之前预先熟悉[https://api.jquery.com/ API文档]。考虑到mw.loader已经集成了不少的常用Ajax方法,这里主要推荐熟练掌握DOM相关的内容,包括[https://api.jquery.com/category/events/ 事件]、[https://api.jquery.com/category/manipulation/ DOM操作]、[https://api.jquery.com/category/selectors/ 选择器]和[https://api.jquery.com/category/traversing/ 遍历]。特别需要提醒的是滥用htmlString有造成XSS的风险,因此请尽量使用如<code lang="js"><nowiki>$('<p>', {html: $('<a>', {text: '文字', href: 'https://llwiki.org'})})</nowiki></code>或<code lang="js"><nowiki>$('<p>').append( $('<a>').text('文字').attr('href', 'https://llwiki.org') )</nowiki></code>等语法进行规避。 |
||
因未被mw.loader包含而可能用到的Ajax方法主要为<code>$.getJSON()</code>,需要注意在MW的默认设置下调用jQuery的Ajax方法必须手动设置<code lang="js">{cache: true}</code>。 |
|||
另外jQuery也提供了一些[https://api.jquery.com/category/utilities/ 工具方法],可以用于缓解ResourceLoader的JS模块不允许使用ES6语法的问题,或是方便键值对相关的语句的书写,或是方便连锁。比如用<code>$.extend()</code>方法代替<code>...</code>算符、用<code>$.each(obj, (key, val) => {})</code>方法代替<code lang="js">for (const key in obj) {}</code>等。 |
另外jQuery也提供了一些[https://api.jquery.com/category/utilities/ 工具方法],可以用于缓解ResourceLoader的JS模块不允许使用ES6语法的问题,或是方便键值对相关的语句的书写,或是方便连锁。比如用<code>$.extend()</code>方法代替<code>...</code>算符、用<code>$.each(obj, (key, val) => {})</code>方法代替<code lang="js">for (const key in obj) {}</code>等。 |
||
应用jQuery时可能出现的一些常见错误列举如下: |
|||
*混淆<code>.attr()</code>方法和<code>.prop()</code>方法。 |
|||
*混淆jQuery对象的<code>.data()</code>方法和HTML元素的<code>.dataset</code>属性。 |
|||
*使用<code>.toggle()</code>、<code>.fadeToggle()</code>等方法时不慎破坏较复杂的CSS布局。 |
|||
*错误使用<code>.remove()</code>、<code>.clone()</code>等方法造成丢失数据和事件处理程序。 |
|||
*混淆<code>event.target</code>、<code>event.currentTarget</code>、<code>event.delegateTarget</code>和<code lang="js">this</code>关键字。 |
|||
*混淆<code>$.when()</code>方法和<code lang="js">Promise.all()</code>方法的参数格式和回调函数。 |
|||
====mediawiki.api==== |
====mediawiki.api==== |
||
====mediawiki.util==== |
====mediawiki.util==== |
於 2020年12月30日 (三) 05:02 的修訂
此頁面內容嚴重缺失,急需您幫忙補充!(點此編輯) 可參考同類條目添加所需內容,並從官方等可靠渠道搜集資料編寫,亦建議附上資料來源。
|
由於LLWiki使用的不是最新版本的MediaWiki系統以及MediaWiki的幫助頁面可能未得到及時和正確的更新,編輯這個頁面時請不要簡單地複製或翻譯來自MediaWiki的內容,應該在條件允許的情況下先實際測試。
全站CSS
這裏所說的全站CSS包含common.css、mobile.css和各CSS小工具,有時由於功能的相似性也會涉及用戶CSS(common.css、vector.css和minerva.css)。LLWiki暫時沒有建立針對不同用戶組的專門CSS頁面。
優先加載的CSS
一些CSS會以<link rel="stylesheet">
的形式在首次渲染前完成加載,包括common.css和各純CSS小工具,這些CSS頁面適合處理靜態HTML元素就需要的樣式。注意純CSS小工具即使在定義時規定了targets=mobile
也一定會在桌面版加載,因此手機版的專用CSS需要添加.skin-minerva
選擇器。
由於common.css本身就會優先加載,桌面版專用的全站CSS寫入該頁面即可,與手機版通用的CSS寫入gadget-site-styles.css。某個小工具專用的CSS如果需要用於靜態HTML元素,請將CSS部分單獨定義為type=styles
(可省略,但添加後方便區分)的純CSS小工具,然後以peers=<纯CSS小工具名称>
的語法添加到對應的JS小工具上。參見#小工具定義。
滯後加載的CSS
一些CSS的加載需要依賴JS,加載時機可能晚於首次渲染,包括mobile.css和除純CSS小工具以外的CSS小工具,這些CSS頁面適合處理依賴JS動態加載的HTML元素。
由於mobile.css加載滯後,靜態HTML元素需要的手機版樣式請添加.skin-minerva
選擇器後寫入gadget-site-styles.css。
CSS小工具分類
定義為type=styles
的小工具應添加純CSS小工具分類,其他CSS小工具應添加CSS小工具分類。其他分類與JS小工具一致,參見#小工具分類。
Widget(小部件)
小部件頁面格式
小部件分類
小部件JS的特殊之處
Gadget(小工具)和全站JS
這裏所涉及的JS頁面包含common.js、mobile.js和各JS小工具,有時由於功能的相似性也會涉及用戶JS(common.js、vector.js和minerva.js)。LLWiki暫時沒有建立針對不同用戶組的專門JS頁面。
ResourceLoader和JS模塊
不作為模塊的JS腳本
小工具定義
小工具簡介
小工具分類
MediaWiki核心模塊介紹
本章節介紹LLWiki使用或曾經使用的MediaWiki核心模塊,更完整的列表參見MediaWiki和JSDuck。
mediawiki
mediawiki是任何頁面都會預加載的兩個環境模塊之一,包含不少功能[1]。這裏只介紹LLWiki常使用的一些屬性和方法。
- mw.config
- 這個屬性提供了大量重要的站點、頁面和用戶信息[2],一般常用mw.config.get()方法獲取對應的變量值。下表整理了LLWiki常用的一些變量:
變量名 | 說明 | 手機版可用性 |
---|---|---|
skin | 皮膚 | 桌面版為「vector」,手機版為「minerva」,這也是區分桌面版和手機版的主要依據 |
wgFormattedNamespaces | 儲存了所有名字空間本地化譯名的數組,不過目前除了「模塊」都是英文 | 可用 |
wgNamespaceIds | 儲存了所有可接受的中英文名字空間名稱對應的編號,注意英文名稱中的空格都顯示為下劃線 | 可用 |
wgScript | /mediawiki/index.php ,在LLWiki也可簡化為/zh ,主要用於不同MediaWiki站點間的代碼通用,非必需 |
可用 |
wgAction | index.php的action參數[3] | 相比於桌面版,手機版由於添加了Special:歷史而少了「history」這個可能值 |
wgArticleId | 內容頁面編號,不存在時值為0,可以用於判斷是否是內容頁面且頁面是否已建立 | 需要注意查看歷史和差異時值為0 |
wgCanonicalSpecialPageName | 標準化的特殊頁面名,也可被wgPageName取代,主要用於不同MediaWiki站點間的代碼通用,非必需 | 可用,而且多了「History」和"MobileDiff"等可能的取值[4] |
wgCategories | 當前閱讀的歷史版本所屬的分類,不含名字空間,下劃線顯示為空格,且總是包含隱藏分類。繁簡規則一般遵從實際分類頁面,但似乎偶有例外 | 除非已執行MobileCategories小工具,否則不可用。另外桌面版的空值為[] ,手機版的空值為null ,注意可能的bug
|
wgCurRevisionId | 頁面最新的版本編號,不存在時值為0 | 在歷史和差異頁面不可用 |
wgIsArticle | 是否是內容頁面(包含由某個頁面的Wikitext原始碼解析生成的HTML,可能是歷史頁面和差異下方的歷史頁面) | 由於差異頁面不可同時顯示歷史頁面,此時不可用 |
wgIsRedirect | 最新版本是否是重定向頁面 | 在歷史和差異頁面不可用 |
wgIsProbablyEditable | 是否可能可以編輯 | 在歷史和差異頁面不可用 |
wgNamespaceNumber | 名字空間編號 | 在歷史和差異頁面會顯示為-1 |
wgPageContentModel | 頁面內容模型,特殊頁面為「wikitext」 | 由於歷史和差異是特殊頁面,會錯誤地顯示為「wikitext」 |
wgPageName | 頁面名稱,空格顯示為下劃線 | 在歷史和差異頁面不可用 |
wgRedirectFrom | 跳轉自重定向時為對應的重定向頁,空格顯示為下劃線 | 可用 |
wgRelevantPageName | 關聯的頁面名稱,空格顯示為下劃線 | 可以用於歷史和差異頁面,此時效果與桌面版一致 |
wgRelevantArticleId | 關聯的內容頁面編號,不存在時值為0 | 可以用於歷史和差異頁面,此時效果與桌面版一致 |
wgRelevantUserName | 關聯的用戶名 | 用戶貢獻頁面不可用 |
wgRelevantPageIsProbablyEditable | 關聯的頁面是否可能可以編輯 | 可以用於歷史和差異頁面,此時效果與桌面版一致 |
wgRestrictionEdit | 編輯保護,不存在的頁面(含受保護的標題)或特殊頁面為null ,存在的內容頁面受全保護時為["sysop"] ,受半保護時為["autoconfirmed"] ,未保護為[] ;不包含名字空間保護和級聯保護 |
在歷史和差異頁面不可用,另外未保護的內容頁面為["*"]
|
wgRestrictionMove | 移動保護,不存在的頁面或特殊頁面為null ,存在的內容頁面受全保護時為["sysop"] ,受半保護時為["autoconfirmed"] ,未保護為[] ;不包含名字空間保護和級聯保護 |
在歷史和差異頁面不可用 |
wgRevisionId | 當前顯示的頁面版本的編號,不存在時值為0。注意和index.php的oldid參數可能不同 | 由於差異頁面不可同時顯示歷史頁面,此時不可用 |
wgTitle | 不含名字空間的頁面名稱 | 在歷史和差異頁面不可用 |
wgUserEditCount | 當前用戶的編輯次數 | 可用 |
wgUserGroups | 當前用戶所屬的用戶組,未登入時為["*"] |
可用 |
wgUserLanguage | 當前用戶使用的界面語言 | 可用 |
wgUserName | 當前用戶的用戶名 | 可用 |
wgUserRegistration | 當前用戶的註冊時間,顯示為毫秒數;可以使用mw.user.getRegistration()方法替代,該方法會生成Date對象 | 可用 |
wgUserVariant | 當前用戶閱讀頁面時的內容語言,在不可更改內容語言的頁面總是為該用戶的默認內容語言 | 可用 |
wgDiffOldId | 差異頁面位於左側的版本的編號 | 不可用 |
wgDiffNewId | 差異頁面位於右側的版本的編號 | 不可用 |
- mw.hook()
- 這個方法是LLWiki建立異步JS框架的重要一環。常用以下兩個方法:
mw.hook(hook).fire(data)
: 用於喚起一個Hook事件,其中data為傳遞給事件處理程序的可選參數。mw.hook(hook).add(handler)
: 用於處理一個Hook事件,handler為該事件處理函數,參數傳遞自mw.hook().fire()
方法。
- 這個方法應與jQuery的event delegation和各Promise對象結合使用,以在恰當的時機執行恰當的函數。以下列舉LLWiki常用的Hook事件。
Hook名稱 | 說明 |
---|---|
MediaWiki預定義的Hook | |
postEdit | 一次非空編輯提交成功,一般發生在自動重載頁面後,可以搭配mw.config.get( 'wgPostEdit' ) 。需要注意各類編輯小工具提交編輯後的頁面重載均未適配這個事件
|
structuredChangeFilters.ui.initialized | 最近修改、相關變更和監視清單頁面的過濾器加載完成,一般至多發生一次 |
wikipage.categories | 頁面下方的div#catlinks 加載完成。特殊頁面或沒有添加任何分類時也能觸發,因為此時#catlinks 仍然存在只是隱藏起來
|
wikipage.collapsibleContent | 某個或某組mw-collapsible 類的元素添加摺疊JS完成
|
wikipage.content | 最常用的Hook,表示頁面內容(一般即div#mw-content-text )加載完成,幾乎無處不在,與$.ready 最大的區別在於這個事件可能多次觸發
|
wikipage.diff | 差異(一般即table.diff )加載完成
|
wikipage.editform | 編輯區加載完成,需要注意此時WikiEditor的工具欄可能尚未加載完成 |
codeEditor.configure | 切換至CodeEditor |
LLWiki定義的Hook | |
code.prettify | 代碼高亮完成 |
codemirror.config | CodeMirror擴展的設置下載完成 |
hotcat.ready | HotCat小工具加載完成 |
local.comments | 簽名時間替換為本地時區 |
mobile.menu | 手機版的左側主菜單加載完成 |
transclusion.preview | 用於預覽潛入頁面的編輯區加載完成 |
wikiplus.dialog | 打開Wikiplus小工具的對話框 |
- mw.loader
- mw.notify()
- 調用這個方法可以在桌面版的右上角、手機版的上方顯示一個泡泡通知。LLWiki一般使用這個方法取代window.alert()或OO.ui.alert()。
- 方法
mw.notify(message, options)
接受兩個參數。第一個必需參數message
指定通知內容,可以是字符串、HTML元素對象或元素對象數組、jQuery對象或mw.message對象;第二個可選參數options
則指定自定義選項,是一個JS對象。 options
中可自定義的選項有:autoHide
:布爾值,決定通知是否會自行消失。默認為true
。autoHideSeconds
:如果啟用了autoHide
(如默認情形),則指定通知自行消失的時間。默認為'short'
(5秒),可以指定為'long'
(30秒)。tag
:字符串,指定通知的標籤,類似於HTML的ID。如果發送多個擁有同一個tag的通知,會導致之前的通知被後來的在原位覆蓋。title
:標題。如果指定,則會於內容上方加粗顯示。type
:字符串,指定通知的種類。除默認效果外其他可選類型為'success'
、'warn'
和'error'
。
- mw.now()
- 這個方法理論上和Date.now()差不多,但實際測試表明和Date.now()的取值不同,因此請勿混合使用。非必需,基本可以完全被Date.now()替換。
jquery
jquery是任何頁面都會預加載的兩個環境模塊之一,尤其在DOM操作和Ajax請求方面功能強大,非常推薦在JS編程之前預先熟悉API文檔。考慮到mw.loader已經集成了不少的常用Ajax方法,這裏主要推薦熟練掌握DOM相關的內容,包括事件、DOM操作、選擇器和遍歷。特別需要提醒的是濫用htmlString有造成XSS的風險,因此請儘量使用如$('<p>', {html: $('<a>', {text: '文字', href: 'https://llwiki.org'})})
或$('<p>').append( $('<a>').text('文字').attr('href', 'https://llwiki.org') )
等語法進行規避。
因未被mw.loader包含而可能用到的Ajax方法主要為$.getJSON()
,需要注意在MW的默認設置下調用jQuery的Ajax方法必須手動設置{cache: true}
。
另外jQuery也提供了一些工具方法,可以用於緩解ResourceLoader的JS模塊不允許使用ES6語法的問題,或是方便鍵值對相關的語句的書寫,或是方便連鎖。比如用$.extend()
方法代替...
算符、用$.each(obj, (key, val) => {})
方法代替for (const key in obj) {}
等。
應用jQuery時可能出現的一些常見錯誤列舉如下:
- 混淆
.attr()
方法和.prop()
方法。 - 混淆jQuery對象的
.data()
方法和HTML元素的.dataset
屬性。 - 使用
.toggle()
、.fadeToggle()
等方法時不慎破壞較複雜的CSS佈局。 - 錯誤使用
.remove()
、.clone()
等方法造成丟失數據和事件處理程序。 - 混淆
event.target
、event.currentTarget
、event.delegateTarget
和this
關鍵字。 - 混淆
$.when()
方法和Promise.all()
方法的參數格式和回調函數。
mediawiki.api
mediawiki.util
mediawiki.Uri
mediawiki.storage
mediawiki.cookie
user.options
jquery.makeCollapsible
jquery.tablesorter
jquery.textSelection
jquery.client
jquery.color
jquery.ui
jquery.tipsy
jquery.chosen
oojs-ui-core
oojs-ui-windows
mediawiki.widgets
LLWiki添加的全局變量和方法
- window.wgULS()和window.wgUCS()[5]
- mw.gadgets
- mw.request
- mw.widget
- mw.windowManager
- mw.standardQuery()[5]
- mw.apiFailure()[5]
- mw.safeEdit()[5]
- mw.resizeLyrics()[6]
ESLint
CodeEditor使用ESLint標註可能存在的語法問題。LLWiki並未在後台預先規定太多規則,目前比較常用的僅是在"use strict";
的基礎上添加/*global mw, $, OO, wgULS*/
或類似語句註明全局變量。特別要注意ESLint並不會對大多數JS模塊不允許使用的ES6語法(async/await語法是已知的唯一例外)作出警告(詳見#ResourceLoader和JS模塊),因此請勿過度依賴這一功能來除錯。
注意事項
手機版
手機版解析器
圖片懶加載
手機版CSS
手機版LLWiki使用Minerva Neue皮膚,與桌面版的Vector皮膚相比,不僅界面有很大差異,眾多基礎HTML元素也都添加了不同的CSS樣式。為了適配窄屏設備,Minerva皮膚還添加了大量基於@media
的規則,一般以設備寬度720px為分界使用不同的樣式。以下着重介紹<table>
和<img>
這兩種需要CSS修正的重災區。
手機版CSS很多時候依賴外層容器的content
類來生效,與此同時#mw-content-text .mw-parser-output
的外層結構也同樣有效,設計各種基於API的快速編輯工具(如Wikiplus等)的預覽界面時需要考慮。
表格
對於<table>
元素及其子節點,手機版已知會自動添加以下樣式:
table, caption, tbody, tfoot, thead, tr, th, td {
font-size: 100%;
}
table {
border-collapse: collapse;
}
.content table {
margin: 1em 0;
overflow: auto;
overflow-y: hidden;
overflow-x: auto;
}
@media only screen and (max-width: 720px) {
.content table {
display: block;
width: 100% !important;
}
}
這裏重點說明一下第二和第四條規則造成的影響。第二條規則使得表格的外層邊框、行邊框和單元格邊框合併,可能造成一系列關於邊框的CSS規則出現不符合預期的表現,尤其是<table>
的cellspacing
屬性會無法生效。因此一般建議避免使用cellspacing
這一HTML屬性,改為使用CSS中的border-spacing
。另外,在需要border-spacing
或border-radius
等樣式時,請同時指定border-collapse: separate;
以使手機版生效。
第四條規則的本意是在窄屏上<table>
元素不會將頁面撐得過寬,但這同時會造成外層的<table>
和內層的<tbody>
分離。特別是如果外層<table>
規定了邊框或背景色時,很容易看出樣式的錯誤。為此一般需要主動指定display: table;
以修復這一問題,LLWiki有很多預定義的表格CSS類也都添加了這一規則[7]。但這樣修改的話又會重新面臨過寬的表格將整個頁面撐大的問題。LLWiki現定義了table-wrapper
類[7],用於套在寬表格外:<div class="table-wrapper">
,這個外層容器會在窄屏上通過overflow-x: auto;
限制裏面的表格寬度。
圖片
皮膚界面
其他
手機版JS
手機版JS模塊
繁簡轉換
Wikitext繁簡轉換
轉換表
Template:NoteTA
基本手工轉換語法
系統消息
CSS繁簡轉換
JS繁簡轉換
濫用過濾器
測試賬戶
如果管理員需要一個沒有自確權限的測試賬戶用於濫用過濾器測試、小工具測試等,可以臨時啟用6號濫用過濾器來移除某個測試賬戶的自確權限。這個濫用過濾器的使用語法非常簡單,請根據樣例修改為對應的用戶名即可,這裏不再贅述。