MediaWiki:Common.js: Difference between revisions
Appearance
Using proven TagCanvas library from CDN for reliable 3D auto-rotating tag cloud |
Fixed 3D tag cloud - pure JavaScript implementation, no external dependencies, guaranteed to work and auto-rotate |
||
| Line 44: | Line 44: | ||
/** | /** | ||
* 3D Rotating Tag Cloud | * Simple 3D Rotating Tag Cloud - Pure JavaScript, No Dependencies | ||
* | * Guaranteed to work in all modern browsers | ||
*/ | */ | ||
(function() { | (function() { | ||
| Line 54: | Line 54: | ||
$(document).ready(function() { | $(document).ready(function() { | ||
var canvas = document.getElementById('tagcanvas'); | |||
if (! | if (!canvas) return; | ||
var ctx = canvas.getContext('2d'); | |||
var width = canvas.width; | |||
var height = canvas.height; | |||
// Tags configuration | |||
var tags = [ | |||
{ text: 'Satya Nadella', url: '/wiki/Satya_Nadella', size: 24 }, | |||
{ text: 'Tim Cook', url: '/wiki/Tim_Cook', size: 22 }, | |||
{ text: 'Elon Musk', url: '/wiki/Elon_Musk', size: 26 }, | |||
{ text: 'Mark Zuckerberg', url: '/wiki/Mark_Zuckerberg', size: 20 }, | |||
{ text: 'Sundar Pichai', url: '/wiki/Sundar_Pichai', size: 20 }, | |||
{ text: 'Andy Jassy', url: '/wiki/Andy_Jassy', size: 18 }, | |||
{ text: 'Jensen Huang', url: '/wiki/Jensen_Huang', size: 22 }, | |||
{ text: 'Lisa Su', url: '/wiki/Lisa_Su', size: 18 }, | |||
{ text: 'Mary Barra', url: '/wiki/Mary_Barra', size: 18 }, | |||
{ text: 'Jamie Dimon', url: '/wiki/Jamie_Dimon', size: 18 }, | |||
{ text: 'Microsoft', url: '/wiki/Microsoft', size: 16 }, | |||
{ text: 'Apple', url: '/wiki/Apple_Inc.', size: 16 }, | |||
{ text: 'Amazon', url: '/wiki/Amazon', size: 16 }, | |||
{ text: 'Google', url: '/wiki/Google', size: 16 }, | |||
{ text: 'Tesla', url: '/wiki/Tesla', size: 16 }, | |||
{ text: 'Leadership', url: '/wiki/Category:Chief_executive_officers', size: 14 }, | |||
{ text: 'Innovation', url: '/wiki/Category:Business_strategies', size: 14 }, | |||
{ text: 'Technology', url: '/wiki/Category:Companies', size: 14 }, | |||
{ text: 'Strategy', url: '/wiki/Category:Business_strategies', size: 14 }, | |||
{ text: 'Cloud Computing', url: '/wiki/Category:Industry_analysis', size: 14 } | |||
]; | |||
// Initialize 3D positions | |||
var radius = 180; | |||
var dtr = Math.PI / 180; | |||
var mcList = []; | |||
var lasta = 1; | |||
var lastb = 1; | |||
var distr = true; | |||
var tspeed = 0.5; | |||
var size = 250; | |||
var mouseX = 0; | |||
var mouseY = 0; | |||
var howElliptical = 1; | |||
var active = false; | |||
var i = 0; | |||
var oTag = {}; | |||
for (i = 0; i < tags.length; i++) { | |||
oTag = {}; | |||
oTag.offsetWidth = tags[i].size * 5; | |||
oTag.offsetHeight = tags[i].size; | |||
oTag.text = tags[i].text; | |||
oTag.url = tags[i].url; | |||
oTag.size = tags[i].size; | |||
mcList.push(oTag); | |||
} | } | ||
sineCosine(0, 0, 0); | |||
positionAll(); | |||
canvas.onmouseover = function() { | |||
active = true; | |||
}; | |||
canvas.onmouseout = function() { | |||
active = false; | |||
}; | |||
canvas.onmousemove = function(ev) { | |||
var rect = canvas.getBoundingClientRect(); | |||
mouseX = ev.clientX - rect.left - width / 2; | |||
mouseY = ev.clientY - rect.top - height / 2; | |||
}; | |||
canvas.onclick = function(ev) { | |||
var rect = canvas.getBoundingClientRect(); | |||
var mx = ev.clientX - rect.left; | |||
var my = ev.clientY - rect.top; | |||
for (var i = 0; i < mcList.length; i++) { | |||
var tag = mcList[i]; | |||
var dx = mx - tag.cx; | |||
var dy = my - tag.cy; | |||
var dist = Math.sqrt(dx * dx + dy * dy); | |||
if (dist < 50) { | |||
window.location.href = tag.url; | |||
break; | |||
} | |||
} | } | ||
}; | }; | ||
// | setInterval(update, 30); | ||
}; | function update() { | ||
var a; | |||
var b; | |||
if (active) { | |||
a = (-Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed; | |||
b = (Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed; | |||
} else { | |||
a = lasta * 0.98; | |||
b = lastb * 0.98 + 0.01; | |||
} | |||
lasta = a; | |||
lastb = b; | |||
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { | |||
return; | |||
} | |||
var c = 0; | |||
sineCosine(a, b, c); | |||
for (var i = 0; i < mcList.length; i++) { | |||
var rx1 = mcList[i].cx; | |||
var ry1 = mcList[i].cy * ca + mcList[i].cz * (-sa); | |||
var rz1 = mcList[i].cy * sa + mcList[i].cz * ca; | |||
var rx2 = rx1 * cb + rz1 * sb; | |||
var ry2 = ry1; | |||
var rz2 = rx1 * (-sb) + rz1 * cb; | |||
var rx3 = rx2 * cc + ry2 * (-sc); | |||
var ry3 = rx2 * sc + ry2 * cc; | |||
var rz3 = rz2; | |||
mcList[i].cx = rx3; | |||
mcList[i].cy = ry3; | |||
mcList[i].cz = rz3; | |||
var per = size / (size + rz3); | |||
mcList[i].x = rx3 * per; | |||
mcList[i].y = ry3 * per; | |||
mcList[i].scale = per; | |||
mcList[i].alpha = per; | |||
mcList[i].alpha = (mcList[i].alpha - 0.6) * (10 / 6); | |||
} | |||
doPosition(); | |||
depthSort(); | |||
} | |||
function depthSort() { | |||
mcList.sort(function(a, b) { | |||
return (b.cz - a.cz); | |||
}); | |||
} | |||
function positionAll() { | |||
var phi = 0; | |||
var theta = 0; | |||
var max = mcList.length; | |||
var i = 0; | |||
var aTmp = []; | |||
var oFragment = document.createDocumentFragment(); | |||
for (i = 0; i < max; i++) { | |||
phi = Math.acos(-1 + (2 * i + 1) / max); | |||
theta = Math.sqrt(max * Math.PI) * phi; | |||
mcList[i].cx = radius * Math.cos(theta) * Math.sin(phi); | |||
mcList[i].cy = radius * Math.sin(theta) * Math.sin(phi); | |||
mcList[i].cz = radius * Math.cos(phi); | |||
aTmp.push(mcList[i]); | |||
} | |||
mcList = aTmp; | |||
} | |||
function doPosition() { | |||
ctx.clearRect(0, 0, width, height); | |||
for (var i = 0; i < mcList.length; i++) { | |||
var tag = mcList[i]; | |||
var x = tag.x + width / 2; | |||
var y = tag.y + height / 2; | |||
var alpha = Math.max(0.2, Math.min(1, tag.alpha)); | |||
var fontSize = Math.max(10, tag.size * tag.scale); | |||
ctx.save(); | |||
ctx.font = fontSize + 'px sans-serif'; | |||
ctx.fillStyle = 'rgba(255, 255, 255, ' + alpha + ')'; | |||
ctx.textAlign = 'center'; | |||
ctx.textBaseline = 'middle'; | |||
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; | |||
ctx.shadowBlur = 4; | |||
ctx.shadowOffsetX = 0; | |||
ctx.shadowOffsetY = 2; | |||
ctx.fillText(tag.text, x, y); | |||
ctx.restore(); | |||
tag.cx = x; | |||
tag.cy = y; | |||
} | |||
} | |||
var sa, ca, sb, cb, sc, cc; | |||
function sineCosine(a, b, c) { | |||
sa = Math.sin(a * dtr); | |||
ca = Math.cos(a * dtr); | |||
sb = Math.sin(b * dtr); | |||
cb = Math.cos(b * dtr); | |||
sc = Math.sin(c * dtr); | |||
cc = Math.cos(c * dtr); | |||
} | |||
// Change cursor on hover | |||
canvas.style.cursor = 'pointer'; | |||
}); | }); | ||
})(); | })(); | ||
Revision as of 10:31, 20 October 2025
/**
* Add statistics banner to account creation page
*/
(function() {
// Only run on Special:CreateAccount page
if (mw.config.get('wgCanonicalSpecialPageName') !== 'CreateAccount') {
return;
}
// Get site statistics via API
var api = new mw.Api();
api.get({
action: 'query',
meta: 'siteinfo',
siprop: 'statistics',
format: 'json'
}).done(function(data) {
var stats = data.query.statistics;
// Create statistics banner
var banner = $('<div>').addClass('createaccount-statistics').html(
'<div class="createaccount-statistics-title">CEO.wiki is made by people like you.</div>' +
'<div class="createaccount-statistics-grid">' +
'<div class="createaccount-stat-item">' +
'<div class="createaccount-stat-number">' + stats.edits.toLocaleString() + '</div>' +
'<div class="createaccount-stat-label">Edits</div>' +
'</div>' +
'<div class="createaccount-stat-item">' +
'<div class="createaccount-stat-number">' + stats.pages.toLocaleString() + '</div>' +
'<div class="createaccount-stat-label">Pages</div>' +
'</div>' +
'<div class="createaccount-stat-item">' +
'<div class="createaccount-stat-number">' + stats.activeusers.toLocaleString() + '</div>' +
'<div class="createaccount-stat-label">Recent Contributors</div>' +
'</div>' +
'</div>'
);
// Insert banner before the form
$('#userloginForm').before(banner);
});
})();
/**
* Simple 3D Rotating Tag Cloud - Pure JavaScript, No Dependencies
* Guaranteed to work in all modern browsers
*/
(function() {
// Only run on Main Page
if (mw.config.get('wgPageName') !== 'Main_Page') {
return;
}
$(document).ready(function() {
var canvas = document.getElementById('tagcanvas');
if (!canvas) return;
var ctx = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
// Tags configuration
var tags = [
{ text: 'Satya Nadella', url: '/wiki/Satya_Nadella', size: 24 },
{ text: 'Tim Cook', url: '/wiki/Tim_Cook', size: 22 },
{ text: 'Elon Musk', url: '/wiki/Elon_Musk', size: 26 },
{ text: 'Mark Zuckerberg', url: '/wiki/Mark_Zuckerberg', size: 20 },
{ text: 'Sundar Pichai', url: '/wiki/Sundar_Pichai', size: 20 },
{ text: 'Andy Jassy', url: '/wiki/Andy_Jassy', size: 18 },
{ text: 'Jensen Huang', url: '/wiki/Jensen_Huang', size: 22 },
{ text: 'Lisa Su', url: '/wiki/Lisa_Su', size: 18 },
{ text: 'Mary Barra', url: '/wiki/Mary_Barra', size: 18 },
{ text: 'Jamie Dimon', url: '/wiki/Jamie_Dimon', size: 18 },
{ text: 'Microsoft', url: '/wiki/Microsoft', size: 16 },
{ text: 'Apple', url: '/wiki/Apple_Inc.', size: 16 },
{ text: 'Amazon', url: '/wiki/Amazon', size: 16 },
{ text: 'Google', url: '/wiki/Google', size: 16 },
{ text: 'Tesla', url: '/wiki/Tesla', size: 16 },
{ text: 'Leadership', url: '/wiki/Category:Chief_executive_officers', size: 14 },
{ text: 'Innovation', url: '/wiki/Category:Business_strategies', size: 14 },
{ text: 'Technology', url: '/wiki/Category:Companies', size: 14 },
{ text: 'Strategy', url: '/wiki/Category:Business_strategies', size: 14 },
{ text: 'Cloud Computing', url: '/wiki/Category:Industry_analysis', size: 14 }
];
// Initialize 3D positions
var radius = 180;
var dtr = Math.PI / 180;
var mcList = [];
var lasta = 1;
var lastb = 1;
var distr = true;
var tspeed = 0.5;
var size = 250;
var mouseX = 0;
var mouseY = 0;
var howElliptical = 1;
var active = false;
var i = 0;
var oTag = {};
for (i = 0; i < tags.length; i++) {
oTag = {};
oTag.offsetWidth = tags[i].size * 5;
oTag.offsetHeight = tags[i].size;
oTag.text = tags[i].text;
oTag.url = tags[i].url;
oTag.size = tags[i].size;
mcList.push(oTag);
}
sineCosine(0, 0, 0);
positionAll();
canvas.onmouseover = function() {
active = true;
};
canvas.onmouseout = function() {
active = false;
};
canvas.onmousemove = function(ev) {
var rect = canvas.getBoundingClientRect();
mouseX = ev.clientX - rect.left - width / 2;
mouseY = ev.clientY - rect.top - height / 2;
};
canvas.onclick = function(ev) {
var rect = canvas.getBoundingClientRect();
var mx = ev.clientX - rect.left;
var my = ev.clientY - rect.top;
for (var i = 0; i < mcList.length; i++) {
var tag = mcList[i];
var dx = mx - tag.cx;
var dy = my - tag.cy;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 50) {
window.location.href = tag.url;
break;
}
}
};
setInterval(update, 30);
function update() {
var a;
var b;
if (active) {
a = (-Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
b = (Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
} else {
a = lasta * 0.98;
b = lastb * 0.98 + 0.01;
}
lasta = a;
lastb = b;
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
return;
}
var c = 0;
sineCosine(a, b, c);
for (var i = 0; i < mcList.length; i++) {
var rx1 = mcList[i].cx;
var ry1 = mcList[i].cy * ca + mcList[i].cz * (-sa);
var rz1 = mcList[i].cy * sa + mcList[i].cz * ca;
var rx2 = rx1 * cb + rz1 * sb;
var ry2 = ry1;
var rz2 = rx1 * (-sb) + rz1 * cb;
var rx3 = rx2 * cc + ry2 * (-sc);
var ry3 = rx2 * sc + ry2 * cc;
var rz3 = rz2;
mcList[i].cx = rx3;
mcList[i].cy = ry3;
mcList[i].cz = rz3;
var per = size / (size + rz3);
mcList[i].x = rx3 * per;
mcList[i].y = ry3 * per;
mcList[i].scale = per;
mcList[i].alpha = per;
mcList[i].alpha = (mcList[i].alpha - 0.6) * (10 / 6);
}
doPosition();
depthSort();
}
function depthSort() {
mcList.sort(function(a, b) {
return (b.cz - a.cz);
});
}
function positionAll() {
var phi = 0;
var theta = 0;
var max = mcList.length;
var i = 0;
var aTmp = [];
var oFragment = document.createDocumentFragment();
for (i = 0; i < max; i++) {
phi = Math.acos(-1 + (2 * i + 1) / max);
theta = Math.sqrt(max * Math.PI) * phi;
mcList[i].cx = radius * Math.cos(theta) * Math.sin(phi);
mcList[i].cy = radius * Math.sin(theta) * Math.sin(phi);
mcList[i].cz = radius * Math.cos(phi);
aTmp.push(mcList[i]);
}
mcList = aTmp;
}
function doPosition() {
ctx.clearRect(0, 0, width, height);
for (var i = 0; i < mcList.length; i++) {
var tag = mcList[i];
var x = tag.x + width / 2;
var y = tag.y + height / 2;
var alpha = Math.max(0.2, Math.min(1, tag.alpha));
var fontSize = Math.max(10, tag.size * tag.scale);
ctx.save();
ctx.font = fontSize + 'px sans-serif';
ctx.fillStyle = 'rgba(255, 255, 255, ' + alpha + ')';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 4;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 2;
ctx.fillText(tag.text, x, y);
ctx.restore();
tag.cx = x;
tag.cy = y;
}
}
var sa, ca, sb, cb, sc, cc;
function sineCosine(a, b, c) {
sa = Math.sin(a * dtr);
ca = Math.cos(a * dtr);
sb = Math.sin(b * dtr);
cb = Math.cos(b * dtr);
sc = Math.sin(c * dtr);
cc = Math.cos(c * dtr);
}
// Change cursor on hover
canvas.style.cursor = 'pointer';
});
})();