Как стать автором
Обновить

Отключаем библиотеку jQuery, встроенную в движок MediaWiki 1.16.x, и заменяем её на свежую, обновляемую и пополняемую администраторами вики

Время на прочтение7 мин
Количество просмотров3.1K


Как нетрудно прочесть на сайте 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('&section=T') == -1 )  a.title = a.title.replace(/:.*$/,': 0')
 else a.title = 'Править секцию: 0'
 a.setAttribute('href', wgScript + '?title='+encodeURIComponent(wgPageName) + '&action=edit&section=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 делает возможным, заслуживают, пожалуй, отдельных блогозаписей на Хабрахабре, но нынешний рассказ мой окончен.
Теги:
Хабы:
Всего голосов 38: ↑24 и ↓14+10
Комментарии13

Публикации

Истории

Ближайшие события