MediaWiki:Common.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* Apogea Wiki Common JavaScript
*/
(function() {
'use strict';
/**
* Sprite preview for Page Forms
*/
function initSpritePreview() {
var inputs = document.querySelectorAll('input');
var found = false;
inputs.forEach(function(input) {
var name = input.getAttribute('name') || '';
// Match sprite fields
if (name.indexOf('sprite]') === -1) return;
found = true;
console.log('[Apogea] Found sprite field:', name);
// Skip if already has preview
if (input.dataset.hasPreview) return;
input.dataset.hasPreview = 'true';
// Create preview container
var preview = document.createElement('div');
preview.className = 'sprite-preview';
preview.style.cssText = 'margin-top: 5px; min-height: 48px;';
input.parentNode.appendChild(preview);
// Find corresponding name field
var container = input.closest('tr') || input.closest('fieldset') || input.parentNode.parentNode;
var nameInput = null;
if (container) {
var allInputs = container.parentNode.querySelectorAll('input');
allInputs.forEach(function(inp) {
var n = inp.getAttribute('name') || '';
if (n.indexOf('[name]') !== -1) {
nameInput = inp;
}
});
}
function updatePreview() {
var spriteName = input.value.trim();
// Fall back to name field if sprite is empty
if (!spriteName && nameInput) {
spriteName = nameInput.value.trim();
}
if (!spriteName) {
preview.innerHTML = '<span style="color: #888;">No preview</span>';
return;
}
// Replace underscores with spaces for the filename
var fileName = spriteName.replace(/_/g, ' ') + '.png';
// Use MediaWiki API to get the actual file URL and dimensions
$.ajax({
url: mw.util.wikiScript('api'),
data: {
action: 'query',
titles: 'File:' + fileName,
prop: 'imageinfo',
iiprop: 'url|size',
format: 'json'
},
dataType: 'json',
success: function(data) {
var pages = data.query.pages;
var url = null;
var width = null;
var height = null;
for (var id in pages) {
if (pages[id].imageinfo && pages[id].imageinfo[0]) {
url = pages[id].imageinfo[0].url;
width = pages[id].imageinfo[0].width;
height = pages[id].imageinfo[0].height;
break;
}
}
if (url) {
// Scale up 2x
var scaledWidth = (width || 32) * 2;
var scaledHeight = (height || 32) * 2;
preview.innerHTML = '<img src="' + url + '" alt="' + spriteName + '" class="pixel-sprite" style="image-rendering: pixelated; width: ' + scaledWidth + 'px; height: ' + scaledHeight + 'px;">';
} else {
preview.innerHTML = '<span style="color: #c33;">Sprite not found: ' + fileName + '</span>';
}
},
error: function() {
preview.innerHTML = '<span style="color: #888;">Preview unavailable</span>';
}
});
}
// Update on input change (debounced)
var timeout;
input.addEventListener('input', function() {
clearTimeout(timeout);
timeout = setTimeout(updatePreview, 500);
});
// Also update when name field changes
if (nameInput) {
nameInput.addEventListener('input', function() {
if (!input.value.trim()) {
clearTimeout(timeout);
timeout = setTimeout(updatePreview, 500);
}
});
}
// Initial preview
updatePreview();
});
return found;
}
/**
* Live infobox preview for item forms
*/
function initInfoboxPreview() {
var containers = document.querySelectorAll('.item-form-container');
var found = false;
containers.forEach(function(container) {
var previewDiv = container.querySelector('.infobox-preview');
if (!previewDiv) return;
// Skip if already initialized
if (previewDiv.dataset.initialized) return;
previewDiv.dataset.initialized = 'true';
found = true;
console.log('[Apogea] Initializing infobox preview');
// Get all form fields in this container
var fields = container.querySelectorAll('input, select, textarea');
function getFieldValue(fieldName) {
var field = container.querySelector('[name*="[' + fieldName + ']"]');
return field ? field.value.trim() : '';
}
function updateInfoboxPreview() {
var name = getFieldValue('name') || mw.config.get('wgTitle') || 'Item';
var sprite = getFieldValue('sprite') || name;
var rarity = getFieldValue('rarity') || 'common';
var description = getFieldValue('description');
var damage = getFieldValue('damage');
var armor = getFieldValue('armor');
var defense = getFieldValue('defense');
var health = getFieldValue('health');
var mana = getFieldValue('mana');
var rng = getFieldValue('rng');
var attackSpeed = getFieldValue('attack_speed');
var moveSpeed = getFieldValue('move_speed');
var ability = getFieldValue('ability');
var magic = getFieldValue('magic');
var healthRegen = getFieldValue('health_regen');
var manaRegen = getFieldValue('mana_regen');
var weight = getFieldValue('weight');
var size = getFieldValue('size');
var slots = getFieldValue('container');
var type = getFieldValue('type');
var slot = getFieldValue('slot');
// Build wikitext for preview with all params
var params = [
'preview=true',
'name=' + name,
'sprite=' + sprite,
'rarity=' + rarity,
'float=none'
];
if (description) params.push('description=' + description);
if (damage) params.push('damage=' + damage);
if (armor) params.push('armor=' + armor);
if (defense) params.push('defense=' + defense);
if (health) params.push('health=' + health);
if (mana) params.push('mana=' + mana);
if (rng) params.push('rng=' + rng);
if (attackSpeed) params.push('attack_speed=' + attackSpeed);
if (moveSpeed) params.push('move_speed=' + moveSpeed);
if (ability) params.push('ability=' + ability);
if (magic) params.push('magic=' + magic);
if (healthRegen) params.push('health_regen=' + healthRegen);
if (manaRegen) params.push('mana_regen=' + manaRegen);
if (weight) params.push('weight=' + weight);
if (size) params.push('size=' + size);
if (slots) params.push('container=' + slots);
if (type) params.push('type=' + type);
if (slot) params.push('slot=' + slot);
var wikitext = '{{Infobox Item|' + params.join('|') + '}}';
// Use API to parse the wikitext
$.ajax({
url: mw.util.wikiScript('api'),
data: {
action: 'parse',
text: wikitext,
contentmodel: 'wikitext',
prop: 'text',
format: 'json',
disablelimitreport: true
},
dataType: 'json',
success: function(data) {
if (data.parse && data.parse.text) {
previewDiv.innerHTML = data.parse.text['*'];
} else {
previewDiv.innerHTML = '<em style="color: #888;">Preview unavailable</em>';
}
},
error: function() {
previewDiv.innerHTML = '<em style="color: #888;">Preview unavailable</em>';
}
});
}
// Debounced update
var timeout;
fields.forEach(function(field) {
field.addEventListener('input', function() {
clearTimeout(timeout);
timeout = setTimeout(updateInfoboxPreview, 800);
});
field.addEventListener('change', function() {
clearTimeout(timeout);
timeout = setTimeout(updateInfoboxPreview, 800);
});
});
// Initial preview immediately
updateInfoboxPreview();
});
return found;
}
// Poll for form elements until found
function waitForForm(callback, maxAttempts) {
var attempts = 0;
maxAttempts = maxAttempts || 20;
function check() {
attempts++;
var container = document.querySelector('.item-form-container');
if (container) {
console.log('[Apogea] Form found after ' + attempts + ' attempts');
callback();
} else if (attempts < maxAttempts) {
setTimeout(check, 250);
} else {
console.log('[Apogea] Form not found after ' + maxAttempts + ' attempts');
}
}
check();
}
// Run on page load
function init() {
console.log('[Apogea] Common.js loaded');
// Try immediately
var spriteFound = initSpritePreview();
var infoboxFound = initInfoboxPreview();
// If not found, poll for form to load
if (!spriteFound || !infoboxFound) {
waitForForm(function() {
initSpritePreview();
initInfoboxPreview();
});
}
// Watch for dynamically added fields (e.g., "Add another" in Page Forms)
var observer = new MutationObserver(function(mutations) {
var shouldInit = false;
mutations.forEach(function(mutation) {
if (mutation.addedNodes.length) {
shouldInit = true;
}
});
if (shouldInit) {
initSpritePreview();
initInfoboxPreview();
}
});
// Observe body for form loading
observer.observe(document.body, { childList: true, subtree: true });
}
// Wait for DOM and jQuery
$(document).ready(init);
})();