MediaWiki:Common.js
MediaWiki interface page
More actions
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.
(function () {
'use strict';
var STORAGE_KEY = 'bhikitiaFounderBirthdayPopupClosed';
var ONE_HOUR = 60 * 60 * 1000;
var TARGET_DATE = '08-23';
var PHOTO_URL = 'https://synchchaos.com/wp-content/uploads/2023/10/parvej.png';
function isBirthdayToday() {
var d = new Date();
var mm = String(d.getMonth() + 1).padStart(2, '0');
var dd = String(d.getDate()).padStart(2, '0');
return (mm + '-' + dd) === TARGET_DATE;
}
function shouldShowPopup() {
var closedAt = localStorage.getItem(STORAGE_KEY);
if (!closedAt) return true;
return Date.now() - parseInt(closedAt, 10) >= ONE_HOUR;
}
function closePopup(popup) {
popup.classList.add('bf-birthday-hide');
setTimeout(function () {
if (popup.parentNode) {
popup.parentNode.removeChild(popup);
}
}, 300);
localStorage.setItem(STORAGE_KEY, Date.now().toString());
}
function el(tag, opts) {
var node = document.createElement(tag);
opts = opts || {};
if (opts.className) node.className = opts.className;
if (opts.text) node.textContent = opts.text;
if (opts.attrs) {
for (var key in opts.attrs) {
if (Object.prototype.hasOwnProperty.call(opts.attrs, key)) {
node.setAttribute(key, opts.attrs[key]);
}
}
}
return node;
}
function buildPopup() {
var popup = el('div', { attrs: { id: 'bhikitia-founder-birthday-popup' } });
var overlay = el('div', { className: 'bf-birthday-overlay' });
var card = el('div', { className: 'bf-birthday-card' });
var closeBtn = el('button', {
className: 'bf-birthday-close',
text: '\u00D7',
attrs: {
type: 'button',
'aria-label': 'Close birthday message',
title: 'Close'
}
});
closeBtn.addEventListener('click', function () {
closePopup(popup);
});
var photo = el('img', {
className: 'bf-birthday-photo',
attrs: {
src: PHOTO_URL,
alt: 'Md Parvej Husen Talukder'
}
});
var title = el('div', {
className: 'bf-birthday-title',
text: 'Happy Birthday!'
});
var name = el('div', {
className: 'bf-birthday-name',
text: 'Md Parvej Husen Talukder'
});
var message = el('div', { className: 'bf-birthday-message' });
message.appendChild(document.createTextNode('Bhikitia wishes its '));
var strong = el('strong', { text: 'Founder' });
message.appendChild(strong);
message.appendChild(document.createTextNode(' a very happy birthday!'));
var subtitle = el('div', {
className: 'bf-birthday-subtitle',
text: 'Thank you for building an open, multilingual encyclopedia that empowers underrepresented voices around the world.'
});
var cake = el('div', {
className: 'bf-birthday-cake',
text: '\uD83C\uDF89 \uD83C\uDF82 \uD83C\uDF89'
});
card.appendChild(closeBtn);
card.appendChild(photo);
card.appendChild(title);
card.appendChild(name);
card.appendChild(message);
card.appendChild(subtitle);
card.appendChild(cake);
popup.appendChild(overlay);
popup.appendChild(card);
return popup;
}
function injectStyles() {
if (document.getElementById('bf-birthday-styles')) return;
var style = document.createElement('style');
style.id = 'bf-birthday-styles';
style.textContent =
'#bhikitia-founder-birthday-popup {' +
'position: fixed; inset: 0; z-index: 99999;' +
'display: flex; align-items: center; justify-content: center;' +
'animation: bfBirthdayFadeIn .35s ease;' +
'}' +
'.bf-birthday-overlay {' +
'position: absolute; inset: 0;' +
'background: rgba(0,0,0,.68); backdrop-filter: blur(5px);' +
'}' +
'.bf-birthday-card {' +
'position: relative; z-index: 2;' +
'width: min(440px, calc(100vw - 32px));' +
'padding: 38px 30px 32px; text-align: center;' +
'border-radius: 24px;' +
'background: linear-gradient(145deg, #ffffff, #fff8ec);' +
'box-shadow: 0 30px 80px rgba(0,0,0,.35), 0 8px 30px rgba(0,0,0,.18);' +
'border: 1px solid rgba(255,193,7,.35);' +
'}' +
'.bf-birthday-close {' +
'position: absolute; top: 12px; right: 14px;' +
'width: 34px; height: 34px; border: 0; border-radius: 50%;' +
'background: rgba(0,0,0,.07); color: #555;' +
'font-size: 25px; line-height: 30px; cursor: pointer;' +
'transition: .2s ease;' +
'}' +
'.bf-birthday-close:hover { background: rgba(0,0,0,.14); transform: rotate(90deg); }' +
'.bf-birthday-photo {' +
'width: 96px; height: 96px; border-radius: 50%;' +
'object-fit: cover; border: 3px solid #ffc107;' +
'box-shadow: 0 4px 16px rgba(0,0,0,.15);' +
'margin-bottom: 14px; display: block; margin-left: auto; margin-right: auto;' +
'}' +
'.bf-birthday-title { font-size: 28px; font-weight: 800; color: #d97706; margin-bottom: 5px; }' +
'.bf-birthday-name { font-size: 20px; font-weight: 700; color: #222; margin-bottom: 18px; }' +
'.bf-birthday-message { font-size: 16px; line-height: 1.7; color: #444; margin-bottom: 12px; }' +
'.bf-birthday-message strong { color: #b45309; }' +
'.bf-birthday-subtitle { font-size: 14px; line-height: 1.6; color: #777; }' +
'.bf-birthday-cake { margin-top: 20px; font-size: 25px; letter-spacing: 8px; }' +
'.bf-birthday-hide { animation: bfBirthdayFadeOut .3s ease forwards; }' +
'@keyframes bfBirthdayFadeIn { from { opacity: 0; } to { opacity: 1; } }' +
'@keyframes bfBirthdayFadeOut { from { opacity: 1; } to { opacity: 0; } }' +
'@media (max-width: 480px) {' +
'.bf-birthday-card { padding: 32px 22px 28px; border-radius: 20px; }' +
'.bf-birthday-photo { width: 80px; height: 80px; }' +
'.bf-birthday-title { font-size: 24px; }' +
'.bf-birthday-name { font-size: 17px; }' +
'}';
document.head.appendChild(style);
}
function init() {
if (!isBirthdayToday()) return;
if (!shouldShowPopup()) return;
injectStyles();
var popup = buildPopup();
document.body.appendChild(popup);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
mw.hook('wikipage.content').add(function () {
// Only show on Suzanne Elrod
if (mw.config.get('wgPageName') !== 'Suzanne_Elrod') {
return;
}
// Don't show more than once
if (document.querySelector('.bhikitia-third-party-ad')) {
return;
}
const ad = document.createElement('div');
ad.className = 'bhikitia-third-party-ad';
ad.innerHTML = `
<div class="bhikitia-third-party-ad-inner">
<div class="bhikitia-third-party-ad-label">
Advertisement
</div>
<div class="bhikitia-third-party-ad-content">
<p>
This space is provided for third-party advertising.
Bhikitia is not affiliated with or responsible for
the advertised products or services.
</p>
</div>
<button
type="button"
class="bhikitia-third-party-ad-close"
aria-label="Close advertisement"
>
×
</button>
</div>
`;
// Find the category section
const categories = document.querySelector('#catlinks');
if (categories) {
// Insert immediately before Categories
categories.parentNode.insertBefore(ad, categories);
} else {
// Fallback: put it at the end of the article content
const content = document.querySelector('#mw-content-text');
if (content) {
content.appendChild(ad);
} else {
return;
}
}
// Close button
const closeButton = ad.querySelector('.bhikitia-third-party-ad-close');
if (closeButton) {
closeButton.addEventListener('click', function () {
ad.remove();
});
}
});