Jump to content

MediaWiki:Common.js: Difference between revisions

The comprehensive free global encyclopedia of CEOs, corporate leadership, and business excellence
Simplified 3D tag cloud with direct window.load initialization and retry logic
Pure JavaScript 3D tag cloud with extensive logging and multiple initialization methods
Line 4: Line 4:
(function() {
(function() {
     // Only run on Special:CreateAccount page
     // Only run on Special:CreateAccount page
     if (mw.config.get('wgCanonicalSpecialPageName') !== 'CreateAccount') {
     if (typeof mw !== 'undefined' && mw.config && mw.config.get('wgCanonicalSpecialPageName') !== 'CreateAccount') {
         return;
         return;
     }
     }


     // Get site statistics via API
     if (typeof mw !== 'undefined' && mw.Api && typeof $ !== 'undefined') {
    var api = new mw.Api();
        // Get site statistics via API
        var api = new mw.Api();


    api.get({
        api.get({
        action: 'query',
            action: 'query',
        meta: 'siteinfo',
            meta: 'siteinfo',
        siprop: 'statistics',
            siprop: 'statistics',
        format: 'json'
            format: 'json'
    }).done(function(data) {
        }).done(function(data) {
        var stats = data.query.statistics;
            var stats = data.query.statistics;


        // Create statistics banner
            // Create statistics banner
        var banner = $('<div>').addClass('createaccount-statistics').html(
            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-title">CEO.wiki is made by people like you.</div>' +
            '<div class="createaccount-statistics-grid">' +
                '<div class="createaccount-statistics-grid">' +
                '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-number">' + stats.edits.toLocaleString() + '</div>' +
                        '<div class="createaccount-stat-number">' + stats.edits.toLocaleString() + '</div>' +
                    '<div class="createaccount-stat-label">Edits</div>' +
                        '<div class="createaccount-stat-label">Edits</div>' +
                '</div>' +
                    '</div>' +
                '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-number">' + stats.pages.toLocaleString() + '</div>' +
                        '<div class="createaccount-stat-number">' + stats.pages.toLocaleString() + '</div>' +
                    '<div class="createaccount-stat-label">Pages</div>' +
                        '<div class="createaccount-stat-label">Pages</div>' +
                '</div>' +
                    '</div>' +
                '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-item">' +
                    '<div class="createaccount-stat-number">' + stats.activeusers.toLocaleString() + '</div>' +
                        '<div class="createaccount-stat-number">' + stats.activeusers.toLocaleString() + '</div>' +
                    '<div class="createaccount-stat-label">Recent Contributors</div>' +
                        '<div class="createaccount-stat-label">Recent Contributors</div>' +
                '</div>' +
                    '</div>' +
            '</div>'
                '</div>'
        );
            );


        // Insert banner before the form
            // Insert banner before the form
        $('#userloginForm').before(banner);
            $('#userloginForm').before(banner);
    });
        });
    }
})();
})();


/**
/**
  * Simple 3D Rotating Tag Cloud - Direct Initialization
  * Simple 3D Rotating Tag Cloud - Pure JavaScript - No Dependencies
* Uses window.onload for maximum compatibility
  */
  */
(function() {
function initCEOTagCloud() {
     // Only run on Main Page
    'use strict';
     if (mw.config.get('wgPageName') !== 'Main_Page') {
   
    console.log('[TagCloud] Script loaded');
   
     // Check if we're on Main Page
     if (typeof mw !== 'undefined' && mw.config) {
        var pageName = mw.config.get('wgPageName');
        console.log('[TagCloud] Page name:', pageName);
        if (pageName !== 'Main_Page') {
            console.log('[TagCloud] Not Main Page, exiting');
            return;
        }
    }
   
    var canvas = document.getElementById('tagcanvas');
    if (!canvas) {
        console.log('[TagCloud] Canvas element not found');
         return;
         return;
     }
     }
 
   
     function initTagCloud() {
    console.log('[TagCloud] Canvas found, initializing...');
         var canvas = document.getElementById('tagcanvas');
   
        if (!canvas) {
    // Hide the fallback list
            console.log('Canvas element not found, retrying in 100ms...');
     var ul = canvas.querySelector('ul');
             setTimeout(initTagCloud, 100);
    if (ul) {
             return;
         ul.style.display = 'none';
        console.log('[TagCloud] Fallback list hidden');
    }
   
    var ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error('[TagCloud] Could not get 2D context');
        return;
    }
   
    var width = canvas.width;
    var height = canvas.height;
   
    console.log('[TagCloud] Canvas size:', width, 'x', 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 tspeed = 0.5;
    var size = 250;
    var mouseX = 0;
    var mouseY = 0;
    var active = false;
   
    // Build tag objects
    for (var i = 0; i < tags.length; i++) {
        var 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);
    }
   
    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);
    }
   
    function positionAll() {
        var phi = 0;
        var theta = 0;
        var max = mcList.length;
       
        for (var 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);
        }
    }
   
    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;
         }
         }
 
    }
         console.log('Canvas found! Initializing 3D tag cloud...');
   
 
    function depthSort() {
         // Hide the fallback list
         mcList.sort(function(a, b) {
         var ul = canvas.querySelector('ul');
            return (b.cz - a.cz);
        if (ul) {
        });
             ul.style.display = 'none';
    }
   
    function update() {
        var a, 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;
         }
         }
 
       
         var ctx = canvas.getContext('2d');
        lasta = a;
         if (!ctx) {
         lastb = b;
            console.error('Could not get 2D context from canvas');
       
         if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
             return;
             return;
         }
         }
 
       
         var width = canvas.width;
         var c = 0;
         var height = canvas.height;
         sineCosine(a, b, c);
 
          
         // Tags configuration
         for (var i = 0; i < mcList.length; i++) {
         var tags = [
             var rx1 = mcList[i].cx;
            { text: 'Satya Nadella', url: '/wiki/Satya_Nadella', size: 24 },
            var ry1 = mcList[i].cy * ca + mcList[i].cz * (-sa);
            { text: 'Tim Cook', url: '/wiki/Tim_Cook', size: 22 },
            var rz1 = mcList[i].cy * sa + mcList[i].cz * ca;
            { text: 'Elon Musk', url: '/wiki/Elon_Musk', size: 26 },
           
            { text: 'Mark Zuckerberg', url: '/wiki/Mark_Zuckerberg', size: 20 },
            var rx2 = rx1 * cb + rz1 * sb;
            { text: 'Sundar Pichai', url: '/wiki/Sundar_Pichai', size: 20 },
            var ry2 = ry1;
            { text: 'Andy Jassy', url: '/wiki/Andy_Jassy', size: 18 },
            var rz2 = rx1 * (-sb) + rz1 * cb;
            { text: 'Jensen Huang', url: '/wiki/Jensen_Huang', size: 22 },
           
            { text: 'Lisa Su', url: '/wiki/Lisa_Su', size: 18 },
            var rx3 = rx2 * cc + ry2 * (-sc);
            { text: 'Mary Barra', url: '/wiki/Mary_Barra', size: 18 },
            var ry3 = rx2 * sc + ry2 * cc;
            { text: 'Jamie Dimon', url: '/wiki/Jamie_Dimon', size: 18 },
            var rz3 = rz2;
            { text: 'Microsoft', url: '/wiki/Microsoft', size: 16 },
           
            { text: 'Apple', url: '/wiki/Apple_Inc.', size: 16 },
            mcList[i].cx = rx3;
            { text: 'Amazon', url: '/wiki/Amazon', size: 16 },
            mcList[i].cy = ry3;
             { text: 'Google', url: '/wiki/Google', size: 16 },
            mcList[i].cz = rz3;
            { text: 'Tesla', url: '/wiki/Tesla', size: 16 },
           
            { text: 'Leadership', url: '/wiki/Category:Chief_executive_officers', size: 14 },
             var per = size / (size + rz3);
            { text: 'Innovation', url: '/wiki/Category:Business_strategies', size: 14 },
              
            { text: 'Technology', url: '/wiki/Category:Companies', size: 14 },
            mcList[i].x = rx3 * per;
            { text: 'Strategy', url: '/wiki/Category:Business_strategies', size: 14 },
             mcList[i].y = ry3 * per;
            { text: 'Cloud Computing', url: '/wiki/Category:Industry_analysis', size: 14 }
             mcList[i].scale = per;
        ];
             mcList[i].alpha = per;
 
             mcList[i].alpha = (mcList[i].alpha - 0.6) * (10 / 6);
        // Initialize 3D positions
        var radius = 180;
        var dtr = Math.PI / 180;
        var mcList = [];
        var lasta = 1;
        var lastb = 1;
        var tspeed = 0.5;
        var size = 250;
        var mouseX = 0;
        var mouseY = 0;
        var active = false;
 
        // Build tag objects
        for (var i = 0; i < tags.length; i++) {
             var 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);
         }
         }
 
          
         var sa, ca, sb, cb, sc, cc;
         doPosition();
 
        depthSort();
         function sineCosine(a, b, c) {
    }
            sa = Math.sin(a * dtr);
   
            ca = Math.cos(a * dtr);
    // Event handlers
            sb = Math.sin(b * dtr);
    canvas.onmouseover = function() {
            cb = Math.cos(b * dtr);
        active = true;
            sc = Math.sin(c * dtr);
    };
            cc = Math.cos(c * dtr);
   
        }
    canvas.onmouseout = function() {
 
        active = false;
        function positionAll() {
    };
            var phi = 0;
   
            var theta = 0;
    canvas.onmousemove = function(ev) {
            var max = mcList.length;
        var rect = canvas.getBoundingClientRect();
 
        mouseX = ev.clientX - rect.left - width / 2;
            for (var i = 0; i < max; i++) {
        mouseY = ev.clientY - rect.top - height / 2;
                phi = Math.acos(-1 + (2 * i + 1) / max);
    };
                theta = Math.sqrt(max * Math.PI) * phi;
   
 
    canvas.onclick = function(ev) {
                mcList[i].cx = radius * Math.cos(theta) * Math.sin(phi);
        var rect = canvas.getBoundingClientRect();
                mcList[i].cy = radius * Math.sin(theta) * Math.sin(phi);
        var mx = ev.clientX - rect.left;
                mcList[i].cz = radius * Math.cos(phi);
        var my = ev.clientY - rect.top;
            }
          
         }
         for (var i = 0; i < mcList.length; i++) {
 
            var tag = mcList[i];
         function doPosition() {
            var dx = mx - tag.cx;
            ctx.clearRect(0, 0, width, height);
            var dy = my - tag.cy;
 
            var dist = Math.sqrt(dx * dx + dy * dy);
            for (var i = 0; i < mcList.length; i++) {
           
                var tag = mcList[i];
            if (dist < 50) {
                var x = tag.x + width / 2;
                 window.location.href = tag.url;
                var y = tag.y + height / 2;
                 break;
 
                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;
             }
             }
         }
         }
    };
   
    canvas.style.cursor = 'pointer';
   
    // Initialize
    sineCosine(0, 0, 0);
    positionAll();
    setInterval(update, 30);
   
    console.log('[TagCloud] Successfully initialized! Animation started.');
}


        function depthSort() {
// Try multiple initialization methods
            mcList.sort(function(a, b) {
if (document.readyState === 'complete') {
                return (b.cz - a.cz);
    initCEOTagCloud();
            });
} else if (document.readyState === 'interactive') {
        }
    setTimeout(initCEOTagCloud, 100);
 
} else {
        function update() {
    if (window.addEventListener) {
            var a, b;
        window.addEventListener('load', initCEOTagCloud);
 
         document.addEventListener('DOMContentLoaded', function() {
            if (active) {
            setTimeout(initCEOTagCloud, 100);
                a = (-Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
         });
                b = (Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
     } else if (window.attachEvent) {
            } else {
         window.attachEvent('onload', initCEOTagCloud);
                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();
        }
 
        // Event handlers
        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;
                }
            }
         };
 
        canvas.style.cursor = 'pointer';
 
        // Initialize
        sineCosine(0, 0, 0);
        positionAll();
        setInterval(update, 30);
 
         console.log('3D tag cloud initialized successfully!');
     }
 
    // Try to initialize immediately
    if (document.readyState === 'complete') {
        initTagCloud();
    } else {
        // Wait for window load
         window.addEventListener('load', initTagCloud);
     }
     }
})();
}

Revision as of 10:45, 20 October 2025

/**
 * Add statistics banner to account creation page
 */
(function() {
    // Only run on Special:CreateAccount page
    if (typeof mw !== 'undefined' && mw.config && mw.config.get('wgCanonicalSpecialPageName') !== 'CreateAccount') {
        return;
    }

    if (typeof mw !== 'undefined' && mw.Api && typeof $ !== 'undefined') {
        // 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
 */
function initCEOTagCloud() {
    'use strict';
    
    console.log('[TagCloud] Script loaded');
    
    // Check if we're on Main Page
    if (typeof mw !== 'undefined' && mw.config) {
        var pageName = mw.config.get('wgPageName');
        console.log('[TagCloud] Page name:', pageName);
        if (pageName !== 'Main_Page') {
            console.log('[TagCloud] Not Main Page, exiting');
            return;
        }
    }
    
    var canvas = document.getElementById('tagcanvas');
    if (!canvas) {
        console.log('[TagCloud] Canvas element not found');
        return;
    }
    
    console.log('[TagCloud] Canvas found, initializing...');
    
    // Hide the fallback list
    var ul = canvas.querySelector('ul');
    if (ul) {
        ul.style.display = 'none';
        console.log('[TagCloud] Fallback list hidden');
    }
    
    var ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error('[TagCloud] Could not get 2D context');
        return;
    }
    
    var width = canvas.width;
    var height = canvas.height;
    
    console.log('[TagCloud] Canvas size:', width, 'x', 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 tspeed = 0.5;
    var size = 250;
    var mouseX = 0;
    var mouseY = 0;
    var active = false;
    
    // Build tag objects
    for (var i = 0; i < tags.length; i++) {
        var 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);
    }
    
    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);
    }
    
    function positionAll() {
        var phi = 0;
        var theta = 0;
        var max = mcList.length;
        
        for (var 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);
        }
    }
    
    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;
        }
    }
    
    function depthSort() {
        mcList.sort(function(a, b) {
            return (b.cz - a.cz);
        });
    }
    
    function update() {
        var a, 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();
    }
    
    // Event handlers
    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;
            }
        }
    };
    
    canvas.style.cursor = 'pointer';
    
    // Initialize
    sineCosine(0, 0, 0);
    positionAll();
    setInterval(update, 30);
    
    console.log('[TagCloud] Successfully initialized! Animation started.');
}

// Try multiple initialization methods
if (document.readyState === 'complete') {
    initCEOTagCloud();
} else if (document.readyState === 'interactive') {
    setTimeout(initCEOTagCloud, 100);
} else {
    if (window.addEventListener) {
        window.addEventListener('load', initCEOTagCloud);
        document.addEventListener('DOMContentLoaded', function() {
            setTimeout(initCEOTagCloud, 100);
        });
    } else if (window.attachEvent) {
        window.attachEvent('onload', initCEOTagCloud);
    }
}