/*
// Rewrite of https://en.wiktionary.orghttps://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 */
// <nowiki>
"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 = ']';
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) + ']' + 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 = '{{lb|' + lang + '|}} ' + 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 + '{{' + value + append + '}} ';
else
activeElement.value = val + '{{' + value +'|' + lang + append + '}} ';
}
}
}
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($('<div>').append(
$('<input>').addClass('def').attr({
type: 'text',
//name: def,
size: 40
}),
'<a href="#" class="delete">Delete</a>'));
} 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 = "=={{subst:#invoke:languages/templates|getByCode|" + lang + "|getCanonicalName}}==\n\n";
// Etymology
if ($('#ety').val() !== '') {
markup += "===Etymology===\n";
markup += $('#ety').val() + "\n\n";
}
else {
markup += "===Etymology===\n";
markup += "{{rfe|" + lang + "}}\n\n";
}
// PoS
var 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 = $(':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').val();
}
}
// PoS subheading
// Common vars
var pre = $('').val();
var app = $('').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 = $(':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 {{head}}');
markup += "{{head" + "|" + lang + "|" + pos.toLowerCase() + "}}\n\n";
}
// Definitions
$('.def').each(function(){
if ($(this).val() === ''){
mw.notify('A definition was empty, defaulted to {{rfdef}}');
markup += "# {{rfdef|" + lang + "}}\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 = "(]) +" + 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: '{{da-noun',
append: '}}',
// 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
,
,
,
,
,
]],
['Plural', '', [
,
,
,
,
, // e.g. syndefald
,
]]],
},
verb: {
prepend: '{{da-verb',
append: '}}',
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', '', [
// tage
]],
['Imperative (particle ending)', '', [
// kål på
]],
['Infinitive', '', [
,
]],
['Present', '', [
,
,
,
]],
['Past', '', [
,
,
]],
['Past participle', '', [
,
,
,
]], ],
},
adjective: {
prepend: '{{da-adj',
append: '}}',
items: [['Neuter', '', [
,
]],
['Plural or definite', '', [
,
,
,
]],
['Comparative', '', [
,
,
,
]],
['Superlative pred.', '', [
,
,
,
,
]],
['Superlative attr.', '', [
,
,
,
,
]], ],
},
adverb: {prepend: '{{da-adv', append: '}}'},
propernoun: {prepend: '{{da-proper noun', append: '}}'}
},
eo: {
noun: {prepend: '{{eo-noun', append: '}}'},
verb: {prepend: '{{eo-verb', append: '}}'},
adjective: {prepend: '{{eo-adj', append: '}}'},
adverb: {prepend: '{{eo-adv', append: '}}'},
propernoun: {prepend: '{{eo-proper noun', append: '}}'}
},
es: {
noun: {prepend: '{{es-noun', append: '}}'},
adjective: {prepend: '{{es-adj', append: '}}'},
adverb: {prepend: '{{es-adv', append: '}}'},
propernoun: {prepend: '{{es-proper noun', append: '}}'}
},
fr: {
noun: {
prepend: '{{fr-noun',
append: '}}',
items: [['Gender', '', [
,
,
]],
['Plural', '', [
,
,
]]
]
},
adjective: {prepend: '{{fr-adj', append: '}}'},
verb: {prepend: '{{fr-verb', append: '}}'},
adverb: {prepend: '{{fr-adv', append: '}}'}
},
};
// 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.map(function(value, index){
//console.info('subarray value: '+ value);
var pre = value;
var app = value;
var wiki = value;
//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' );
// = displayed infl
// = wikicode
// Check the first options when
if (index === 0 && specials.indexOf(pre) === -1 &&
option !== 'Stem' && pre !== 'input')
return '<label class="nec_infl_removable">' +
'<input type="radio" name="' + option + 'infl" value="' + wiki + '"' + 'checked="checked"' + '>' +
pre + title + app + '</label>';
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 '<label>' +
'<input type="radio" name="' + option + 'infl" value="' + wiki + '"' + 'checked="checked"' + '>' +
pre + '</label>';
// Specials - show only pre
else if (specials.indexOf(pre) !== -1)
return '<label class="nec_infl_removable">' +
'<input type="radio" name="' + option + 'infl" value="' + wiki + '"' + '>' +
pre + '</label>';
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 $('<span>').addClass('span_other_'+ option).append(
$('<input>').attr({
type: 'radio',
name: option + 'infl',
value: 'other'
}),
$('<label>').text(app).append(
$('<input>').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 $('<span>').addClass('span_other_'+ option)
.addClass('nec_infl_removable').append(
$('<input>').attr({
type: 'radio',
name: option + 'infl',
value: 'other'
}),
$('<label>').text(app).append(
$('<input>').addClass('input_text').attr({
type: 'text',
name: 'other',
value: wiki
})));
else if (option != 'Stem')
// Options not related to stem or input
return '<label class="nec_infl_removable">' +
'<input type="radio" name="' + option + 'infl" value="' + wiki + '">' +
pre + title + app + '</label>';
});
return infls;
}
// Common vars
var lang = $('#lang').val();
var 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) {
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').val();
var imperative_input = $('.input_text').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.map(function(value){
// contains the the infl option
// empty
// subarray with options
//console.info(value)
var option = value;
if (option == ('Stem' || 'Imperative')) {
// These should not be updated
return '';
}
else {
// These should also be removed
var p = $('<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 = $('<p>').text('Inflections');
// Process inflection data if it exist
if(necinfl.hasOwnProperty(lang)) {
console.info('has lang data');
if(pos && title && pos_lower in necinfl) {
console.info('default infl ' + lang + ' ' + pos_lower);
var pre = necinfl;
var app = necinfl;
var dc = necinfl;
// Include prepend and append as hidden
var hidden = $('<span>').append(
$('<input>').attr({
type: 'hidden',
name: 'prepend',
value: pre
}),
$('<input>').attr({
type: 'hidden',
name: 'append',
value: app
}));
// Handle double consonants
if (dc == '1')
var dc_p = $('<p>').text('Enable double consonant handling').append(
$('<input>').attr({
type: 'checkbox',
name: 'dc',
}));
else
var dc_p = '';
// Check if items are defined
var infl_items;
if ("items" in necinfl){
// Generate the inflections for the first time
infl_items = necinfl.map(function(value){
// contains the the infl option
// empty
// subarray with options
var option = value;
var p = $('<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 = $('<small>').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(
$('</br>'),
$('<small>').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('').prop('checked', true);
});
// Reload infl if stem is changed
$('.input_text').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').keyup(function() {
setTimeout(function(){
setup_infl(true);
}, 1500);
});
}
function form() {
var necheadings = ;
var necposlist = ;
var p_lang = $('<p>').text('Language code: ').append(
$('<input>').attr({
type: 'text',
value: lang,
id: 'lang',
size: 10
}));
// Etymology
var ety_b_items = ;
var ety_buttons = ety_b_items.map(function(value){
return $('<input>').addClass('unselectable', 'eb').attr({
type: 'button',
name: value,
value: 'Insert ' + value,
onmousedown: 'button("' + value + '","'+ lang +'")'
});
});
//'<input class="unselectable" type="button" name="label" value="Insert label" onmousedown="label(); return false">';
var p_ety = $('<p>').text('Etymology: ').append(
$('<input>').attr({
type: 'text',
value: '',
id: 'ety',
size: 40
}));
// Generate new array by mapping over necposlist
var pos_items= necposlist.map(function(value) {
// Check the PoS from GET
if (pos_cap === value) {
return '<label class="nec-' + value + '">' +
'<input type="radio" name="pos" value="' + value + '"' + 'checked="checked"' + '>' +
value +
'</label>';
}
// Check noun by default if no PoS set
else if (typeof pos_cap === 'undefined' && value == 'Noun') {
console.info('defaulting to noun');
return '<label class="nec-' + value + '">' +
'<input type="radio" name="pos" value="' + value + '"' + 'checked="checked"' + '>' +
value +
'</label>';
}
else {
return '<label class="nec-' + value + '">' +
'<input type="radio" name="pos" value="' + value + '">' +
value +
'</label>';
}
});
var pos_joined = '<p class="nec-options">' + pos_items.join(' ') + '</p>';
var p_pos = $('<p>').text('Part of speech: ').append(pos_joined);
// Inflection
var div_infl = $('<div>').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 = $('<input>').addClass('unselectable', 'eb').attr({
type: 'button',
name: 'rfdef',
value: 'Insert {{rfdef|lang}}',
title: 'Note: This is the default if a definition is left empty.',
onmousedown: 'button("rfdef",true,false)' // false= no trailing '|'
});
var def_buttons = $('<div>').addClass('def_buttons').append(
link_button,label_button,rfdef_button);
var div_def = $('<div>').addClass('container1').append(
$('<button>').addClass('add_form_field').text('Add another definition'),
$('<div>').append(
$('<p>').text('Definition: '),
$('<input>').addClass('def').attr({
type: 'text',
value: def,
size: 40
})));
// Reference buttons
var ref_button_da = $('<input>').addClass('unselectable', 'eb').attr({
type: 'button',
name: 'ddo',
value: 'Insert {{R:DDO}}',
onmousedown: 'button("R:DDO",false,false)' // no lang, no trailing '|'
});
// TODO add customization
var ref_buttons = $('<div>').addClass('ref_buttons').append(
ref_button_da);
// Generate the headings dynamically
// First generate the links
var heading_links= necheadings.map(function(value) {
var h4 = $('<p>').text(value).addClass('hl').attr('id', 'p_' +value);
var input = $('<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($('<div>').append(h4, input, a));
});
});
// Show the links
var headings_links = $('<div>').attr({id:'headings_links'}).append(heading_links);
// This is the div that the headings get appended to
var headings = $('<div>').attr({id:'headings'});
var generate_button = $('<input>').attr({
type: 'submit',
value: 'Generate',
}).click(function(){generate()});
var form = $('<div>').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
$('').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', 'https://en.wiktionary.org/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', 'https://en.wiktionary.org/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();
}
} );
});
// </nowiki>