MediaWiki:Common.js: Difference between revisions
From Tuyin Archives
No edit summary |
No edit summary |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
/** | // Audio Player System | ||
// Audio Player System | |||
/* Any JavaScript here will be loaded for all users on every page load. */ | |||
// Audio Player System | |||
// Mobile audio unlocker | |||
/* Any JavaScript here will be loaded for all users on every page load. */ | |||
// Audio Player System | |||
// Mobile audio unlocker (optional but harmless) | |||
document.addEventListener('DOMContentLoaded', function () { | |||
var isMobile = /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent); | |||
if (isMobile) { | |||
var unlockAudio = document.createElement('audio'); | |||
unlockAudio.src = "data:audio/ogg;base64,T2dnUwACAAAAAAAAAABVDxXAAAAAAACf5tYBHgF2b3JiaXMAAAAAAkSsAAAAAAD+/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; | |||
unlockAudio.muted = true; | |||
unlockAudio.playsInline = true; | |||
unlockAudio.autoplay = true; | |||
unlockAudio.preload = "auto"; | |||
document.body.appendChild(unlockAudio); | |||
unlockAudio.play().catch(() => {}); | |||
} | |||
}); | |||
mw.hook('wikipage.content').add(function($content) { | mw.hook('wikipage.content').add(function($content) { | ||
$content.find(' | $content.find('.audioplayer').each(function() { | ||
var | var $container = $(this); | ||
var id = | var filename = $container.attr('data-filename'); | ||
var audio = | var caption = $container.attr('data-caption') || 'Audio File'; | ||
if (!filename) return; | |||
var baseName = filename.replace(/\.\w+$/, ''); // remove extension if present | |||
// Generate unique ID | |||
var playerId = 'audio_' + Math.random().toString(36).substr(2, 9); | |||
// Create player HTML | |||
var $player = $('<div>').css({ | |||
'display': 'inline-flex', | |||
'align-items': 'center', | |||
'gap': '12px' | |||
}); | |||
var $playerBox = $('<div>').css({ | |||
'border': '1px solid #8B7355', | |||
'padding': '8px', | |||
'border-radius': '4px', | |||
'background-color': '#F5F0E8', | |||
'width': '200px' | |||
}); | |||
var $button = $('<button>').attr('id', playerId + '_btn').text('▶️').css({ | |||
'padding': '4px 8px', | |||
'margin-right': '8px', | |||
'font-size': '12px', | |||
'border': '1px solid #8B7355', | |||
'background': '#D4C4A8', | |||
'color': '#5D4E37' | |||
}); | |||
var $progressContainer = $('<div>').css({ | |||
'display': 'inline-block', | |||
'width': '120px', | |||
'height': '6px', | |||
'background-color': '#D4C4A8', | |||
'border-radius': '3px', | |||
'vertical-align': 'middle' | |||
}); | |||
var $progress = $('<div>').attr('id', playerId + '_progress').css({ | |||
'height': '100%', | |||
'background-color': '#8B7355', | |||
'border-radius': '3px', | |||
'width': '0%', | |||
'transition': 'width 0.1s' | |||
}); | |||
var $caption = $('<span>').text(caption).css({ | |||
'color': '#8B7355', | |||
'font-style': 'italic' | |||
}); | |||
// Build structure | |||
$progressContainer.append($progress); | |||
$playerBox.append($button).append($progressContainer); | |||
$player.append($playerBox).append($caption); | |||
// Replace container content | |||
$container.empty().append($player); | |||
// Create real DOM <audio> element with both sources | |||
var $realAudio = $('<audio preload="metadata" playsinline style="display:none;">') | |||
.append($('<source>').attr('src', 'https://tuyin.online/images/' + baseName + '.ogg').attr('type', 'audio/ogg')) | |||
.append($('<source>').attr('src', 'https://tuyin.online/images/' + baseName + '.mp3').attr('type', 'audio/mpeg')); | |||
$container.append($realAudio); | |||
var audio = $realAudio[0]; | |||
var isPlaying = false; | var isPlaying = false; | ||
$button.click(function() { | |||
if (isPlaying) { | if (isPlaying) { | ||
audio.pause(); | audio.pause(); | ||
$button.text('▶️'); | |||
isPlaying = false; | |||
} else { | } else { | ||
audio.play(); | audio.play().then(function() { | ||
$button.text('⏸️'); | |||
isPlaying = true; | |||
}).catch(function(error) { | |||
alert('Could not play audio: ' + error.message); | |||
}); | |||
} | } | ||
}); | }); | ||
audio.addEventListener('timeupdate', function () { | audio.addEventListener('timeupdate', function() { | ||
var percentage = (audio.currentTime / audio.duration) * 100; | if (audio.duration) { | ||
var percentage = (audio.currentTime / audio.duration) * 100; | |||
$progress.css('width', percentage + '%'); | |||
} | |||
}); | }); | ||
audio.addEventListener('ended', function () { | audio.addEventListener('ended', function() { | ||
$button.text('▶️'); | |||
$progress.css('width', '0%'); | |||
isPlaying = false; | isPlaying = false; | ||
}); | }); | ||
}); | }); | ||
}); | |||
//Translator Tool | |||
mw.hook('wikipage.content').add(function ($content) { | |||
if (mw.config.get('wgPageName') !== 'Translator') return; | |||
const languages = ['dwarven', 'orcian', 'ratik', 'elvic', 'snekian', 'trogian']; | |||
const dictionaries = {}; | |||
let loaded = 0; | |||
// UI setup | |||
const container = $('<div>').css({ | |||
padding: '1em', | |||
background: '#f5f0e8', | |||
border: '1px solid #ccc' | |||
}); | |||
const dropdown = $('<select>').css({ | |||
marginBottom: '1em', | |||
padding: '0.4em', | |||
display: 'block' | |||
}); | |||
dropdown.append($('<option>').val('').text('Select a language')); | |||
languages.forEach(lang => { | |||
dropdown.append($('<option>').val(lang).text(lang.charAt(0).toUpperCase() + lang.slice(1))); | |||
}); | |||
const input = $('<textarea>') | |||
.attr('placeholder', 'Enter English text...') | |||
.css({ width: '100%', height: '80px', marginBottom: '1em' }); | |||
const output = $('<div>').attr('id', 'translator-output'); | |||
container.append(dropdown).append(input).append(output); | |||
$content.prepend(container); | |||
// Load dictionaries | |||
languages.forEach(lang => { | |||
$.get(`/wiki/index.php?title=${lang.charAt(0).toUpperCase() + lang.slice(1)}&action=render`, html => { | |||
const dict = {}; | |||
$(html).find('table.wikitable tr').each(function () { | |||
const cells = $(this).find('td'); | |||
if (cells.length >= 2) { | |||
const english = $(cells[0]).text().trim().toLowerCase(); | |||
const translated = $(cells[1]).text().trim(); | |||
if (english && translated) { | |||
dict[english] = translated; | |||
} | |||
} | |||
}); | |||
dictionaries[lang] = dict; | |||
loaded++; | |||
}); | |||
}); | |||
function updateOutput() { | |||
const lang = dropdown.val(); | |||
const text = input.val().trim().toLowerCase(); | |||
if (!lang || !text || !dictionaries[lang]) { | |||
output.empty(); | |||
return; | |||
} | |||
const dict = dictionaries[lang]; | |||
const words = text.split(/\s+/); | |||
const normal = words.map(w => dict[w] || w).join(' '); | |||
const script = words.map(w => (dict[w] || w).toUpperCase()).join(' '); | |||
const block = $('<div>').css({ marginTop: '1em' }); | |||
block.append( | |||
$('<div>').css({ fontWeight: 'bold', marginBottom: '0.3em' }) | |||
.text(lang.charAt(0).toUpperCase() + lang.slice(1) + ':') | |||
); | |||
block.append($('<div>').text(normal)); | |||
block.append( | |||
$('<div>').addClass(lang).css({ | |||
fontSize: '160%', | |||
marginTop: '0.5em' | |||
}).text(script) | |||
); | |||
output.html(block); | |||
} | |||
input.on('input', updateOutput); | |||
dropdown.on('change', updateOutput); | |||
}); | }); | ||
Latest revision as of 13:20, 7 August 2025
/* Any JavaScript here will be loaded for all users on every page load. */
// Audio Player System
// Audio Player System
/* Any JavaScript here will be loaded for all users on every page load. */
// Audio Player System
// Mobile audio unlocker
/* Any JavaScript here will be loaded for all users on every page load. */
// Audio Player System
// Mobile audio unlocker (optional but harmless)
document.addEventListener('DOMContentLoaded', function () {
var isMobile = /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent);
if (isMobile) {
var unlockAudio = document.createElement('audio');
unlockAudio.src = "data:audio/ogg;base64,T2dnUwACAAAAAAAAAABVDxXAAAAAAACf5tYBHgF2b3JiaXMAAAAAAkSsAAAAAAD+/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
unlockAudio.muted = true;
unlockAudio.playsInline = true;
unlockAudio.autoplay = true;
unlockAudio.preload = "auto";
document.body.appendChild(unlockAudio);
unlockAudio.play().catch(() => {});
}
});
mw.hook('wikipage.content').add(function($content) {
$content.find('.audioplayer').each(function() {
var $container = $(this);
var filename = $container.attr('data-filename');
var caption = $container.attr('data-caption') || 'Audio File';
if (!filename) return;
var baseName = filename.replace(/\.\w+$/, ''); // remove extension if present
// Generate unique ID
var playerId = 'audio_' + Math.random().toString(36).substr(2, 9);
// Create player HTML
var $player = $('<div>').css({
'display': 'inline-flex',
'align-items': 'center',
'gap': '12px'
});
var $playerBox = $('<div>').css({
'border': '1px solid #8B7355',
'padding': '8px',
'border-radius': '4px',
'background-color': '#F5F0E8',
'width': '200px'
});
var $button = $('<button>').attr('id', playerId + '_btn').text('▶️').css({
'padding': '4px 8px',
'margin-right': '8px',
'font-size': '12px',
'border': '1px solid #8B7355',
'background': '#D4C4A8',
'color': '#5D4E37'
});
var $progressContainer = $('<div>').css({
'display': 'inline-block',
'width': '120px',
'height': '6px',
'background-color': '#D4C4A8',
'border-radius': '3px',
'vertical-align': 'middle'
});
var $progress = $('<div>').attr('id', playerId + '_progress').css({
'height': '100%',
'background-color': '#8B7355',
'border-radius': '3px',
'width': '0%',
'transition': 'width 0.1s'
});
var $caption = $('<span>').text(caption).css({
'color': '#8B7355',
'font-style': 'italic'
});
// Build structure
$progressContainer.append($progress);
$playerBox.append($button).append($progressContainer);
$player.append($playerBox).append($caption);
// Replace container content
$container.empty().append($player);
// Create real DOM <audio> element with both sources
var $realAudio = $('<audio preload="metadata" playsinline style="display:none;">')
.append($('<source>').attr('src', 'https://tuyin.online/images/' + baseName + '.ogg').attr('type', 'audio/ogg'))
.append($('<source>').attr('src', 'https://tuyin.online/images/' + baseName + '.mp3').attr('type', 'audio/mpeg'));
$container.append($realAudio);
var audio = $realAudio[0];
var isPlaying = false;
$button.click(function() {
if (isPlaying) {
audio.pause();
$button.text('▶️');
isPlaying = false;
} else {
audio.play().then(function() {
$button.text('⏸️');
isPlaying = true;
}).catch(function(error) {
alert('Could not play audio: ' + error.message);
});
}
});
audio.addEventListener('timeupdate', function() {
if (audio.duration) {
var percentage = (audio.currentTime / audio.duration) * 100;
$progress.css('width', percentage + '%');
}
});
audio.addEventListener('ended', function() {
$button.text('▶️');
$progress.css('width', '0%');
isPlaying = false;
});
});
});
//Translator Tool
mw.hook('wikipage.content').add(function ($content) {
if (mw.config.get('wgPageName') !== 'Translator') return;
const languages = ['dwarven', 'orcian', 'ratik', 'elvic', 'snekian', 'trogian'];
const dictionaries = {};
let loaded = 0;
// UI setup
const container = $('<div>').css({
padding: '1em',
background: '#f5f0e8',
border: '1px solid #ccc'
});
const dropdown = $('<select>').css({
marginBottom: '1em',
padding: '0.4em',
display: 'block'
});
dropdown.append($('<option>').val('').text('Select a language'));
languages.forEach(lang => {
dropdown.append($('<option>').val(lang).text(lang.charAt(0).toUpperCase() + lang.slice(1)));
});
const input = $('<textarea>')
.attr('placeholder', 'Enter English text...')
.css({ width: '100%', height: '80px', marginBottom: '1em' });
const output = $('<div>').attr('id', 'translator-output');
container.append(dropdown).append(input).append(output);
$content.prepend(container);
// Load dictionaries
languages.forEach(lang => {
$.get(`/wiki/index.php?title=${lang.charAt(0).toUpperCase() + lang.slice(1)}&action=render`, html => {
const dict = {};
$(html).find('table.wikitable tr').each(function () {
const cells = $(this).find('td');
if (cells.length >= 2) {
const english = $(cells[0]).text().trim().toLowerCase();
const translated = $(cells[1]).text().trim();
if (english && translated) {
dict[english] = translated;
}
}
});
dictionaries[lang] = dict;
loaded++;
});
});
function updateOutput() {
const lang = dropdown.val();
const text = input.val().trim().toLowerCase();
if (!lang || !text || !dictionaries[lang]) {
output.empty();
return;
}
const dict = dictionaries[lang];
const words = text.split(/\s+/);
const normal = words.map(w => dict[w] || w).join(' ');
const script = words.map(w => (dict[w] || w).toUpperCase()).join(' ');
const block = $('<div>').css({ marginTop: '1em' });
block.append(
$('<div>').css({ fontWeight: 'bold', marginBottom: '0.3em' })
.text(lang.charAt(0).toUpperCase() + lang.slice(1) + ':')
);
block.append($('<div>').text(normal));
block.append(
$('<div>').addClass(lang).css({
fontSize: '160%',
marginTop: '0.5em'
}).text(script)
);
output.html(block);
}
input.on('input', updateOutput);
dropdown.on('change', updateOutput);
});
