Как нетрудно прочесть
на сайте MediaWiki, нынешняя линейка стабильных версий (1.16.x) поставляется со встроенною библиотекою jQuery, код которой лежит по адресу
«skins/common/jquery.min.js». Это jQuery сравнительно старой версии (1.3.2, вышедшая в феврале 2009 года), слегка запатченная для преодоления одного из её багов, и она запускается в режиме совместимости
(«noConflict()») таким образом, чтобы поместиться
в переменную $j вместо $. Этот код jQuery не содержит никаких плагинов и является, в сущности, необязательным, подключаясь к странице только в том случае, когда код MediaWiki содержит вызов метода
$wgOut->includeJQuery(). Скажем, расширение
UsabilityInitiative содержит именно такой вызов на строке 128 своего файла
«UsabilityInitiative.hooks.php», так что jQuery появляется в некоторых темах оформления (например, в Vector), когда расширение UsabilityInitiative подключено к вики.
Предлагаю встать на точку зрения
вики-техника, то есть администратора сервера MediaWiki, имеющего прямой доступ (наподобие SSH) и возможность менять настройки вики (LocalSettings.php), доустанавливать расширения MediaWiki и проводить другие подобные действия. Какие обстоятельства могут вызвать
у вики-техника MediaWiki 1.16.x стремление переменить к лучшему то положение дел, которое упомянуто в предыдущем абзаце? Каким путём уместнее всего действовать
вики-технику на пути воплощения этого своего стремления?
Первотолчком такого стремления является естественное и почти неизбежное осознание того, как неудобна та
необязательность появления jQuery в коде страниц, которая настроена по умолчанию. Всякий
вики-техник, если он имеет достаточно досуга для размышлений, рано или поздно постигает, что простота и могущество
функции $(…), если бы она была
всегда в распоряжении администраторов, сочиняющих скрипты для вики, всенепременно породили бы
JS-код куда компактнее, чем прежний. Возьмём для примера
версию от 22 мая 2011 года страницы «MediaWiki:Common.js» из россияноязычной Википедии. В ней нетрудно заметить вот какой код функции:
function editZeroSection(){
var body = document.getElementById('bodyContent')
if (!body) return
var h2s = body.getElementsByTagName('H2')
var h2 = h2s[0]
if (!h2) return
if (h2.parentNode.id == 'toctitle') h2 = h2s[1]
if (!h2) return
var span = h2.firstChild
if (!span || span.className != 'editsection') return
var zero = span.cloneNode(true)
body.insertBefore(zero, body.firstChild)
var a = zero.getElementsByTagName('a')[0]
if (a.href.indexOf('§ion=T') == -1 ) a.title = a.title.replace(/:.*$/,': 0')
else a.title = 'Править секцию: 0'
a.setAttribute('href', wgScript + '?title='+encodeURIComponent(wgPageName) + '&action=edit§ion=0')
}
Любому поклоннику jQuery хорошо известно, как эта библиотека напрочь избавила бы авторов функции от необходимости прибегать
к getElementById() и getElementsByTagName(), а также предоставила бы сокращённые аналоги некоторых других методов и полей. А ведь такая функция там не одна. Не одна и такая вики: аналогичные громоздкости нетрудно усмотреть, скажем,
в версии от 28 мая 2011 года страницы «MediaWiki:Common.js» из «Абсурдопедии».
Предположим,
что вики-техник обеспечил неукоснительность появления jQuery в коде страницы, последовав
официальной инструкции и пополнив файл «LocalSettings.php» соответствующим кодом:
// Include jQuery
function wfIncludeJQuery() {
global $wgOut;
$wgOut->includeJQuery();
}
$wgExtensionFunctions[] = 'wfIncludeJQuery';
Администраторы вики, обладая правами править страницу «MediaWiki:Common.js», начали переписывать тамошние функции на jQuery,
использовать $(…) вместо
addOnloadHook(…), и так далее. Какие два камня преткновения ожидают этот процесс в дальнейшем?
Во-первых, при знакомстве с историей jQuery непременно вскроется,
что версия 1.3.2 (как я ужé упоминал чуть выше) появилась давненько —
аж в феврале 2009 года. Постоянным читателям хабрахабровского
блога jQuery и рассказывать не надо, как велико и значительно было развитие библиотеки за истекшие с той поры 2⅓ года; для всех остальных я просто приведу в пример
ускорение анимации в версии 1.4.3, новые интерфейсы
deferred ([1], [2]) в версии 1.5,
полную поддержку IE9 в версии 1.5.1… а изменения в версии 1.4 вообще
на 14 страницах излагаются.
Во-вторых, едва покончив с переводом существующих скриптов
на jQ-основу, администраторы вики закономерно призадумаются о том, какие ещё возможности открываются для автоматизации (заскриптовывания) вики в лучшую сторону. Почти неизбежно при этом их знакомство с таким потрясающим инструментом, каким служат плагины jQuery, позволяющие нехитрым способом («копипастою») во мгновение ока снабжать сайт значительными, впечатляющими улучшениями. Например, достаточно добавить
jQuery.ScrollTo да jQuery.LocalScroll — и тотчас же
сразу все внутристраничные гиперссылки можно будет снабдить зрелищной анимацией прокручивания страницы, задействовав несложный скрипт:
$(function(){
$.localScroll({
hash: true,
onAfter: function(target){
location = '#' + ( target.id || target.name );
}
});
});
Для вики на движке MediaWiki, с его автоматическими оглавлениями статей, такое улучшение поведения неоценимо.
Мы видим: на этом этапе ход событий неумолимо подталкивает
вики-техника к тому, чтобы создать файл (лучше всего —
один файл, чтобы не тратилось время на лишние запросы к серверу), содержащий и новую версию библиотеки jQuery, и все желаемые плагины к ней. Сгодится ли
«skins/common/jquery.min.js» на роль такого файла? Мало вероятно, и на то есть две причины.
Во-первых, как известно, любой переход на новую версию MediaWiki (даже с версии 1.16.x на версию
1.16.x+1) сопряжён с записыванием новых файлов поверх старых — малейшая невнимательность обновляющего может привести к тому, что файл
«skins/common/jquery.min.js» будет вновь заменён версией jQuery, поставляемой с MediaWiki (1.3.2, без плагинов).
Во-вторых, вообще
не очень-то логично поручать обновление jQuery и плагинов
вики-технику и требовать для этого прав прямого доступа
к вики-серверу, раз уж многие другие джаваскрипты MediaWiki (такие, как вышеупомянутый «MediaWiki:Common.js», например) может править любой администратор через интерфейс самóй вики, к тому же снабжённый удобной встроенной системою контроля версий и просмотра разности правок. Получается, что логичнее было бы и jQuery, вместе со всеми уместными в конкретной вики плагинами, разместить на странице с именем «MediaWiki:jQuery.js», да на том успокоиться.
Достижимо ли такое размещение в техническом отношении? Да, вполне достижимо; для него достаточно только убрать из файла «LocalSettings.php» тот код с вызовом метода
includeJQuery(), который был туда добавлен на предыдущем этапе — а вместо него подключить вызов такого расширения MediaWiki, которое обеспечивало бы подключение скрипта «MediaWiki:jQuery.js», да вдобавок выкусывало бы вызов скрипта
«skins/common/jquery.min.js» на тот случай, если вызов метода
includeJQuery() всё же поступит
от какого-нибудь другого расширения.
Задача о сочинении такого кода расширения MediaWiki, который подключил бы «MediaWiki:jQuery.js» к каждой странице вики, давно решена мною — ответ её (код его) выглядит следующим образом (включая лицензию MIT):
<?php
/*
* jQuery.php - Adds jQuery script to the <head> . . . </head>
* @author Mithgol the Webmaster
* @version 0.2
* @copyright Copyright (C) 2010 Mithgol the Webmaster
* @license The MIT License - http://www.opensource.org/licenses/mit-license.php
* ---------------------------------------------------------------------------------------
* Copyright (c) 2010 Mithgol the Webmaster
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
* -----------------------------------------------------------------------
* Version notes:
* version 0.2:
* erase MediaWiki's internal jQuery call, which lacks plugins
* version 0.1:
* initial release
* -----------------------------------------------------------------------
*/
# Confirm MW environment
if (defined('MEDIAWIKI')) {
# Credits
$wgExtensionCredits['other'][] = array(
'name' => 'jQuery',
'author' => 'Mithgol the Webmaster',
'url' => 'http://traditio.ru/wiki/JQuery_%D0%B4%D0%BB%D1%8F_MediaWiki',
'description' => 'Adds jQuery to the list of scripts (HEAD element).',
'version' => '0.2'
);
function jQueryMyHook( &$output, &$skin ) {
$output->mScripts = "\t\t".
'<script type="text/javascript" src="/w/index.php?title=MediaWiki:jQuery.js&action=raw&ctype=text/javascript"></script>'.
"\n" . preg_replace('/<script src="\/w\/skins\/common\/jquery\.min\.js\?\d+"><\/script>/', '<!-- jQuery double, erased -->', $output->mScripts);
return true;
}
$wgHooks['BeforePageDisplay'][] = 'jQueryMyHook';
} # End MW Environment wrapper
?>![]()
Обратите внимание, что выкусыватель файла
«skins/common/jquery.min.js» учитывает манеру MediaWiki прибавлять
«?» и число к URLу скрипта.
При наполнении файла «MediaWiki:jQuery.js» уместно обеспечить обратную совместимость
с «skins/common/jquery.min.js» по формату имени jQuery. Для этой цели вполне достаточно поместить в файл «MediaWiki:jQuery.js» дополнительно вот какой код:
/* По меньшей мере два скрипта MediaWiki:
* 1) /skins/common/edit.js
* 2) /skins/common/preview.js
* полагаются на то, что jQuery можно вызвать переменною $j.
* Так не разочаруем же их:
*/
$j=$;
Очевидно, надеюсь, что этот синоним должен создаваться после кода самóй библиотеки jQuery.
Вышеприведённое расширение внедрено в русской
вики-энциклопедии «Традиция» в 2010 году и успело на деле всецело доказать свою пригодность. Некоторые из тех улучшений и удобств, созданных скриптами, которые употребление jQuery в MediaWiki делает возможным, заслуживают, пожалуй, отдельных блогозаписей на Хабрахабре, но нынешний рассказ мой окончен.