MediaWiki:Gadget-OpenExternal.js
Appearance
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.
// Open all external links on a new window
mw.loader.using(['mediawiki.util']).then(function () {
// Constants
const internalLinkActions = [
'edit', 'history', 'delete', 'submit', 'watch', 'unwatch',
'protect', 'unprotect', 'markpatrolled', 'purge', 'render'
];
const currentHostname = window.location.hostname;
// Helper function to apply external link attributes
function makeExternal(link) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
// Helper function to check if link should be treated as internal
function isInternalAction(url) {
try {
const linkUrl = new URL(url);
const action = linkUrl.searchParams.get('action');
return linkUrl.hostname === currentHostname && action && internalLinkActions.includes(action);
} catch (e) {
return false;
}
}
// Helper function to apply hover effects to social media icons
function applySocialIconHoverEffects() {
document.querySelectorAll('.link-open-external a').forEach(function(link) {
// Only apply to links that don't already have the effects
if (link.dataset.hoverEffectsApplied) return;
// Apply base transition styles
link.style.transition = 'all 0.2s ease-out';
link.style.transformOrigin = 'center';
// Add hover event listeners for scale effect
link.addEventListener('mouseenter', function() {
this.style.transform = 'scale(1.10)';
this.style.textDecoration = 'none';
});
link.addEventListener('mouseleave', function() {
this.style.transform = 'scale(1)';
});
// Mark as processed to avoid duplicate event listeners
link.dataset.hoverEffectsApplied = 'true';
});
}
function openExternalLinks() {
// Process MediaWiki external/interwiki links
document.querySelectorAll('a.external, a.extiw').forEach(function (link) {
if (link.getAttribute('target') === '_blank') return;
if (!isInternalAction(link.href)) {
makeExternal(link);
}
});
// Dedicated social media link processing: MediaWiki file syntax conversion
document.querySelectorAll('div.link-open-external a, div.ntldstats a').forEach(function (link) {
// Remove interfering class that redirects to File description pages
if (link.classList.contains('mw-file-description')) {
link.classList.remove('mw-file-description');
}
// Extract real URL from MediaWiki file link title attribute coming from SocialMedia.lua
if (link.href.includes('/File:') && link.title && link.title.startsWith('link=')) {
link.href = link.title.substring(5); // Remove 'link=' prefix
}
makeExternal(link);
});
// Smart detection for other unclassified external links
document.querySelectorAll('a[href^="http"]').forEach(function (link) {
if (link.getAttribute('target') === '_blank') return;
// Skip if already processed by prior selectors
if (link.closest('div.link-open-external, div.ntldstats') ||
link.classList.contains('external') ||
link.classList.contains('extiw')) {
return;
}
try {
const linkUrl = new URL(link.href);
if (linkUrl.hostname !== currentHostname) {
makeExternal(link);
}
} catch (e) {
makeExternal(link);
}
});
// Apply hover effects to all social media icons after DOM processing
applySocialIconHoverEffects();
}
// MutationObserver to handle dynamically inserted external links (like sidebar icons)
function setupDynamicLinkWatcher() {
const observer = new MutationObserver(function (mutations) {
for (const mutation of mutations) {
if (mutation.type !== 'childList') continue;
for (const node of mutation.addedNodes) {
if (node.nodeType !== Node.ELEMENT_NODE) continue;
// Check if node contains external links or canonical containers
if (node.matches && (
node.matches('a[href^="http"], div.link-open-external') ||
node.querySelector && node.querySelector('a[href^="http"], div.link-open-external')
)) {
openExternalLinks();
return; // Process once and exit early
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
mw.hook('wikipage.content').add(openExternalLinks);
// Set up the dynamic link watcher after initial page load
$(function () {
setupDynamicLinkWatcher();
});
});