Участник:Serhio Magpie/enhanceWikitextEditor.js

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
/**
 * Enhance Wikitext Editor
 * 
 * Author: Serhio Magpie
 * Licenses: MIT, CC BY-SA
 */

// <nowiki>

$( function () {
	var _config = {
			contentModel: mw.config.get( 'wgPageContentModel' ),
			codeEditorLanguage:  mw.config.get( 'wgCodeEditorCurrentLanguage' )
		},
		_nodes = {},
		_editOptionsHeight = 0,
		_css;
	
	if ( !window.EnhanceWikitextEditor ) {
		window.EnhanceWikitextEditor = {};
	}
	
	EnhanceWikitextEditor.default = {
		name: 'EnhanceWikitextEditor',
		allow: [ 'wikitext' ],
		toggleEditOptions: true
	};
	EnhanceWikitextEditor.config = $.extend( {}, EnhanceWikitextEditor.default, EnhanceWikitextEditor.config || {} );

	function getNodes() {
		_nodes.$textbox = $( '#wpTextbox1' );
		_nodes.$toolbar = $( '#wikiEditor-ui-toolbar' );
		_nodes.$toolbarMain = $( '#wikiEditor-section-main' );
		_nodes.$wpPreviewLive = $( '#wpPreviewLive' );
		_nodes.$wpDiffLive = $( '#wpDiffLive' );
		_nodes.$editOptions = $( '#editform .editOptions' );
		_nodes.$summary = $( '#wpSummary' );
		_nodes.$sandboxPage = $( '#wpTemplateSandboxPage .oo-ui-inputWidget-input' );
		// Code Mirror
		_nodes.$codeMirrorButton = $( '#mw-editbutton-codemirror .oo-ui-buttonElement-button' );
		// Ace Editor
		_nodes.$aceEditorButton = $( '#editform .wikiEditor-ui-toolbar .group-codeeditor-main .oo-ui-toggleButtonWidget .oo-ui-buttonElement-button' );
	}

	function resizeTextbox() {
		// Кнопки переключения режимов редактора
		_nodes.$codeMirrorButton.on( 'click', resizeTextboxHandler );
		_nodes.$aceEditorButton.on( 'click', resizeTextboxHandler );
		// Масштабировать textarea при вводе текста
		_nodes.$textbox.on( 'keyup', resizeTextboxHandler );
		// Масштабировать textarea или редактор
		resizeTextboxHandler();
	}

	function resizeTextboxHandler() {
		let top = $( window ).scrollTop();
		_nodes.$textbox.css( 'height', 'auto' );
		_nodes.$textbox.css( 'height', _nodes.$textbox.prop( 'scrollHeight' ) + 'px' );
		setEditor();
		$( window ).scrollTop( top );
	}
	
	function setEditOptions() {
		if ( !EnhanceWikitextEditor.config.toggleEditOptions ) {
			return;
		}
		_nodes.$editOptions.addClass( 'enhanceWikitextEditor--editOptions' );
		_nodes.$editOptions.on( 'mouseenter', setEditOptionsHeight );
		_nodes.$summary.on( 'focus', showEditOptions );
		_nodes.$summary.on( 'blur', hideEditOptions );
		_nodes.$sandboxPage.on( 'focus', showEditOptions );
		_nodes.$sandboxPage.on( 'blur', hideEditOptions );
	}

	function showEditOptions() {
		setEditOptionsHeight();
		_nodes.$editOptions.addClass( 'visible' );
	}
	
	function setEditOptionsHeight() {
		if ( _css && _css.cssRules[0] && _css.cssRules[0].selectorText === ':root' ) {
			var height = (
				_nodes.$editOptions.prop( 'scrollHeight' ) -
				_nodes.$editOptions.outerHeight() +
				_nodes.$editOptions.height()
			);
			if ( height !== _editOptionsHeight ) {
				_editOptionsHeight = height;
				_css.cssRules[0].style.setProperty( '--enhanceWikitextEditor--editOptions-visible-height', height + 'px' );
			}
		}
	}

	function hideEditOptions() {
		_nodes.$editOptions.removeClass( 'visible' );
	}
	
	function setCodeMirror() {
		if ( typeof CodeMirror !== 'undefined' ) {
			CodeMirror.defaults.viewportMargin = Infinity;
		}
	}
	
	function setAceEditor() {
		if ( typeof ace !== 'undefined' ) {
			_nodes.$ace = $( '#editform .ace_editor' );
			var editor = ace.edit( _nodes.$ace.get( 0 ) );
			editor.setOptions( { maxLines: Infinity } );
		}
	}
	
	function setEditor() {
		setCodeMirror();
		setAceEditor();
	}

	function init() {
		_css = mw.util.addCSS( '\
			:root { --enhanceWikitextEditor--editOptions-hidden-height:12px; --enhanceWikitextEditor--editOptions-visible-height:300px; }\
			\
			.wikiEditor-ui .wikiEditor-ui-top { position:-webkit-sticky; position:sticky; top:0; z-index:20; }\
			.wikiEditor-ui .wikiEditor-ui-text { height:auto !important; }\
			.wikiEditor-ui .wikiEditor-ui-text .ui-resizable { height:auto !important; }\
			.wikiEditor-ui .wikiEditor-ui-text .ace_editor { min-height:475px; position:relative !important; }\
			.wikiEditor-ui .wikiEditor-ui-text .ace_search { position:fixed; top:auto; bottom:70px; border:1px solid #cbcbcb; border-radius:0; }\
			.wikiEditor-ui .wikiEditor-ui-text .ace_search.right { right:24px; }\
			.wikiEditor-ui .wikiEditor-ui-view .codeEditor-status { position:sticky; bottom:48px; z-index:4; }\
			.wikiEditor-toolbar-dialog { position:fixed !important; }\
			\
			.enhanceWikitextEditor--editOptions { height:var(--enhanceWikitextEditor--editOptions-hidden-height); position:-webkit-sticky; position:sticky; bottom:0; z-index:19; overflow:hidden; border-top:1px solid #c8ccd1; transition:height 250ms ease-in-out 100ms; }\
			.enhanceWikitextEditor--editOptions:hover,\
			.enhanceWikitextEditor--editOptions:active,\
			.enhanceWikitextEditor--editOptions:focus-within,\
			.enhanceWikitextEditor--editOptions.visible { height:var(--enhanceWikitextEditor--editOptions-visible-height); }\
			.enhanceWikitextEditor--editOptions #wpSummaryLabel .oo-ui-fieldLayout-header { padding-bottom:1em; }\
			 \
			.mw-editform #wpTextbox1 { max-height:none; overflow:hidden; }\
			.CodeMirror { height:auto !important; }\
			.CodeMirror-scroll { min-height:475px; }\
		' );
		getNodes();
		resizeTextbox();
		setEditOptions();
	}

	// CodeMirror
	if(
		EnhanceWikitextEditor.config.allow.includes( _config.contentModel ) &&
		![ 'error', 'missing' ].includes( mw.loader.getState( 'ext.CodeMirror' ) )
	) {
		init();
		mw.loader.using( [ 'ext.wikiEditor' ] ).then( setEditor );
		return;
	}
	
	// Ace Editor
	if (
		_config.codeEditorLanguage &&
		![ 'error', 'missing' ].includes( mw.loader.getState( 'ext.codeEditor.ace' ) )
	) {
		init();
		mw.loader.using( [ 'ext.codeEditor', 'ext.codeEditor.ace' ] ).then( setEditor );
		return;
	}

} );

// </nowiki>