Нет описания правки
мНет описания правки
 
(не показаны 84 промежуточные версии 2 участников)
Строка 14: Строка 14:
/* global mw, $ */
/* global mw, $ */
/* jshint strict:false, browser:true */
/* jshint strict:false, browser:true */
 
//console.log('→ [Common.js] Tag‑Capitalizer стартует');
mw.loader.using( [ 'mediawiki.util' ] ).done( function () {
mw.loader.using( [ 'mediawiki.util' ] ).done( function () {
/* Begin of mw.loader.using callback */
/* Begin of mw.loader.using callback */
Строка 141: Строка 142:
mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );
mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );


/* Попытка изменить межстрочное расстояние при печати poem
window.onbeforeprint = function() {
  var poems = document.querySelectorAll('.poem');
  poems.forEach(function(poem) {
    poem.style.lineHeight = '0.6';
  });
}
*/
/* Добавление обработки - при сохранении формы заменять первые буквы в значениях Tag на прописные */
/*
$(document).ready(function() {
    // Обработка поля с тегами в реальном времени
    $(document).on('select2:select select2:unselect', 'select[name="Song[Tag][]"]', function(e) {
        const $select = $(this);
        const tags = $select.val() || [];
       
        const formattedTags = tags.map(tag => {
            const trimmed = tag.trim();
            if (trimmed.length === 0) return '';
            return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
        });
       
        // Обновляем значения без перезагрузки виджета
        $select.val(formattedTags).trigger('change');
    });
    // Финишное форматирование перед отправкой
    $('#pfForm').on('submit', function(e) {
        const $select = $('select[name="Song[Tag][]"]');
        const tags = $select.val() || [];
       
        const formattedTags = tags.map(tag => {
            const trimmed = tag.trim();
            if (trimmed.length === 0) return '';
            return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
        });
       
        $select.val(formattedTags);
    });
});
*/
/* Оно же - другой вариант
$(document).ready(function() {
    function processTag(tag) {
        return tag.replace(/^([а-я])/, function(match) {
            return match.toUpperCase();
        });
    }
    function handleInput(event) {
        const $input = $(this);
        const cursorPos = $input.prop('selectionStart');
        const originalValue = $input.val();
       
        const newValue = originalValue.split(',')
            .map(tag => {
                const trimmed = tag.trim();
                return trimmed ? processTag(trimmed) : '';
            })
            .filter(tag => tag !== '')
            .join(', ');
        if (newValue !== originalValue) {
            $input.val(newValue);
            const delta = newValue.length - originalValue.length;
            $input.prop('selectionStart', cursorPos + delta);
            $input.prop('selectionEnd', cursorPos + delta);
        }
    }
    // Для обычных полей
    $('input[name="Tag"]')
        .on('input', handleInput)
        .on('change', handleInput);
    // Для динамических полей (автодополнение)
    $(document).on('mw.widgets.TagMultiselectWidget', '.mw-widgets-tagMultiselectWidget', function(e) {
        $(this).find('input').on('input change', handleInput);
    });
});
*/
/* Add customized buttons for Wikieditor toolbar */
/* Add customized buttons for Wikieditor toolbar */
/* Добавление кнопок в Wikieditor toolbar */
/* Добавление кнопок в Wikieditor toolbar */
Строка 275: Строка 360:
type: 'encapsulate',
type: 'encapsulate',
options: {
options: {
//peri: ':::',
//peri: '   ',
regex: /^/gm,
regex: /^/gm,
         regexReplace: ":::"//,
         regexReplace: "   "//,
//ownline: true
//ownline: true
}
}
Строка 327: Строка 412:
label: 'Вставить тэг Poem для текста песни',
label: 'Вставить тэг Poem для текста песни',
type: 'button',
type: 'button',
icon: 'https://upload.wikimedia.org/wikipedia/commons/2/29/Button_double_angle_quotes_with_ellipsis.png',
icon: 'https://bard-wiki.net/images/6/66/Button_Poem2.png',
action: {
action: {
type: 'encapsulate',
type: 'encapsulate',
Строка 343: Строка 428:
//}
//}


// Check if we're editing a page.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
// Add a hook handler.
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
// Configure a new toolbar entry on the given $textarea jQuery object.
$free_text.wikiEditor( 'addToToolbar', {
section: 'advanced',
group: 'format',
tools: {
math: {
label: 'Вставить тэг Poem 1 столбец для текста песни',
type: 'button',
icon: 'https://bard-wiki.net/images/8/84/Button_Poem_1st.png',
action: {
type: 'encapsulate',
options: {
pre: '<poem c=1>',
post: '</poem>',
ownline: true
}
}
}
}
} );


// Check if we're editing a page.
} );
//}
// Для аккордов.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
// Add a hook handler.
// Add a hook handler.
Строка 354: Строка 465:
tools: {
tools: {
math: {
math: {
label: 'Вставить тэг NoWiki для текста с аккордами',
label: 'Вставить тэг для текста с аккордами',
type: 'button',
type: 'button',
icon: 'https://song.bard-radio.ru/resources/src/mediawiki.icon/images/Button_nowiki.png',
icon: 'https://bard-wiki.net/images/f/ff/Button_accord.png',
action: {
action: {
type: 'encapsulate',
type: 'encapsulate',
options: {
options: {
pre: ' <nowiki>',
pre: '===Аккорды===\n<poem c=1>\n',
post: '</nowiki>',
post: '</poem>',
ownline: true
ownline: true
}
}
Строка 372: Строка 483:
//}
//}


// Check if we're editing a page.
// Убираем переводы строк.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
// Add a hook handler.
// Add a hook handler.
Строка 388: Строка 499:
type: 'encapsulate',
type: 'encapsulate',
options: {
options: {
regex: /(\n{3})/gm,
        regexReplace: "\n\n",
}
}
}
}
} );
} );
//}
//
//
/*
//Добавление кнопки для исправления автора
mw.hook('wikiEditor.toolbarReady').add(function($toolbar) {
  $toolbar.wikiEditor('addToToolbar', {
    section: 'advanced',
    group: 'format',
    tools: {
      updatePersona: {
        label: 'Обновить Persona',
        type: 'button',
        icon: 'https://commons.wikimedia.org/wiki/File:Vector_toolbar_big_text_button.png',
        action: {
          type: 'callback',
          execute: function(context) {
            var wikiText = context.$textarea.val();
            if (wikiText.indexOf('{{Persona') === -1) {
              return;
            }
            var updatedWikiText = wikiText.replace(/\|Name=([^|\n]*)/, function(match, p1) {
              return '|Name=' + p1.trim().replace(/_/g, ' ');
            });
            updatedWikiText = updatedWikiText.replace(/\|FullName=([^|\n]*)/, function(match, p1) {
              var fullNameParts = p1.trim().split(',').map(function(namePart) {
                return namePart.trim().replace(/_/g, ' ');
              });
              return '|FullName=' + fullNameParts.join(', ');
            });
            context.$textarea.val(updatedWikiText);
          }
        }
      }
    }
  });
});
*/
//
//
//
//
//
//
//
//
// Для цитаты.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
// Add a hook handler.
mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
// Configure a new toolbar entry on the given $textarea jQuery object.
$free_text.wikiEditor( 'addToToolbar', {
section: 'advanced',
group: 'format',
tools: {
math: {
label: 'Вставить тэги для цитаты',
type: 'button',
icon: 'https://upload.wikimedia.org/wikipedia/commons/1/13/Button-citiranje.PNG',
action: {
type: 'encapsulate',
type: 'encapsulate',
options: {
options: {
//peri: ':::',
pre: '<blockquote>',
regex: /\n\n\n/gm,
post: '</blockquote>',
        regexReplace: "\n\n"
ownline: true
//ownline: true
}
}
}
}
}
Строка 435: Строка 619:
}
}
/* End of mw.loader.using callback */
/* End of mw.loader.using callback */
$(document).ready(function() {
  $('div.poem p').each(function() {
    var text = $(this).html();
    // Заменяем двойные переводы строк на уникальный маркер
    var markedText = text.replace(/\n\s*\n/g, '<doublebr>\n');
    // Разделяем текст на строки
    var lines = markedText.split('\n');
    // Перекрашивание строки, начинающейся с запятой в синий цвет
    for (var i = 0; i < lines.length; i++) {
      if (lines[i].trim().startsWith(',')) {
        lines[i] = '<span style="color:Blue">' + lines[i].trim().replace(',', ' ') + '</span>';
      }
    }
    // Объединяем строки обратно в текст, заменяя переводы строк на '<br>'
    var html = lines.join('<br>');
    // Заменяем уникальный маркер обратно на '<br>'
    html = html.replace(/<doublebr>/g, '<br>');
    $(this).html(html);
  });
});
} );
} );
//Код для вставления на форму панели edittools
mw.loader.using(['ext.pageforms.main', 'mediawiki.util'], function() {
    $(document).ready(function() {
        // Проверяем, что мы на странице редактирования формы
        if ($('form[name="createbox"]').length > 0 || $('.pfForm').length > 0) {
           
            // Получаем содержимое EditTools из MediaWiki
            var api = new mw.Api();
           
            api.get({
                action: 'parse',
                page: 'MediaWiki:Edittools',
                prop: 'text',
                disablelimitreport: true
            }).done(function(data) {
                if (data.parse && data.parse.text && data.parse.text['*']) {
                    var edittoolsHtml = data.parse.text['*'];
                   
                    // Создаём контейнер для EditTools
                    var edittoolsContainer = $('<div id="edittools-container"></div>').css({
                        'margin-top': '20px',
                        'padding': '10px',
                        'border-top': '1px solid #a2a9b1',
                        'background': '#f8f9fa'
                    });
                   
                    // Вставляем HTML EditTools
                    edittoolsContainer.html(edittoolsHtml);
                   
                    // Функция для поиска правильного поля ввода
                    function findTargetField() {
                        // Сначала ищем поле в фокусе, но исключаем служебные поля
                        var focusedField = $('input:focus, textarea:focus').filter(function() {
                            var $this = $(this);
                            var name = $this.attr('name') || '';
                            var id = $this.attr('id') || '';
                           
                            // Исключаем служебные поля MediaWiki
                            return !name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                  !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                  !$this.hasClass('mw-summary');
                        });
                       
                        if (focusedField.length > 0) {
                            return focusedField.first();
                        }
                       
                        // Если нет поля в фокусе, ищем поля формы (исключая служебные)
                        var formFields = $('form[name="createbox"] input[type="text"], form[name="createbox"] textarea, .pfForm input[type="text"], .pfForm textarea').filter(function() {
                            var $this = $(this);
                            var name = $this.attr('name') || '';
                            var id = $this.attr('id') || '';
                           
                            // Исключаем служебные поля
                            return !name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                  !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                  !$this.hasClass('mw-summary') &&
                                  $this.is(':visible');
                        });
                       
                        // Возвращаем последнее использованное поле или первое доступное
                        if (window.lastUsedField && window.lastUsedField.length > 0 && $.contains(document, window.lastUsedField[0])) {
                            return window.lastUsedField;
                        }
                       
                        return formFields.first();
                    }
                   
                    // Отслеживаем последнее использованное поле
                    $(document).on('focus', 'input, textarea', function() {
                        var $this = $(this);
                        var name = $this.attr('name') || '';
                        var id = $this.attr('id') || '';
                       
                        // Сохраняем только поля формы, не служебные
                        if (!name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                            !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                            !$this.hasClass('mw-summary')) {
                            window.lastUsedField = $this;
                        }
                    });
                   
                    // Обрабатываем все ссылки в EditTools для вставки символов
                    edittoolsContainer.find('a').each(function() {
                        var $link = $(this);
                        var originalHref = $link.attr('href');
                       
                        // Если это ссылка на вставку символа (javascript:insertTags)
                        if (originalHref && originalHref.indexOf('javascript:insertTags') === 0) {
                            $link.click(function(e) {
                                e.preventDefault();
                               
                                // Извлекаем символ из href
                                var match = originalHref.match(/insertTags\('([^']*)',\s*'([^']*)',\s*'([^']*)'\)/);
                                if (match) {
                                    var prefix = match[1] || '';
                                    var suffix = match[2] || '';
                                    var symbol = match[3] || '';
                                   
                                    var textToInsert = prefix + symbol + suffix;
                                   
                                    var activeField = findTargetField();
                                   
                                    if (activeField.length > 0) {
                                        // Вставляем текст
                                        var currentValue = activeField.val();
                                        var cursorPos = activeField[0].selectionStart || currentValue.length;
                                        var newValue = currentValue.substring(0, cursorPos) + textToInsert + currentValue.substring(cursorPos);
                                        activeField.val(newValue);
                                       
                                        // Возвращаем фокус
                                        activeField.focus();
                                        if (activeField[0].setSelectionRange) {
                                            activeField[0].setSelectionRange(cursorPos + textToInsert.length, cursorPos + textToInsert.length);
                                        }
                                       
                                        // Сохраняем как последнее использованное поле
                                        window.lastUsedField = activeField;
                                    }
                                }
                               
                                return false;
                            });
                        }
                        // Если это обычная ссылка с текстом для вставки
                        else if ($link.text().trim().length > 0 && !originalHref) {
                            $link.click(function(e) {
                                e.preventDefault();
                               
                                var symbol = $(this).text();
                               
                                var activeField = findTargetField();
                               
                                if (activeField.length > 0) {
                                    var currentValue = activeField.val();
                                    var cursorPos = activeField.length > 0 && activeField[0].selectionStart !== undefined ? activeField[0].selectionStart : currentValue.length;
                                    var newValue = currentValue.substring(0, cursorPos) + symbol + currentValue.substring(cursorPos);
                                    activeField.val(newValue);
                                   
                                    activeField.focus();
                                    if (activeField[0].setSelectionRange) {
                                        activeField[0].setSelectionRange(cursorPos + symbol.length, cursorPos + symbol.length);
                                    }
                                   
                                    // Сохраняем как последнее использованное поле
                                    window.lastUsedField = activeField;
                                }
                               
                                return false;
                            });
                        }
                    });
                   
                    // Размещаем панель внизу формы
                    var form = $('form[name="createbox"], .pfForm').first();
                    if (form.length > 0) {
                        form.after(edittoolsContainer);
                    }
                }
            }).fail(function() {
                console.error('Не удалось загрузить EditTools');
            });
        }
    });
}).fail(function() {
    console.error('Не удалось загрузить модули для EditTools');
});
// Показываем дополнительные вкладки только на Главной
mw.loader.using( 'mediawiki.util', function () {
    // Проверяем, главная ли сейчас страница
    if ( mw.config.get( 'wgIsMainPage' ) ) {
        // «Предложения»
        mw.util.addPortletLink(
            'p-namespaces',
            mw.util.getUrl( 'Project:Предложения' ),
            'Предложения',
            'ca-proposals',
            'Предложения к содержимому Главной'
        );
        // «Заявки»
        mw.util.addPortletLink(
            'p-namespaces',
            mw.util.getUrl( 'Project:Заявки' ),
            'Заявки',
            'ca-requests',
            'Заявки на изменение Главной'
        );
    }
});
mw.hook('wikipage.content').add(function ($content) {
  $content.on('click', '#votebox.vote-clickable', function (e) {
    e.preventDefault();
    e.stopPropagation();
    var link = document.querySelector('.vote-vote-link');
    if (!link) {
      return;
    }
    link.dispatchEvent(
      new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        view: window
      })
    );
  });
});
/* DO NOT ADD CODE BELOW THIS LINE */
/* DO NOT ADD CODE BELOW THIS LINE */

Текущая версия от 21:29, 6 января 2026

/**
 * Keep code in MediaWiki:Common.js to a minimum as it is unconditionally
 * loaded for all users on every wiki page. If possible create a gadget that is
 * enabled by default instead of adding it here (since gadgets are fully
 * optimized ResourceLoader modules with possibility to add dependencies etc.)
 *
 * Since Common.js isn't a gadget, there is no place to declare its
 * dependencies, so we have to lazy load them with mw.loader.using on demand and
 * then execute the rest in the callback. In most cases these dependencies will
 * be loaded (or loading) already and the callback will not be delayed. In case a
 * dependency hasn't arrived yet it'll make sure those are loaded before this.
 */

/* global mw, $ */
/* jshint strict:false, browser:true */
//console.log('→ [Common.js] Tag‑Capitalizer стартует');
 
mw.loader.using( [ 'mediawiki.util' ] ).done( function () {
	/* Begin of mw.loader.using callback */

	/**
	 * Map addPortletLink to mw.util
	 * @deprecated: Use mw.util.addPortletLink instead.
	 */
	mw.log.deprecate( window, 'addPortletLink', mw.util.addPortletLink, 'Use mw.util.addPortletLink instead' );

	/**
	 * Test if an element has a certain class
	 * @deprecated:  Use $(element).hasClass() instead.
	 */
	mw.log.deprecate( window, 'hasClass', function ( element, className ) {
		return $( element ).hasClass( className );
	}, 'Use jQuery.hasClass() instead' );

	/**
	 * @source www.mediawiki.org/wiki/Snippets/Load_JS_and_CSS_by_URL
	 * @rev 6
	 */
	var extraCSS = mw.util.getParamValue( 'withCSS' ),
		extraJS = mw.util.getParamValue( 'withJS' );

	if ( extraCSS ) {
		if ( extraCSS.match( /^MediaWiki:[^&<>=%#]*\.css$/ ) ) {
			mw.loader.load( '/w/index.php?title=' + extraCSS + '&action=raw&ctype=text/css', 'text/css' );
		} else {
			mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withCSS value' } );
		}
	}

	if ( extraJS ) {
		if ( extraJS.match( /^MediaWiki:[^&<>=%#]*\.js$/ ) ) {
			mw.loader.load( '/w/index.php?title=' + extraJS + '&action=raw&ctype=text/javascript' );
		} else {
			mw.notify( 'Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withJS value' } );
		}
	}

	/**
	 * WikiMiniAtlas
	 *
	 * Description: WikiMiniAtlas is a popup click and drag world map.
	 *              This script causes all of our coordinate links to display the WikiMiniAtlas popup button.
	 *              The script itself is located on the Meta-Wiki because it is used by many projects.
	 *              See [[Meta:WikiMiniAtlas]] for more information.
	 * Note - use of this service is recommended to be replaced with mw:Help:Extension:Kartographer
	 */
	$( function () {
		var requireWikiminiatlas = $( 'a.external.text[href*="geohack"]' ).length || $( 'div.kmldata' ).length;
		if ( requireWikiminiatlas ) {
			mw.loader.load( '//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript' );
		}
	} );

	/**
	 * Collapsible tables; reimplemented with mw-collapsible
	 * Styling is also in place to avoid FOUC
	 *
	 * Allows tables to be collapsed, showing only the header. See [[Help:Collapsing]].
	 * @version 3.0.0 (2018-05-20)
	 * @source https://www.mediawiki.org/wiki/MediaWiki:Gadget-collapsibleTables.js
	 * @author [[User:R. Koot]]
	 * @author [[User:Krinkle]]
	 * @author [[User:TheDJ]]
	 * @deprecated Since MediaWiki 1.20: Use class="mw-collapsible" instead which
	 * is supported in MediaWiki core. Shimmable since MediaWiki 1.32
	 *
	 * @param {jQuery} $content
	 */
	function makeCollapsibleMwCollapsible( $content ) {
		var $tables = $content
			.find( 'table.collapsible:not(.mw-collapsible)' )
			.addClass( 'mw-collapsible' );

		$.each( $tables, function ( index, table ) {
			// mw.log.warn( 'This page is using the deprecated class collapsible. Please replace it with mw-collapsible.');
			if ( $( table ).hasClass( 'collapsed' ) ) {
				$( table ).addClass( 'mw-collapsed' );
				// mw.log.warn( 'This page is using the deprecated class collapsed. Please replace it with mw-collapsed.');
			}
		} );
		if ( $tables.length > 0 ) {
			mw.loader.using( 'jquery.makeCollapsible' ).then( function () {
				$tables.makeCollapsible();
			} );
		}
	}
	mw.hook( 'wikipage.content' ).add( makeCollapsibleMwCollapsible );

	/**
	 * Add support to mw-collapsible for autocollapse, innercollapse and outercollapse
	 *
	 * Maintainers: TheDJ
	 */
	function mwCollapsibleSetup( $collapsibleContent ) {
		var $element,
			$toggle,
			autoCollapseThreshold = 2;
		$.each( $collapsibleContent, function ( index, element ) {
			$element = $( element );
			if ( $element.hasClass( 'collapsible' ) ) {
				$element.find( 'tr:first > th:first' ).prepend( $element.find( 'tr:first > * > .mw-collapsible-toggle' ) );
			}
			if ( $collapsibleContent.length >= autoCollapseThreshold && $element.hasClass( 'autocollapse' ) ) {
				$element.data( 'mw-collapsible' ).collapse();
			} else if ( $element.hasClass( 'innercollapse' ) ) {
				if ( $element.parents( '.outercollapse' ).length > 0 ) {
					$element.data( 'mw-collapsible' ).collapse();
				}
			}
			// because of colored backgrounds, style the link in the text color
			// to ensure accessible contrast
			$toggle = $element.find( '.mw-collapsible-toggle' );
			if ( $toggle.length ) {
				// Make the toggle inherit text color
				if ( $toggle.parent()[ 0 ].style.color ) {
					$toggle.find( 'a' ).css( 'color', 'inherit' );
				}
			}
		} );
	}

	mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );

/* Попытка изменить межстрочное расстояние при печати poem 
window.onbeforeprint = function() {
  var poems = document.querySelectorAll('.poem');
  poems.forEach(function(poem) {
    poem.style.lineHeight = '0.6';
  });
}
*/

/* Добавление обработки - при сохранении формы заменять первые буквы в значениях Tag на прописные */
/*
$(document).ready(function() {
    // Обработка поля с тегами в реальном времени
    $(document).on('select2:select select2:unselect', 'select[name="Song[Tag][]"]', function(e) {
        const $select = $(this);
        const tags = $select.val() || [];
        
        const formattedTags = tags.map(tag => {
            const trimmed = tag.trim();
            if (trimmed.length === 0) return '';
            return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
        });
        
        // Обновляем значения без перезагрузки виджета
        $select.val(formattedTags).trigger('change');
    });

    // Финишное форматирование перед отправкой
    $('#pfForm').on('submit', function(e) {
        const $select = $('select[name="Song[Tag][]"]');
        const tags = $select.val() || [];
        
        const formattedTags = tags.map(tag => {
            const trimmed = tag.trim();
            if (trimmed.length === 0) return '';
            return trimmed.charAt(0).toUpperCase() + trimmed.slice(1);
        });
        
        $select.val(formattedTags);
    });
});
*/

/* Оно же - другой вариант
$(document).ready(function() {
    function processTag(tag) {
        return tag.replace(/^([а-я])/, function(match) {
            return match.toUpperCase();
        });
    }

    function handleInput(event) {
        const $input = $(this);
        const cursorPos = $input.prop('selectionStart');
        const originalValue = $input.val();
        
        const newValue = originalValue.split(',')
            .map(tag => {
                const trimmed = tag.trim();
                return trimmed ? processTag(trimmed) : '';
            })
            .filter(tag => tag !== '')
            .join(', ');

        if (newValue !== originalValue) {
            $input.val(newValue);
            const delta = newValue.length - originalValue.length;
            $input.prop('selectionStart', cursorPos + delta);
            $input.prop('selectionEnd', cursorPos + delta);
        }
    }

    // Для обычных полей
    $('input[name="Tag"]')
        .on('input', handleInput)
        .on('change', handleInput);

    // Для динамических полей (автодополнение)
    $(document).on('mw.widgets.TagMultiselectWidget', '.mw-widgets-tagMultiselectWidget', function(e) {
        $(this).find('input').on('input change', handleInput);
    });
});

*/
/* Add customized buttons for Wikieditor toolbar */
/* Добавление кнопок в Wikieditor toolbar */
/**
// Check if we're editing a page.
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
		$textarea.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			hline: {
				label: 'Ident',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/a/a3/OOjs_UI_icon_indent-ltr.svg',
				action: {
					type: 'encapsulate',
					options: {
						//peri: ':::',
						regex: /^/gm,
        				regexReplace: ":::"//,
						//ownline: true
					}
				}
			}
		}
	} );
	} );
}

// Check if we're editing a page.
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
		$textarea.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			hline: {
				label: 'NoIdent',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/a/a4/OOjs_UI_icon_outdent-ltr.svg',
				action: {
					type: 'encapsulate',
					options: {
						//peri: ':::',
						regex: /^:/gm,
        				regexReplace: ""//,
						//ownline: true
					}
				}
			}
		}
	} );
	} );
}

// Check if we're editing a page.
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$textarea.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Poem',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/2/29/Button_double_angle_quotes_with_ellipsis.png',
				action: {
					type: 'encapsulate',
					options: {
						pre: '<poem>',
						post: '</poem>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
}


// Check if we're editing a page.
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $textarea ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$textarea.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'NoWiki',
				type: 'button',
				icon: 'https://song.bard-radio.ru/resources/src/mediawiki.icon/images/Button_nowiki.png',
				action: {
					type: 'encapsulate',
					options: {
						pre: ' <nowiki>',
						post: '</nowiki>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
}

/* Add customized buttons for Wikieditor toolbar */
/* Добавление кнопок в Wikieditor toolbar для PageForms */
// Check if we're editing a page.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
		$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			hline: {
				label: 'Добавить отступ текста',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/a/a3/OOjs_UI_icon_indent-ltr.svg',
				action: {
					type: 'encapsulate',
					options: {
						//peri: '   ',
						regex: /^/gm,
        				regexReplace: "   "//,
						//ownline: true
					}
				}
			}
		}
	} );
	} );
//}

// Check if we're editing a page.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
		$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			hline: {
				label: 'Убрать отступ текста',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/a/a4/OOjs_UI_icon_outdent-ltr.svg',
				action: {
					type: 'encapsulate',
					options: {
						//peri: ':::',
						regex: /^:*/gm,
        				regexReplace: ""//,
						//ownline: true
					}
				}
			}
		}
	} );
	} );
//}

// Check if we're editing a page.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Вставить тэг Poem для текста песни',
				type: 'button',
				icon: 'https://bard-wiki.net/images/6/66/Button_Poem2.png',
				action: {
					type: 'encapsulate',
					options: {
						pre: '<poem>',
						post: '</poem>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
//}

// Check if we're editing a page.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Вставить тэг Poem 1 столбец для текста песни',
				type: 'button',
				icon: 'https://bard-wiki.net/images/8/84/Button_Poem_1st.png',
				action: {
					type: 'encapsulate',
					options: {
						pre: '<poem c=1>',
						post: '</poem>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
//}
// Для аккордов.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Вставить тэг для текста с аккордами',
				type: 'button',
				icon: 'https://bard-wiki.net/images/f/ff/Button_accord.png',
				action: {
					type: 'encapsulate',
					options: {
						pre: '===Аккорды===\n<poem c=1>\n',
						post: '</poem>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
//}

// Убираем переводы строк.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Убрать лишние переводы строки',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/f/f3/Button_brrm.png',
				action: {
					type: 'encapsulate',
					options: {
						regex: /(\n{3})/gm,
        				regexReplace: "\n\n",
					}
				}
			}
		}
	} );

	} );
//}
//
//
/*
//Добавление кнопки для исправления автора
mw.hook('wikiEditor.toolbarReady').add(function($toolbar) {
  $toolbar.wikiEditor('addToToolbar', {
    section: 'advanced',
    group: 'format',
    tools: {
      updatePersona: {
        label: 'Обновить Persona',
        type: 'button',
        icon: 'https://commons.wikimedia.org/wiki/File:Vector_toolbar_big_text_button.png',
        action: {
          type: 'callback',
          execute: function(context) {
            var wikiText = context.$textarea.val();
            if (wikiText.indexOf('{{Persona') === -1) {
              return;
            }

            var updatedWikiText = wikiText.replace(/\|Name=([^|\n]*)/, function(match, p1) {
              return '|Name=' + p1.trim().replace(/_/g, ' ');
            });

            updatedWikiText = updatedWikiText.replace(/\|FullName=([^|\n]*)/, function(match, p1) {
              var fullNameParts = p1.trim().split(',').map(function(namePart) {
                return namePart.trim().replace(/_/g, ' ');
              });
              return '|FullName=' + fullNameParts.join(', ');
            });

            context.$textarea.val(updatedWikiText);
          }
        }
      }
    }
  });
});
*/
//
//

//
//


//
//
//
//
// Для цитаты.
//if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	// Add a hook handler.
	mw.hook( 'wikiEditor.toolbarReady' ).add( function ( $free_text ) {
		// Configure a new toolbar entry on the given $textarea jQuery object.
			$free_text.wikiEditor( 'addToToolbar', {
		section: 'advanced',
		group: 'format',
		tools: {
			math: {
				label: 'Вставить тэги для цитаты',
				type: 'button',
				icon: 'https://upload.wikimedia.org/wikipedia/commons/1/13/Button-citiranje.PNG',
				action: {
					type: 'encapsulate',
					options: {
						pre: '<blockquote>',
						post: '</blockquote>',
						ownline: true
					}
				}
			}
		}
	} );

	} );
//}
	/**
	 * Magic editintros ****************************************************
	 *
	 * Description: Adds editintros on disambiguation pages and BLP pages.
	 * Maintainers: [[User:RockMFR]]
	 *
	 * @param {string} name
	 */
	function addEditIntro( name ) {
		$( '.mw-editsection, #ca-edit, #ca-ve-edit' ).find( 'a' ).each( function ( i, el ) {
			el.href = $( this ).attr( 'href' ) + '&editintro=' + name;
		} );
	}

	if ( mw.config.get( 'wgNamespaceNumber' ) === 0 ) {
		$( function () {
			if ( document.getElementById( 'disambigbox' ) ) {
				addEditIntro( 'Template:Disambig_editintro' );
			}
		} );

		$( function () {
			var cats = mw.config.get( 'wgCategories' );
			if ( !cats ) {
				return;
			}
			if ( $.inArray( 'Living people', cats ) !== -1 || $.inArray( 'Possibly living people', cats ) !== -1 ) {
				addEditIntro( 'Template:BLP_editintro' );
			}
		} );
	}
	/* End of mw.loader.using callback */


$(document).ready(function() {
  $('div.poem p').each(function() {
    var text = $(this).html();
    // Заменяем двойные переводы строк на уникальный маркер
    var markedText = text.replace(/\n\s*\n/g, '<doublebr>\n');
    // Разделяем текст на строки
    var lines = markedText.split('\n');
    // Перекрашивание строки, начинающейся с запятой в синий цвет
    for (var i = 0; i < lines.length; i++) {
      if (lines[i].trim().startsWith(',')) {
        lines[i] = '<span style="color:Blue">' + lines[i].trim().replace(',', ' ') + '</span>';
      }
    }
    // Объединяем строки обратно в текст, заменяя переводы строк на '<br>'
    var html = lines.join('<br>');
    // Заменяем уникальный маркер обратно на '<br>'
    html = html.replace(/<doublebr>/g, '<br>');
    $(this).html(html);
  });
});
	
} );

//Код для вставления на форму панели edittools

mw.loader.using(['ext.pageforms.main', 'mediawiki.util'], function() {
    $(document).ready(function() {
        // Проверяем, что мы на странице редактирования формы
        if ($('form[name="createbox"]').length > 0 || $('.pfForm').length > 0) {
            
            // Получаем содержимое EditTools из MediaWiki
            var api = new mw.Api();
            
            api.get({
                action: 'parse',
                page: 'MediaWiki:Edittools',
                prop: 'text',
                disablelimitreport: true
            }).done(function(data) {
                if (data.parse && data.parse.text && data.parse.text['*']) {
                    var edittoolsHtml = data.parse.text['*'];
                    
                    // Создаём контейнер для EditTools
                    var edittoolsContainer = $('<div id="edittools-container"></div>').css({
                        'margin-top': '20px',
                        'padding': '10px',
                        'border-top': '1px solid #a2a9b1',
                        'background': '#f8f9fa'
                    });
                    
                    // Вставляем HTML EditTools
                    edittoolsContainer.html(edittoolsHtml);
                    
                    // Функция для поиска правильного поля ввода
                    function findTargetField() {
                        // Сначала ищем поле в фокусе, но исключаем служебные поля
                        var focusedField = $('input:focus, textarea:focus').filter(function() {
                            var $this = $(this);
                            var name = $this.attr('name') || '';
                            var id = $this.attr('id') || '';
                            
                            // Исключаем служебные поля MediaWiki
                            return !name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                   !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                   !$this.hasClass('mw-summary');
                        });
                        
                        if (focusedField.length > 0) {
                            return focusedField.first();
                        }
                        
                        // Если нет поля в фокусе, ищем поля формы (исключая служебные)
                        var formFields = $('form[name="createbox"] input[type="text"], form[name="createbox"] textarea, .pfForm input[type="text"], .pfForm textarea').filter(function() {
                            var $this = $(this);
                            var name = $this.attr('name') || '';
                            var id = $this.attr('id') || '';
                            
                            // Исключаем служебные поля
                            return !name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                   !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                                   !$this.hasClass('mw-summary') &&
                                   $this.is(':visible');
                        });
                        
                        // Возвращаем последнее использованное поле или первое доступное
                        if (window.lastUsedField && window.lastUsedField.length > 0 && $.contains(document, window.lastUsedField[0])) {
                            return window.lastUsedField;
                        }
                        
                        return formFields.first();
                    }
                    
                    // Отслеживаем последнее использованное поле
                    $(document).on('focus', 'input, textarea', function() {
                        var $this = $(this);
                        var name = $this.attr('name') || '';
                        var id = $this.attr('id') || '';
                        
                        // Сохраняем только поля формы, не служебные
                        if (!name.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                            !id.match(/^(wpSummary|wpEditToken|wpUnicodeCheck|wpWatchthis|wpMinoredit)$/) &&
                            !$this.hasClass('mw-summary')) {
                            window.lastUsedField = $this;
                        }
                    });
                    
                    // Обрабатываем все ссылки в EditTools для вставки символов
                    edittoolsContainer.find('a').each(function() {
                        var $link = $(this);
                        var originalHref = $link.attr('href');
                        
                        // Если это ссылка на вставку символа (javascript:insertTags)
                        if (originalHref && originalHref.indexOf('javascript:insertTags') === 0) {
                            $link.click(function(e) {
                                e.preventDefault();
                                
                                // Извлекаем символ из href
                                var match = originalHref.match(/insertTags\('([^']*)',\s*'([^']*)',\s*'([^']*)'\)/);
                                if (match) {
                                    var prefix = match[1] || '';
                                    var suffix = match[2] || '';
                                    var symbol = match[3] || '';
                                    
                                    var textToInsert = prefix + symbol + suffix;
                                    
                                    var activeField = findTargetField();
                                    
                                    if (activeField.length > 0) {
                                        // Вставляем текст
                                        var currentValue = activeField.val();
                                        var cursorPos = activeField[0].selectionStart || currentValue.length;
                                        var newValue = currentValue.substring(0, cursorPos) + textToInsert + currentValue.substring(cursorPos);
                                        activeField.val(newValue);
                                        
                                        // Возвращаем фокус
                                        activeField.focus();
                                        if (activeField[0].setSelectionRange) {
                                            activeField[0].setSelectionRange(cursorPos + textToInsert.length, cursorPos + textToInsert.length);
                                        }
                                        
                                        // Сохраняем как последнее использованное поле
                                        window.lastUsedField = activeField;
                                    }
                                }
                                
                                return false;
                            });
                        }
                        // Если это обычная ссылка с текстом для вставки
                        else if ($link.text().trim().length > 0 && !originalHref) {
                            $link.click(function(e) {
                                e.preventDefault();
                                
                                var symbol = $(this).text();
                                
                                var activeField = findTargetField();
                                
                                if (activeField.length > 0) {
                                    var currentValue = activeField.val();
                                    var cursorPos = activeField.length > 0 && activeField[0].selectionStart !== undefined ? activeField[0].selectionStart : currentValue.length;
                                    var newValue = currentValue.substring(0, cursorPos) + symbol + currentValue.substring(cursorPos);
                                    activeField.val(newValue);
                                    
                                    activeField.focus();
                                    if (activeField[0].setSelectionRange) {
                                        activeField[0].setSelectionRange(cursorPos + symbol.length, cursorPos + symbol.length);
                                    }
                                    
                                    // Сохраняем как последнее использованное поле
                                    window.lastUsedField = activeField;
                                }
                                
                                return false;
                            });
                        }
                    });
                    
                    // Размещаем панель внизу формы
                    var form = $('form[name="createbox"], .pfForm').first();
                    if (form.length > 0) {
                        form.after(edittoolsContainer);
                    }
                }
            }).fail(function() {
                console.error('Не удалось загрузить EditTools');
            });
        }
    });
}).fail(function() {
    console.error('Не удалось загрузить модули для EditTools');
});

// Показываем дополнительные вкладки только на Главной
mw.loader.using( 'mediawiki.util', function () {

    // Проверяем, главная ли сейчас страница
    if ( mw.config.get( 'wgIsMainPage' ) ) {

        // «Предложения»
        mw.util.addPortletLink(
            'p-namespaces',
            mw.util.getUrl( 'Project:Предложения' ),
            'Предложения',
            'ca-proposals',
            'Предложения к содержимому Главной'
        );

        // «Заявки»
        mw.util.addPortletLink(
            'p-namespaces',
            mw.util.getUrl( 'Project:Заявки' ),
            'Заявки',
            'ca-requests',
            'Заявки на изменение Главной'
        );
    }
});

mw.hook('wikipage.content').add(function ($content) {

  $content.on('click', '#votebox.vote-clickable', function (e) {
    e.preventDefault();
    e.stopPropagation();

    var link = document.querySelector('.vote-vote-link');
    if (!link) {
      return;
    }

    link.dispatchEvent(
      new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        view: window
      })
    );
  });

});




/* DO NOT ADD CODE BELOW THIS LINE */