Jump to content

MediaWiki:Common.js

The comprehensive free global encyclopedia of CEOs, corporate leadership, and business excellence
Revision as of 12:07, 19 October 2025 by Maintenance script (talk | contribs) (Added 3D interactive tag cloud JavaScript for Main Page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.
/* 3D Tag Cloud Interactive Animation */
(function() {
    if (typeof window.TagCloudInitialized !== 'undefined') return;
    window.TagCloudInitialized = true;

    function initTagCloud() {
        var container = document.getElementById('tagcloud-sphere');
        if (!container) return;

        var tags = container.getElementsByClassName('tag-item');
        if (tags.length === 0) return;

        var radius = 180;
        var dtr = Math.PI / 180;
        var mcList = [];
        var active = false;
        var lasta = 1;
        var lastb = 1;
        var distr = true;
        var tspeed = 2;
        var size = 250;
        var mouseX = 0;
        var mouseY = 0;
        var howElliptical = 1;
        var aA = null;
        var oDiv = container;

        // Position tags in 3D sphere
        var i = 0;
        var oTag = null;
        
        for (i = 0; i < tags.length; i++) {
            oTag = {};
            oTag.offsetWidth = tags[i].offsetWidth;
            oTag.offsetHeight = tags[i].offsetHeight;
            mcList.push(oTag);
        }

        sineCosine(0, 0, 0);

        positionAll();

        // Auto-rotate
        var autoRotateTimer = 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;
            }

            lasta = a;
            lastb = b;

            if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) {
                // Gentle auto-rotation when idle
                a = 0.3;
                b = 0.3;
            }

            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 = 350 / (350 + 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() {
            var i = 0;
            var aTmp = [];

            for (i = 0; i < tags.length; i++) {
                aTmp.push(tags[i]);
            }

            aTmp.sort(function(vItem1, vItem2) {
                if (vItem1.cz > vItem2.cz) {
                    return -1;
                } else if (vItem1.cz < vItem2.cz) {
                    return 1;
                } else {
                    return 0;
                }
            });

            for (i = 0; i < aTmp.length; i++) {
                aTmp[i].style.zIndex = i;
            }
        }

        function positionAll() {
            var phi = 0;
            var theta = 0;
            var max = mcList.length;
            var aTmp = [];
            var oFragment = document.createDocumentFragment();

            for (var i = 0; i < max; i++) {
                phi = Math.acos(-1 + (2 * i) / 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);

                tags[i].style.left = mcList[i].cx + oDiv.offsetWidth / 2 - mcList[i].offsetWidth / 2 + 'px';
                tags[i].style.top = mcList[i].cy + oDiv.offsetHeight / 2 - mcList[i].offsetHeight / 2 + 'px';
            }
        }

        function doPosition() {
            var l = oDiv.offsetWidth / 2;
            var t = oDiv.offsetHeight / 2;
            
            for (var i = 0; i < mcList.length; i++) {
                var item = tags[i];
                var mc = mcList[i];

                item.style.left = mc.x + l - mc.offsetWidth / 2 + 'px';
                item.style.top = mc.y + t - mc.offsetHeight / 2 + 'px';
                
                item.style.fontSize = Math.ceil(12 * mc.scale / 2) + 8 + 'px';
                item.style.filter = 'alpha(opacity=' + 100 * mc.alpha + ')';
                item.style.opacity = mc.alpha;
            }
        }

        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);
        }

        // Mouse/Touch interaction
        var containerElement = document.getElementById('tagcloud-container');
        
        containerElement.addEventListener('mouseover', function() {
            active = true;
        });

        containerElement.addEventListener('mouseout', function() {
            active = false;
        });

        containerElement.addEventListener('mousemove', function(ev) {
            var rect = containerElement.getBoundingClientRect();
            mouseX = ev.clientX - rect.left - containerElement.offsetWidth / 2;
            mouseY = ev.clientY - rect.top - containerElement.offsetHeight / 2;
        });

        // Touch support
        containerElement.addEventListener('touchstart', function() {
            active = true;
        });

        containerElement.addEventListener('touchend', function() {
            active = false;
        });

        containerElement.addEventListener('touchmove', function(ev) {
            ev.preventDefault();
            var rect = containerElement.getBoundingClientRect();
            var touch = ev.touches[0];
            mouseX = touch.clientX - rect.left - containerElement.offsetWidth / 2;
            mouseY = touch.clientY - rect.top - containerElement.offsetHeight / 2;
        });
    }

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTagCloud);
    } else {
        initTagCloud();
    }
})();