User:Mikevoir/betterCodeMirror.js

mw.loader.using('mediawiki.api').then(function {	var lib = this._LIB;	var settings = this.betterCodeMirror || {};	var $textbox = $( '#wpTextbox1' );	var betterCodeMirror = {		config: mw.config.get(['wgAction']),		row: document.querySelector('.group-insert'),		init: function {			if (this.config.wgAction && ['edit', 'submit'].includes(this.config.wgAction)) {				if (!settings.disable || !Array.isArray(settings.disable) || !settings.disable.includes('quickOL'))				{lib.waitFor('.CodeMirror', this.quickOL);}				if (!settings.disable || !Array.isArray(settings.disable) || !settings.disable.includes('templateDataShow'))				{lib.waitFor('.CodeMirror', this.templateDataShow);}			}		},		addButton: function(query, content, handler) {			var addTo = document.querySelector(query);			if (addTo) {				var container = document.createElement('span');				container.classList.add('tool', 'oo-ui-widget', 'oo-ui-widget-enabled', 'oo-ui-buttonElement', 'oo-ui-buttonElement-frameless', 'oo-ui-iconElement', 'oo-ui-buttonWidget'); var button = document.createElement('a'); button.classList.add('oo-ui-buttonElement-button'); button.innerHTML = content; button.role = 'button'; button.addEventListener('mouseup', handler); container.appendChild(button); addTo.insertBefore(container, addTo.children[0]); }		},		quickOL: function { // Add buttons betterCodeMirror.addButton('.group-insert', 'OL_tl', addOL); betterCodeMirror.addButton('.group-insert', 'OL', addOL); // Add call when clicked function addOL(event) { // OL call without TL params if (event.target.innerHTML == 'OL'){ $textbox.textSelection(						'replaceSelection',						''); // OL call with TL params }else if (event.target.innerHTML == 'OL_tl'){ $textbox.textSelection(						'replaceSelection',						''); }			}		},		templateDataShow: function { var $textbox = $textbox || $( '#wpTextbox1' ); var api = api || new mw.Api; var loadedPage; // Load VE-only styling importArticles({			   type: 'css',			    articles: ['u:community:User:Mikevoir/betterCodeMirror.css']			});

var TDSmethods = { init: function(event) { console.log(loadedPage); $textbox = $( '#wpTextbox1' ); var checkTemplate = /^[\s\S]*\{\{([^\}\{\|]+)(\|$|\}\}$|$)?$/g; var checkParam = /^[\s\S]+\|(\s*[\w\d_\-\s]+\s*)$/g; var currCaret = $textbox.textSelection('getCaretPosition'); console.log('currCaret', currCaret); var uptoCaret = $textbox.textSelection('getContents').substring(0, currCaret); console.log('uptoCaret', uptoCaret.length); if (uptoCaret && checkTemplate.test(uptoCaret)) { var template = uptoCaret.replace(checkTemplate, '$1'); if (!loadedPage || loadedPage.TEMPLATE !== template){ this.getTD(template, this.renderTD); } else { this.renderTD(loadedPage); }					} else if (uptoCaret && loadedPage && checkParam.test(uptoCaret)) { var raw_str = uptoCaret.replace(checkParam, '$1'); var param = raw_str.trim; // Sort possible fillups var selection = { paramOrder: [], params: {}, format: loadedPage.format, TEMPLATE: loadedPage.TEMPLATE, description: loadedPage.description };						loadedPage.paramOrder.forEach(function(paramName){							if (paramName.indexOf(param) == 0 ) {								selection.paramOrder.push(paramName);								selection.params[paramName] = loadedPage.params[paramName];							} else if (loadedPage.params[paramName].aliases && loadedPage.params[paramName].aliases.length>0) {								loadedPage.params[paramName].aliases.forEach(function(alias){ if (!selection.params[paramName] && alias.indexOf(param)) { selection.paramOrder.push(paramName); selection.params[paramName] = loadedPage.params[paramName]; }								});							}						});						if (selection.paramOrder.length > 0) { this.proofTD(selection, this.renderTD); }						var paramSelect = function(event){ $textbox = $( '#wpTextbox1' ); if (event.target.closest('code') || event.target.nodeName == 'code'){ var selectedParam = event.target.nodeValue || event.target.innerHTML; var spacing = ' = '; var formatRegex = /\{\{/; if (loadedPage.format && loadedPage.format !== 'inline') { var touse = loadedPage.format.replace(/^.*?\|(_+) =.+$/, '$1'); if (touse.length > selectedParam.length) { spacing = ' '.repeat(touse.length-selectedParam.length) + ' = '; }								}								console.log('currCaret', currCaret); console.log('raw_str.length', raw_str.length); document.querySelector('.ve-ui-mwVerticalLayout').removeEventListener('mouseup', paramSelect); document.querySelector('.ve-ui-overlay-global.ve-ui-overlay-global-desktop.ve-ui-overlay').remove; $textbox.textSelection('setSelection', {0:(currCaret-raw_str.length), 1:currCaret}); console.log($textbox.textSelection('getSelection')); $textbox.textSelection('replaceSelection', selectedParam); //+ spacing);							}						};						document.addEventListener('mouseup', paramSelect);					}				},				getTD: function(template, callBack) {					var tdRegex = / ([\s\S]+)<\/templatedata>/g;					api.get({ action: 'parse', page: 'Template:'+template+'/doc', prop: 'wikitext|categories|sections' }).then(function(data){ if (							data &&							data.parse &&							data.parse.wikitext &&							data.parse.wikitext['*'] &&							tdRegex.test(data.parse.wikitext['*'])						){ var raw_templateData = data.parse.wikitext['*'].match(tdRegex)[0].replace(' ', ).replace(' ', ); var templateData = JSON.parse(raw_templateData); templateData.TEMPLATE = template; TDSmethods.proofTD(templateData, callBack); }					});				},				proofTD: function(data, callBack) {					if (!data.paramOrder && data.params) {						data.paramOrder = [];						Object.keys(data.params).forEach(function(key) { data.paramOrder.push(key); });					}					if (!data.format) {data.format='inline';}					callBack(data);				},				renderTD: function(data) {					loadedPage = data;					var frame = TDSmethods.nestElements(document.querySelector('body'), [							{								classNames: [ "ve-ui-overlay-global", "ve-ui-overlay-global-desktop", "ve-ui-overlay" ] },							{								classNames: [ "oo-ui-windowManager", "oo-ui-windowManager-modal", "ve-ui-dir-block-ltr", "oo-ui-windowManager-floating" ], attributes: { role: 'dialog' }							},							{								classNames: [ "oo-ui-window", "oo-ui-dialog", "oo-ui-processDialog", "ve-ui-mwTemplateDialog-ready", "ve-ui-mwTransclusionDialog-single-transclusion", "oo-ui-window-active", "oo-ui-window-setup", "oo-ui-window-ready" ], attributes: { role: 'dialog' }							},							{								classNames: ['oo-ui-window-frame'], styles: { width: '900px', height: '90%' }							},						]					);					//Starting trap					TDSmethods.addElement({ addTo: frame, classNames: ['oo-ui-window-focusTrap'], attributes: {tabindex: '0'}, noreturn: true });					var main = TDSmethods.addElement({ addTo: frame, classNames: [ 'oo-ui-window-content', 'oo-ui-dialog-content', 'oo-ui-processDialog-content', 'oo-ui-window-content-setup', 'oo-ui-window-content-ready' ], attributes: {tabindex: '-1'} });					//Ending trap					TDSmethods.addElement({ addTo: frame, classNames: ['oo-ui-window-focusTrap'], attributes: {tabindex: '0'}, noreturn: true });					// Head container					var head =					TDSmethods.nestElements(main, [							{ classNames: [ 'oo-ui-window-head' ] }, { classNames: [ 'oo-ui-processDialog-navigation' ] } ]					);					// Head 1					TDSmethods.nestElements(head, [							{ 								classNames: [ 'oo-ui-processDialog-location' ], styles: { 'padding-left': '77.7167px', 'padding-right': '77.7167px' }							},							{								node: 'label', classNames: [ 'oo-ui-widget', 'oo-ui-widget-enabled', 'oo-ui-labelElement-label', 'oo-ui-labelWidget', 'oo-ui-processDialog-title', 'oo-ui-labelElement' ], content: 'Template Data: ' + data.TEMPLATE }						]					);					// Head 2					var head2 = 					TDSmethods.nestElements( head, [							{ classNames: [ 'oo-ui-processDialog-actions-safe' ] }, {								node: 'span', classNames: [ 'oo-ui-widget', 'oo-ui-widget-enabled', 'oo-ui-buttonElement', 'oo-ui-buttonElement-framed', 'oo-ui-iconElement', 'oo-ui-flaggedElement-safe', 'oo-ui-flaggedElement-close', 'oo-ui-buttonWidget', 'oo-ui-actionWidget' ] },							{								node: 'a', classNames: [ 'oo-ui-buttonElement-button' ], attributes: { role: 'button', tabindex: '0', rel: 'nofollow' }							}						]					);					TDSmethods.addElement({ addTo: head2, node: 'span', classNames: [ 'oo-ui-iconElement-icon', 'oo-ui-icon-close' ], noreturn: true });					TDSmethods.addElement({ addTo: head2, node: 'span', classNames: [ 'oo-ui-labelElement-label', 'oo-ui-labelElement-invisible' ], content: 'Cancel', noreturn: true });					TDSmethods.addElement({ addTo: head2, node: 'span', classNames: [ 'oo-ui-indicatorElement-indicator', 'oo-ui-indicatorElement-noIndicator' ], noreturn: true });					// Window body					var body = TDSmethods.nestElements( main, [							{ classNames: [ 'oo-ui-window-body' ], styles: { bottom: '52px' } }, { classNames: [ 'oo-ui-layout', 'oo-ui-menuLayout', 'oo-ui-menuLayout-before', 'oo-ui-menuLayout-showMenu', 've-ui-mwTwoPaneTransclusionDialogLayout' ] }, { classNames: [ 'oo-ui-menuLayout-content' ] }, { classNames: [ 'oo-ui-layout', 'oo-ui-panelLayout', 'oo-ui-panelLayout-scrollable', 'oo-ui-panelLayout-expanded', 've-ui-mwVerticalLayout', 've-ui-mwTwoPaneTransclusionDialogLayout-stackLayout' ] } ]					);					// Body title					var body_title = TDSmethods.nestElements( body, [							{ classNames: [ 'oo-ui-layout', 'oo-ui-panelLayout', 'oo-ui-panelLayout-expanded', 'oo-ui-pageLayout', 've-ui-mwTemplatePage' ] }, { 								classNames: [ 'oo-ui-layout', 'oo-ui-iconElement', 'oo-ui-labelElement', 'oo-ui-fieldsetLayout' ], node: 'fieldset', content: TDSmethods.listElements(									null,									[										{ 											classNames: [ 'oo-ui-layout', 'oo-ui-iconElement', 'oo-ui-labelElement', 'oo-ui-fieldsetLayout' ],											node: 'legend',											content: TDSmethods.listElements(null, [ { classNames: [ 'oo-ui-iconElement-icon', 'oo-ui-icon-puzzle' ], node: 'span' }, { classNames: [ 'oo-ui-labelElement-label' ], node: 'span', content: data.TEMPLATE }, ])										},										{ 											classNames: [ 'oo-ui-fieldsetLayout-group' ],											content: data.description || 'No template description.'										},										{ 											classNames: [ 've-ui-mwTemplatePage-description' ],											content: 'Format: ' + (data.format.replace(/\\/, '\\') || 'inline')										},									]								) },						]					);					data.paramOrder.forEach(function(param){ TDSmethods.addElement({							addTo: body,							classNames: [ 'oo-ui-layout', 'oo-ui-panelLayout', 'oo-ui-panelLayout-expanded', 'oo-ui-pageLayout', 've-ui-mwParameterPage' ],							content: TDSmethods.parseParam(data.params[param], param)						}); });					// Close popup					var listenTo = ['mouseup', 'keyup'];					var closePopup = function(event) {						if ( (								event.target.closest('.oo-ui-processDialog-navigation a.oo-ui-buttonElement-button') &&								(event.type == 'mouseup')							)|| (								event.type == 'keyup' &&								event.key == 'Escape'							) ){							// Close popup and remove listeners							document.querySelector('.ve-ui-overlay-global.ve-ui-overlay-global-desktop.ve-ui-overlay').remove;							listenTo.forEach(function(type){document.removeEventListener(type, closePopup);});						}					};					listenTo.forEach(function(type){document.addEventListener(type, closePopup);});				},				addElement: function(options) {					if (!options.node){options.node = 'div';}					var newNode;					if (options.node !== 'text') {						newNode = document.createElement(options.node);						if (options.classNames) {							options.classNames.forEach(function(className){ if ('string' == typeof className && className.length > 0) { newNode.classList.add(className); }							});						}						if (options.styles) {							Object.keys(options.styles).forEach(function(key) { newNode.style[key] = options.styles[key]; });						}						if (options.attributes) {							Object.keys(options.attributes).forEach(function(key) { newNode.setAttribute(key, options.attributes[key]); });						}						if (Array.isArray(options.content) && options.content.length>0) {							options.content.forEach(function(content){ if ('string' == typeof content) { newNode.appendChild(document.createTextNode(content)); }else if ('object' == typeof content && content.ownerDocument) { newNode.appendChild(content); }							});						} else if ('string' == typeof options.content) {							newNode.appendChild(document.createTextNode(options.content));						}else if ('object' == typeof options.content && options.content.ownerDocument) {							newNode.appendChild(options.content);						}					} else { newNode = document.createTextNode(options.content); }					if (options.addTo) {						options.addTo.appendChild(newNode);					}					if (!options.noreturn) {						return newNode;					}				},				nestElements: function(startNode, optionsArray) {					var oldNode = startNode;					optionsArray.forEach(function(options){ options.addTo = oldNode; oldNode = TDSmethods.addElement(options); });					return oldNode;				},				listElements: function(parentNode, optionsArray) {					var newNodes = [];					optionsArray.forEach(function(options){ if (parentNode) {options.addTo = parentNode;} var newNode = TDSmethods.addElement(options); if (!parentNode && newNode) {newNodes.push(newNode);} });					return parentNode || newNodes;				},				parseParam: function(data, param) {					var param_names = [{ content: param, node: 'code', classNames: ['ve-ui-mwParameterPage-param'] }];					var param_desc = [];					var hr = false;					if (data.aliases && data.aliases.length>0) {						data.aliases.forEach(function(alias){ param_names.push({								content: alias,								node: 'code',								classNames: ['ve-ui-mwParameterPage-param']							}); });					}					if (data.description) {						if (!hr){param_desc.push({node: 'hr'}); hr=true;}						param_desc.push({ content: data.description, node: 'p'						});					}					if (data.default) {						if (!hr){param_desc.push({node: 'hr'}); hr=true;}						param_desc.push({ content: 'Default: ' + data.default, classNames: ['ve-ui-mwParameterPage-doc-default'], node: 'p'						});}					if (data.example) {						if (!hr){param_desc.push({node: 'hr'}); hr=true;}						param_desc.push({ content: 'Example: ' + data.example, classNames: ['ve-ui-mwParameterPage-doc-example'], node: 'p'						});					}					return TDSmethods.listElements(null, [							{								classNames: [ 've-ui-mwParameterPage-info' ], content: TDSmethods.addElement({									classNames: [ 've-ui-mwParameterPage-label', 'oo-ui-widget', 'oo-ui-widget-enabled', 'oo-ui-labelElement', 'oo-ui-labelElement-label', 'oo-ui-labelWidget' ],									node: 'label',									content: data.label || param								}) },							{								classNames: [ 've-ui-mwParameterPage-param' ], content: TDSmethods.listElements(null,param_names) },							{								classNames: [ 've-ui-mwParameterPage-inlineDescription' ], content: TDSmethods.listElements(null,param_desc) },						]					);				}			};			document.querySelector('.CodeMirror-code').addEventListener('dblclick', function(event){ // Run on: left click when (alt key + ctrl + shift) if ((event.button == 0) && event.altKey){ event.preventDefault; TDSmethods.init(event); }			});		},	};

betterCodeMirror.init; });