User:Erutuon/scripts/Marshallese.js
< User:Erutuon | scripts
Note – after saving, you may have to bypass your browser’s cache to see the changes.
- Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
- Konqueror and Chrome: click Reload or press F5;
- Opera: clear the cache in Tools → Preferences;
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.
- This script lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • redirects • your own
$(() => {
// C: non-glide consonant
// G: glide
// V: vowel
// #: word boundary
// None of these occur in any of the rows.
const specialNotation = {
'C': '[pmtnrlkŋ][ʲˠʷ]?',
'G': '[jɰw]',
'V': '[æɛei]',
'#': '(?:^|\s|$)',
};
const hasSpecialNotation = str => {
return new RegExp('[' + Object.keys(specialNotation).join('') + ']')
.test(str);
};
// Add search box above table of Marshallese transcriptions
// in [[Module:mh-pronunc]].
// The box will accept the symbols C, G, V, #,
// which match a non-glide consonant, glide, vowel, and word boundary.
// If any of the symbols are included,
// the box searches the phonemic IPA transcription.
$('.mh-transcription-list').get().forEach(t => {
const getRows = t => {
return $(t).find('tr').filter((_, e) => {
return $(e).find('th').length === 0;
});
};
const name1 = 'mh-transcription-list-search';
const $searchLabel = $('<label>')
.attr('for', name1)
.text('Filter table rows:');
const $searchBox = $('<input>')
.attr({ 'type': 'search', 'id': name1 })
.on('input', function() {
const $rows = getRows(t);
const input = $(this).val();
let filterer;
if (hasSpecialNotation(input)) {
const regex = new RegExp(
input.replace(/./g, char => specialNotation[char]
? specialNotation[char] + "\\.?"
: char),
'g'
);
filterer = ($row, templateInput, phonemic) => {
return phonemic && regex.test(phonemic);
};
} else {
const lowercaseInput = input.toLowerCase();
filterer = ($row, templateInput) => {
return $row.text().toLowerCase().includes(input)
|| templateInput && templateInput.toLowerCase().includes(input);
};
}
$rows.each((_, row) => {
const $row = $(row);
$row.css(
'display',
filterer($row, $row.data('templateInput'), $row.data('phonemic')) ? '' : 'none');
});
});
const name2 = 'show-only-differences';
const $checkBoxLabel = $('<label>')
.attr('for', name2)
.text('Show only rows with a difference');
const $checkBox = $('<input>')
.attr({ 'type': 'checkbox', 'id': name2 })
.on('change', function() {
const $rows = getRows(t);
$rows.each((_, row) => {
const $row = $(row);
$row.css(
'display',
!this.checked || Boolean($row.data('hasDifference')) ? '' : 'none');
});
});
$(t).before($('<p>').append($searchLabel, $searchBox), $('<p>').append($checkBoxLabel, $checkBox));
});
const forEachTextNode = (func) => {
const key = Symbol();
const apply = node => {
if (!(node instanceof Node)) {
throw new TypeError("Expected Node");
}
for (const child of node.childNodes) {
if (child[key])
continue;
switch (child.nodeType) {
case Node.ELEMENT_NODE: apply(child); break;
case Node.TEXT_NODE: func(child);
}
child[key] = true;
}
};
return apply;
};
const addZwnjBeforeCedilla = forEachTextNode(textNode => {
textNode.nodeValue = textNode.nodeValue
.normalize('NFD')
.replace(/\u200C*\u0327/g, '\u200C\u0327')
.normalize('NFC');
});
$(":lang(mh)").get().forEach(addZwnjBeforeCedilla);
});