User:So9q/new-entry-creator.js

/* // Rewrite of https://en.wiktionary.org/w/index.php?title=User:Yair_rand/newentrywiz.js&oldid=54099266 // by So9q 19/9-2019 /* jshint sub:true, shadow:true, undef:true, unused:true, strict:true, forin:true, latedef:true */ /* global $, mw */ //

"use strict";

function customize { if (typeof window.NEC_default_lang == 'undefined') { // Default is not defined, set to defaults window.NEC_default_lang = "da"; } } function capitalize(s) { if (typeof s !== 'string') return ''; return s.charAt(0).toUpperCase + s.slice(1); }

// Initialize variables // Support prefilling via GET if (mw.util.getParamValue('ct') == 'true') { var pos = mw.util.getParamValue('pos'); var pos_cap = capitalize(pos); var def =  + mw.util.getParamValue('def') + ; var lang = mw.util.getParamValue('lang'); } else { // enable customization customize; var lang = window.NEC_default_lang; var pos, def = ''; } function wikilinkText { var sel; if (window.getSelection) { sel = window.getSelection; var activeElement = document.activeElement; if (activeElement.nodeName == "TEXTAREA" ||          (activeElement.nodeName == "INPUT" && activeElement.type.toLowerCase == "text")) { var val = activeElement.value, start = activeElement.selectionStart, end = activeElement.selectionEnd; activeElement.value = val.slice(0, start) +  + sel +  + val.slice(end); }	} }

function label { var sel; if (window.getSelection) { sel = window.getSelection; var activeElement = document.activeElement; if (activeElement.nodeName == "TEXTAREA" ||          (activeElement.nodeName == "INPUT" && activeElement.type.toLowerCase == "text")) { var val = activeElement.value; activeElement.value = ' ' + val; }	} } function button(value,lang,append) { var sel; if (window.getSelection) { sel = window.getSelection; var activeElement = document.activeElement; if (activeElement.nodeName == "TEXTAREA" ||          (activeElement.nodeName == "INPUT" && activeElement.type.toLowerCase == "text")) { var val = activeElement.value; if (append === (null || undefined)) var append = '|' if (append === false) var append = '' if (lang === false) activeElement.value = val + ' '; else activeElement.value = val + ' '; }	} }

function setup_defs { var max_fields = 10; var wrapper = $(".container1"); var add_button = $(".add_form_field");

var x = 1; $(add_button).click(function(e) {       e.preventDefault;        if (x < max_fields) {            x++;            //add input box            $(wrapper).append($(' ').append(            	$(' ').addClass('def').attr({ type: 'text', //name: def, size: 40 }),				'Delete'));       } else {            alert('You Reached the limits');        }    });

$(wrapper).on("click", ".delete", function(e) {       e.preventDefault;        $(this).parent('div').remove;        x--;    }); } function setup_headings { $('#headings').on('click', '.delete_heading', function(e){				console.info($(this).parent('div'));				e.preventDefault;				$(this).parent('div').remove;		}); } function clean(option) { // Clean spaces and parens return option.replace(/\s/g, ).replace(/\./g, ) .replace(/\(/g, ).replace(/\)/g, ); } function generate { console.info('generate clicked'); var lang = $('#lang').val; // Language heading var markup = "==getByCode==\n\n"; // Etymology if ($('#ety').val !== '') { markup += "===Etymology===\n"; markup += $('#ety').val + "\n\n"; }	else { markup += "===Etymology===\n"; markup += "\n\n"; }	// PoS var pos = $('[name="pos"]:checked').val; if (pos !== '') { markup += "===" + pos + "===\n"; }	else { // this should never happen because we select noun by default mw.notify('Please select a Part of Speech'); return; }	function get_value(option) { // Get the value from either the radio buttons value= field or 		// the input=text coming after the radio button // Clean option var option = clean(option); var val = $('[name="'+option+'infl"]:checked').val; console.info('val: '+val) // Support languages where only prepend and append is set if (val === undefined) return ''; // Get value from radio button else if (val !== 'other') return val; // Get value from input box after radio=other else { return $('.span_other_'+option).find('input[type=text]').val; }	}	// PoS subheading // Common vars var pre = $('[name=prepend]').val; var app = $('[name=append]').val; if ((pre && app) !== undefined) { // PoS if (pos == 'Noun') { var stem = get_value("Stem"); var sd = get_value("Singular definite"); var pl = get_value("Plural"); markup += pre + stem + sd + pl + app + "\n\n"; }		else if (pos == 'Verb') { var im = get_value("Imperative form without particle ending"); // Halt and warn if imperative is not set if (im === '|' || im === 'undefined' || im === undefined){ mw.notify('Imperative is empty, please fix'); return; }			else { var im_pe = get_value("Imperative (particle ending)"); if (im_pe === '|particle=') im_pe = ''; var inf = get_value("Infinitive"); var pr = get_value("Present"); var pa = get_value("Past"); var pp = get_value("Past participle"); // Handle double consonants var dc = $('[name="dc"]:checked').length; // We have 4 cases: // 1. with double consonant and no particle ending defined if (dc == '1' && im_pe === undefined) markup += pre + im + inf + pr + pa + pp + '|dc=1' + app + "\n\n"; // 2. with double consonant and particle ending defined else if (dc == '1' && im_pe !== undefined) markup += pre + im + im_pe + inf + pr + pa + pp + '|dc=1' + app + "\n\n"; // 3. with no double consonant and particle ending defined else if (dc !== '1' && im_pe !== undefined) markup += pre + im + im_pe + inf + pr + pa + pp + app + "\n\n"; // 4. with no double consonant and no particle ending defined else markup += pre + im + inf + pr + pa + pp + app + "\n\n"; }		}		else if (pos == 'Adjective') { var ne = get_value("Neuter"); var pd = get_value("Plural or definite"); var co = get_value("Comparative"); var sp = get_value("Superlative pred"); var sa = get_value("Superlative attr"); markup += pre + ne + pd + co + sp + sa + app + "\n\n"; }		else { markup += pre + app + "\n\n"; }	}	else { mw.notify('No template or inflection data found. Defaulting to '); markup += "\n\n"; }	// Definitions $('.def').each(function{		if ($(this).val === ''){			mw.notify('A definition was empty, defaulted to ');			markup += "# \n";		}		else			markup += "# " + $(this).val + "\n";	}); // Add newline after def markup += "\n"; // Add headings $('.hl').each(function{		//var markup = markup		if ($(this).next.val === ''){			mw.notify('A field is empty, please fix');			return;		}		else {			markup += "===" + $(this).text + "===\n";			markup += $(this).next.val + "\n\n";		}	}); $('#wpTextbox1').val(markup); // Edit summary var neceditsummary = "(So9qs rewritten NEC) +" + lang + ":" + pos + ": "; $('.def').each(function{			neceditsummary += $(this).val + ", ";	}); // Set summary $("#wpSummary").val(neceditsummary); } // Inflection data ported and extended from newentrywiz.js var title = mw.config.get( 'wgTitle' ); var necinfl = { // This is the reference object da: { noun: { prepend: '', // The subarrays in items all have this format: // prepend/special word, append, wikicode // The special words supported are: (inherited), // (no singular definite), (no plural), (not used), // (not comparable), input items: stem=']					, ['Singular definite', '', [ // format: prepend/special, append, wikicode // specials: (inherited), (no singular definite), // (no plural), (not used), (not comparable), input ['', 'en', '|en'], ['', 'et', '|et'], ['', 't', '|t'], ['', 'n', '|n'], ['(no singular definite)', '', '|-'], ['input', 'Other: ', '|'] ]], 					['Plural', '', [ ['', 'e', '|e'], ['', 'er', '|er'], ['', 'r', '|r'], ['', 's', '|s'], [, , '|'], // e.g. syndefald ['(no plural)', '', '|-'], ['input', 'Other: ', '|'] ]]],		},		verb: { prepend: '', double_consonant: '1', // 1=true 0=false items: [ // This now supports splitting verbs with particle endings // Example: tage kål på				['Imperative form without particle ending', '', [ ['input', ' ', '|'] // tage ]], 				['Imperative (particle ending)', '', [ ['input', 'Optional: ', '|particle='] // kål på				]], ['Infinitive', '', [ ['(inherited)', '', '|'], ['input', 'Other: ', '|'] ]], 				['Present', '', [ ['', 'r', '|er'], ['', 'er', '|er'], ['(not used)', '', '|-'], ['input', 'Other: ', '|'] ]], 				['Past', '', [ ['', 'ede', '|ede'], ['(not used)', '', '|-'], ['input', 'Other: ', '|'] ]], 				['Past participle', '', [ ['har ', 'et', '|har|et'], ['har ', 't', '|har|t'], ['(not used)', '', '|-'], ['input', 'Other: ', '|har|'] ]], ],		},		adjective: { prepend: '', items: t'],				['input', 'Other: ', '|']			, ['Plural or definite', '', [ ['', 'e', '|e'], ['', 'er', '|er'], ['(not used)', '|-'], ['input', 'Other: ', '|'] ]], 			['Comparative', '', [ ['', 'ere', '|ere'], ['mere ', '', '|mere'], ['(not used)', '|-'], ['input', 'Other: ', '|'] ]], 			['Superlative pred.', '', [ ['', 'est', '|est'], ['', 'st', '|st'], ['mest ', '', '|mest'], ['(not used)', '', '|-'], ['input', 'Other: ', '|'] ]], 			['Superlative attr.', '', [ ['', 'este', '|este'], ['', 'ste', '|ste'], ['mest ', 'e', '|mest ' + title + 'e'], ['(not used)', '', '|-'], ['input', 'Other: ', '|'] ]], ],		},		adverb: {prepend: ''}, propernoun: {prepend: ''} },	eo: { noun: {prepend: ''}, verb: {prepend: ''}, adjective: {prepend: ''}, adverb: {prepend: ''}, propernoun: {prepend: ''} },

es: { noun: {prepend: ''}, adjective: {prepend: ''}, adverb: {prepend: ''}, propernoun: {prepend: ''} },

fr: { noun: { prepend: '', items: m'],				['feminine', '', '|f']			, ['Plural', '', [ [, 's', ], ['(uncountable)', '', '|pl=-'], ['input', ' ', '|pl=']]] ]		},		adjective: {prepend: ''}, verb: {prepend: ''}, adverb: {prepend: ''} }, };

// This function sets up the inflection subsections based on the dynamic // variables stem and imperative when update_only is true. // TODO implement imperative and generalize more function setup_infl(update_only) { function processor(object, option, stem, imperative) { /*	This is the workhorse of the inflection setup. There are 4 scenarios: 1) option is Stem and stem is null				=> generate stem radio and input			2) option is not stem and stem is null => generate radio and input for the rest 3) (update_only=true) option is Stem and stem is set				Nothing is done in this case			4) (update_only=true) option is not stem and stem is set => update the inflections */		// Clean option var option = clean(option); var specials = ['(no singular definite)', '(no plural)', '(not used)', '(not comparable)', '(uncountable)']; var infls = object[2].map(function(value, index){				//console.info('subarray value: '+ value[0]);				var pre = value[0];				var app = value[1];				var wiki = value[2];				//console.info('pre: '+pre + ' app: '+app+' wiki: '+wiki)				var title;				if (stem){					// Use clean stem as title					title = stem.slice(6);					console.info('stem is set: ' + stem);				}				else if (imperative) {					// Use clean imperative as title					title = imperative.slice(1);					console.info('imperative is set: ' + imperative);									}				else 					title = mw.config.get( 'wgTitle' );				// [0] = displayed infl				// [1] = wikicode				// Check the first options when 				if (index === 0 && specials.indexOf(pre) === -1 && option !== 'Stem' && pre !== 'input')					return '' +							'' +							pre + title + app +	' ';				else if (pre === '(inherited)' && stem === null)					// show only pre and check					// stem must be null to avoid duplicating the stem input box on update					return ' ' +							'' +							 pre + 	' ';				// Specials - show only pre				else if (specials.indexOf(pre) !== -1)					return '' +							'' +							 pre + 	' ';				else if (pre === 'input' && option === ('Stem' || 'Imperative form without particle ending') && stem === null)					// This is the input we later gather the custom stem from // stem must be null to avoid duplicating the stem input box on update return $(' ').addClass('span_other_'+ option).append(						$(' ').attr({ type: 'radio', name: option + 'infl', value: 'other' }),						$(' ').text(app).append( $(' ').addClass('input_text').attr({							type: 'text',							name: clean(option),							value: wiki						}))); else if (pre == 'input' && option != 'Stem') // Other inputs not related to stem that we remove and update later return $(' ').addClass('span_other_'+ option) .addClass('nec_infl_removable').append(						$(' ').attr({ type: 'radio', name: option + 'infl', value: 'other' }),						$(' ').text(app).append( $(' ').addClass('input_text').attr({							type: 'text',							name: 'other',							value: wiki						}))); else if (option != 'Stem') // Options not related to stem or input return '' + '' + pre + title + app + ' '; });		return infls;	}	// Common vars	var lang = $('#lang').val;	var pos = $('[name="pos"]:checked').val;	var pos_lower = pos.toLowerCase;	var title = mw.config.get( 'wgTitle' );	// Update the inflection based on the stem the user typed in	// TODO enable for imperative in verbs also.	if (update_only === true && pos_lower in necinfl[lang]) {		console.info('update_only infl');		// This is never true if inflection data does not exist		// Stem is already set, get it		var stem_input = $('.input_text[name=stem]').val;		var imperative_input = $('.input_text[name=imperative]').val;		var stem;		var imperative;		if (stem_input !== '|stem=') {			stem = stem_input;			console.info('stem: ' + stem);		}		else if (imperative_input !== '|') {			imperative = imperative_input;			console.info('imperative: ' + imperative);		}		// Generate the inflections		var infl_items_update = necinfl[lang][pos_lower]["items"].map(function(value){ // [0] contains the the infl option // [1] empty // [2] subarray with options //console.info(value) var option = value[0]; if (option == ('Stem' || 'Imperative')) { // These should not be updated return ''; }			else { // These should also be removed var p = $(' ').addClass('nec_infl_removable_p').text(option+':'); // Process subarray other than Stem var infls = processor(value, option, stem, imperative); //console.info(infls) return $(p).append(infls); }		});		// Obsolete ones now that a custom stem has been entered		// parent is the var p in the loop		$('.nec_infl_removable').parent.remove;		$('.nec_infl_removable_p').remove;		// Append custom stem-based inflections		//console.info(infl_items_update)		$('.infl').append(infl_items_update);		setup_click_keyup;	}	// Update is not true, generate all inflection options	else {		//console.info('default infl');		// Inflection data		// Common var		var p_title = $(' ').text('Inflections');		// Process inflection data if it exist		if(necinfl.hasOwnProperty(lang)) {			console.info('has lang data');			if(pos && title && pos_lower in necinfl[lang]) {				console.info('default infl ' + lang + ' ' + pos_lower);				var pre = necinfl[lang][pos_lower]["prepend"];				var app = necinfl[lang][pos_lower]["append"];				var dc = necinfl[lang][pos_lower]["double_consonant"];				// Include prepend and append as hidden var hidden = $(' ').append(						$(' ').attr({ type: 'hidden', name: 'prepend', value: pre }),						$(' ').attr({ type: 'hidden', name: 'append', value: app }));				// Handle double consonants if (dc == '1') var dc_p = $(' ').text('Enable double consonant handling').append(						$(' ').attr({ type: 'checkbox', name: 'dc', }));				else var dc_p = ''; // Check if items are defined var infl_items; if ("items" in necinfl[lang][pos_lower]){ // Generate the inflections for the first time infl_items = necinfl[lang][pos_lower]["items"].map(function(value){						// [0] contains the the infl option						// [1] empty						// [2] subarray with options						var option = value[0];						var p = $(' ').text(option+':');						// Process subarray						var infls = processor(value, option, null);						return $(p).append(infls);					}); } else { // Nothing other than prepend and append in the data infl_items = $(' ').addClass('nec_infl_removable_p') .text('Only template found, no inflection data.').css('color', 'red'); }			}			// Remove "No inflection data found" when switching PoS $('.infl').children.remove; $('.infl').append(p_title, hidden, dc_p, infl_items); setup_click_keyup; } // if data found else { console.info('no infl data'); // No inflection data found at all // remove old inflections if any $('.infl').children.remove; $('.infl').append(p_title.append( $(' '),				$(' ').addClass('nec_infl_removable').text('No inflection data found').css('color', 'red'))); }	} }

function setup_click_keyup { console.info('running setup_click_keyup') // Setup focus on other input boxes $('.input_text').focus(function {		$(this).parent.parent.find('[type=radio]').prop('checked', true);	}); // Reload infl if stem is changed $('.input_text[name=Stem]').keyup(function {		setTimeout(function{ setup_infl(true); }, 1500);	});	// Reload infl if code is changed $('#lang').keyup(function {		setTimeout(function{ setup_infl; }, 1500);	});	// Reload infl if imperative form is changed var imp_cleaned = clean('Imperative form without particle ending') $('.input_text[name='+imp_cleaned+']').keyup(function {		setTimeout(function{ setup_infl(true); }, 1500);	}); }

function form { var necheadings = ['Usage notes', 'Inflection', 'Conjugation', 'Declension', 'Quotations', 'Synonyms', 'Antonyms', 'Hypernyms', 'Hyponyms', 'Meronyms', 'Holonyms', 'Derived terms', 'Related terms', 'Coordinate terms', 'Descendants', 'Translations', 'See also', 'References']; var necposlist = ['Noun', 'Verb', 'Adjective', 'Adverb', 'Pronoun', 'Conjunction', 'Interjection', 'Preposition', 'Proper noun', 'Article', 'Prepositional phrase', 'Contraction', 'Prefix', 'Suffix', 'Symbol', 'Letter', 'Idiom', 'Phrase']; var p_lang = $(' ').text('Language code: ').append(		$(' ').attr({ type: 'text', value: lang, id: 'lang', size: 10 }))[0];	// Etymology var ety_b_items = ['cog', 'com', 'af']; var ety_buttons = ety_b_items.map(function(value){		return $(' ').addClass('unselectable', 'eb').attr({ type: 'button', name: value, value: 'Insert ' + value, onmousedown: 'button("' + value + '","'+ lang +'")' })[0];	});	//''; var p_ety = $(' ').text('Etymology: ').append(		$(' ').attr({ type: 'text', value: '', id: 'ety', size: 40 }))[0];	// Generate new array by mapping over necposlist var pos_items= necposlist.map(function(value) {		// Check the PoS from GET		if (pos_cap === value) {			return '' +					'' +					value +					' ';		}		// Check noun by default if no PoS set		else if (typeof pos_cap === 'undefined' && value == 'Noun') {			console.info('defaulting to noun');			return '' +					'' +					value +					' ';		}		else {			return '' +					'' +					value +					' ';		}	}); var pos_joined = '<p class="nec-options">' + pos_items.join(' ') + ' '; var p_pos = $(' ').text('Part of speech: ').append(pos_joined)[0]; // Inflection var div_infl = $(' ').addClass('infl'); var link_button = '<input class="unselectable" type="button" name="PasteOver" value=" + " onmousedown="wikilinkText; return false">'; var label_button = '<input class="unselectable" type="button" name="label" value="Insert label" onmousedown="label; return false">'; var rfdef_button = $(' ').addClass('unselectable', 'eb').attr({			type: 'button',			name: 'rfdef',			value: 'Insert ',			title: 'Note: This is the default if a definition is left empty.',			onmousedown: 'button("rfdef",true,false)' // false= no trailing '|'		})[0]; var def_buttons = $(' ').addClass('def_buttons').append(		link_button,label_button,rfdef_button); var div_def = $(' ').addClass('container1').append(		$(' ').addClass('add_form_field').text('Add another definition'),		$(' ').append( $(' ').text('Definition: '), $(' ').addClass('def').attr({				type: 'text',				value: def,				size: 40			}))); // Reference buttons var ref_button_da = $(' ').addClass('unselectable', 'eb').attr({			type: 'button',			name: 'ddo',			value: 'Insert ',			onmousedown: 'button("R:DDO",false,false)' // no lang, no trailing '|'		})[0]; // TODO add customization var ref_buttons = $(' ').addClass('ref_buttons').append(		ref_button_da); // Generate the headings dynamically // First generate the links var heading_links= necheadings.map(function(value) {		var h4 = $(' ').text(value).addClass('hl').attr('id', 'p_' +value);		var input = $(' ')			.css({ width: '50%', 'min-height': '5em' })			.attr({ type: 'textarea', value: '', id: 'input_' + value, /*rows: 5, cols: 20*/ });		var a = $('<a>')			.attr({ 'title': 'Remove', 'href': '#'})			.text('(−)')			.addClass('delete_heading');		return $('<a title="Add ' + value + ' heading">' + value + ' </a>').click(function{ $('#headings').append($(' ').append(h4, input, a)); });	});	// Show the links var headings_links = $(' ').attr({id:'headings_links'}).append(heading_links); // This is the div that the headings get appended to	var headings = $(' ').attr({id:'headings'}); var generate_button = $(' ').attr({			type: 'submit',			value: 'Generate',	}).click(function{generate}); var form = $(' ').append(		p_lang, ety_buttons, p_ety, p_pos, div_infl, def_buttons, div_def, headings_links, ref_buttons, headings, generate_button); // workaround bug related to the editform $('#editform').prepend($('#so9q-nec'), $('#editform').children.first); // Add the content $('#mw-content-text > div.mw-editintro').append(form); // Setup dynamic defs setup_defs; setup_headings; setup_infl; // Setup click on PoS $('[name="pos"]').click(setup_infl); }

$(document).ready(function necload {	$.when( mw.loader.using('mediawiki.util'), $.ready ).then( function { if (mw.config.get('wgPageName') === 'Special:Search') { mw.util.addPortletLink( mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions', '/w/index.php?title=' + mw.util.getParamValue('search') + '&action=edit&editintro=User:So9q/usenec', 'nec', 'id', 'use the New Entry Creator to create a new entry', 'n', 'nextnode'); }		if (typeof variable === 'undefined' || mw.util.getParamValue('action') === 'undefined' || mw.util.getParamValue('action') === 'edit' && mw.util.getParamValue('redlink') === '1') { mw.util.addPortletLink( mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions', '/w/index.php?title=' + mw.config.get('wgPageName') + '&action=edit&editintro=User:So9q/usenec', 'nec', 'id', 'use the New Entry Creator to create a new entry', 'm', 'nextnode'); }		if (document.getElementById('so9q-nec')) { form; }	} ); }); //